"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "less-424/opttbl.c" of archive less-424.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*
    2  * Copyright (C) 1984-2008  Mark Nudelman
    3  *
    4  * You may distribute under the terms of either the GNU General Public
    5  * License or the Less License, as specified in the README file.
    6  *
    7  * For more information about less, or for information on how to
    8  * contact the author, see the README file.
    9  */
   10 
   11 
   12 /*
   13  * The option table.
   14  */
   15 
   16 #include "less.h"
   17 #include "option.h"
   18 
   19 /*
   20  * Variables controlled by command line options.
   21  */
   22 public int quiet;		/* Should we suppress the audible bell? */
   23 public int how_search;		/* Where should forward searches start? */
   24 public int top_scroll;		/* Repaint screen from top?
   25 				   (alternative is scroll from bottom) */
   26 public int pr_type;		/* Type of prompt (short, medium, long) */
   27 public int bs_mode;		/* How to process backspaces */
   28 public int know_dumb;		/* Don't complain about dumb terminals */
   29 public int quit_at_eof;		/* Quit after hitting end of file twice */
   30 public int quit_if_one_screen;	/* Quit if EOF on first screen */
   31 public int squeeze;		/* Squeeze multiple blank lines into one */
   32 public int tabstop;		/* Tab settings */
   33 public int back_scroll;		/* Repaint screen on backwards movement */
   34 public int forw_scroll;		/* Repaint screen on forward movement */
   35 public int caseless;		/* Do "caseless" searches */
   36 public int linenums;		/* Use line numbers */
   37 public int autobuf;		/* Automatically allocate buffers as needed */
   38 public int bufspace;		/* Max buffer space per file (K) */
   39 public int ctldisp;		/* Send control chars to screen untranslated */
   40 public int force_open;		/* Open the file even if not regular file */
   41 public int swindow;		/* Size of scrolling window */
   42 public int jump_sline;		/* Screen line of "jump target" */
   43 public long jump_sline_fraction = -1;
   44 public int chopline;		/* Truncate displayed lines at screen width */
   45 public int no_init;		/* Disable sending ti/te termcap strings */
   46 public int no_keypad;		/* Disable sending ks/ke termcap strings */
   47 public int twiddle;             /* Show tildes after EOF */
   48 public int show_attn;		/* Hilite first unread line */
   49 public int shift_count;		/* Number of positions to shift horizontally */
   50 public int status_col;		/* Display a status column */
   51 public int use_lessopen;	/* Use the LESSOPEN filter */
   52 public int quit_on_intr;	/* Quit on interrupt */
   53 public int follow_mode;		/* F cmd Follows file desc or file name? */
   54 public int oldbot;		/* Old bottom of screen behavior {{REMOVE}} */
   55 #if HILITE_SEARCH
   56 public int hilite_search;	/* Highlight matched search patterns? */
   57 #endif
   58 
   59 public int less_is_more = 0;	/* Make compatible with POSIX more */
   60 
   61 /*
   62  * Long option names.
   63  */
   64 static struct optname a_optname      = { "search-skip-screen",   NULL };
   65 static struct optname b_optname      = { "buffers",              NULL };
   66 static struct optname B__optname     = { "auto-buffers",         NULL };
   67 static struct optname c_optname      = { "clear-screen",         NULL };
   68 static struct optname d_optname      = { "dumb",                 NULL };
   69 #if MSDOS_COMPILER
   70 static struct optname D__optname     = { "color",                NULL };
   71 #endif
   72 static struct optname e_optname      = { "quit-at-eof",          NULL };
   73 static struct optname f_optname      = { "force",                NULL };
   74 static struct optname F__optname     = { "quit-if-one-screen",   NULL };
   75 #if HILITE_SEARCH
   76 static struct optname g_optname      = { "hilite-search",        NULL };
   77 #endif
   78 static struct optname h_optname      = { "max-back-scroll",      NULL };
   79 static struct optname i_optname      = { "ignore-case",          NULL };
   80 static struct optname j_optname      = { "jump-target",          NULL };
   81 static struct optname J__optname     = { "status-column",        NULL };
   82 #if USERFILE
   83 static struct optname k_optname      = { "lesskey-file",         NULL };
   84 #endif
   85 static struct optname K__optname     = { "quit-on-intr",         NULL };
   86 static struct optname L__optname     = { "no-lessopen",          NULL };
   87 static struct optname m_optname      = { "long-prompt",          NULL };
   88 static struct optname n_optname      = { "line-numbers",         NULL };
   89 #if LOGFILE
   90 static struct optname o_optname      = { "log-file",             NULL };
   91 static struct optname O__optname     = { "LOG-FILE",             NULL };
   92 #endif
   93 static struct optname p_optname      = { "pattern",              NULL };
   94 static struct optname P__optname     = { "prompt",               NULL };
   95 static struct optname q2_optname     = { "silent",               NULL };
   96 static struct optname q_optname      = { "quiet",                &q2_optname };
   97 static struct optname r_optname      = { "raw-control-chars",    NULL };
   98 static struct optname s_optname      = { "squeeze-blank-lines",  NULL };
   99 static struct optname S__optname     = { "chop-long-lines",      NULL };
  100 #if TAGS
  101 static struct optname t_optname      = { "tag",                  NULL };
  102 static struct optname T__optname     = { "tag-file",             NULL };
  103 #endif
  104 static struct optname u_optname      = { "underline-special",    NULL };
  105 static struct optname V__optname     = { "version",              NULL };
  106 static struct optname w_optname      = { "hilite-unread",        NULL };
  107 static struct optname x_optname      = { "tabs",                 NULL };
  108 static struct optname X__optname     = { "no-init",              NULL };
  109 static struct optname y_optname      = { "max-forw-scroll",      NULL };
  110 static struct optname z_optname      = { "window",               NULL };
  111 static struct optname quote_optname  = { "quotes",               NULL };
  112 static struct optname tilde_optname  = { "tilde",                NULL };
  113 static struct optname query_optname  = { "help",                 NULL };
  114 static struct optname pound_optname  = { "shift",                NULL };
  115 static struct optname keypad_optname = { "no-keypad",            NULL };
  116 static struct optname oldbot_optname = { "old-bot",              NULL };
  117 static struct optname follow_optname = { "follow-name",          NULL };
  118 
  119 
  120 /*
  121  * Table of all options and their semantics.
  122  *
  123  * For BOOL and TRIPLE options, odesc[0], odesc[1], odesc[2] are
  124  * the description of the option when set to 0, 1 or 2, respectively.
  125  * For NUMBER options, odesc[0] is the prompt to use when entering
  126  * a new value, and odesc[1] is the description, which should contain
  127  * one %d which is replaced by the value of the number.
  128  * For STRING options, odesc[0] is the prompt to use when entering
  129  * a new value, and odesc[1], if not NULL, is the set of characters
  130  * that are valid in the string.
  131  */
  132 static struct loption option[] =
  133 {
  134 	{ 'a', &a_optname,
  135 		BOOL, OPT_OFF, &how_search, NULL,
  136 		{
  137 			"Search includes displayed screen",
  138 			"Search skips displayed screen",
  139 			NULL
  140 		}
  141 	},
  142 
  143 	{ 'b', &b_optname,
  144 		NUMBER|INIT_HANDLER, 64, &bufspace, opt_b,
  145 		{
  146 			"Max buffer space per file (K): ",
  147 			"Max buffer space per file: %dK",
  148 			NULL
  149 		}
  150 	},
  151 	{ 'B', &B__optname,
  152 		BOOL, OPT_ON, &autobuf, NULL,
  153 		{
  154 			"Don't automatically allocate buffers",
  155 			"Automatically allocate buffers when needed",
  156 			NULL
  157 		}
  158 	},
  159 	{ 'c', &c_optname,
  160 		TRIPLE, OPT_OFF, &top_scroll, NULL,
  161 		{
  162 			"Repaint by scrolling from bottom of screen",
  163 			"Repaint by painting from top of screen",
  164 			"Repaint by painting from top of screen"
  165 		}
  166 	},
  167 	{ 'd', &d_optname,
  168 		BOOL|NO_TOGGLE, OPT_OFF, &know_dumb, NULL,
  169 		{
  170 			"Assume intelligent terminal",
  171 			"Assume dumb terminal",
  172 			NULL
  173 		}
  174 	},
  175 #if MSDOS_COMPILER
  176 	{ 'D', &D__optname,
  177 		STRING|REPAINT|NO_QUERY, 0, NULL, opt_D,
  178 		{
  179 			"color desc: ",
  180 			"Ddknsu0123456789.",
  181 			NULL
  182 		}
  183 	},
  184 #endif
  185 	{ 'e', &e_optname,
  186 		TRIPLE, OPT_OFF, &quit_at_eof, NULL,
  187 		{
  188 			"Don't quit at end-of-file",
  189 			"Quit at end-of-file",
  190 			"Quit immediately at end-of-file"
  191 		}
  192 	},
  193 	{ 'f', &f_optname,
  194 		BOOL, OPT_OFF, &force_open, NULL,
  195 		{
  196 			"Open only regular files",
  197 			"Open even non-regular files",
  198 			NULL
  199 		}
  200 	},
  201 	{ 'F', &F__optname,
  202 		BOOL, OPT_OFF, &quit_if_one_screen, NULL,
  203 		{
  204 			"Don't quit if end-of-file on first screen",
  205 			"Quit if end-of-file on first screen",
  206 			NULL
  207 		}
  208 	},
  209 #if HILITE_SEARCH
  210 	{ 'g', &g_optname,
  211 		TRIPLE|HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL,
  212 		{
  213 			"Don't highlight search matches",
  214 			"Highlight matches for previous search only",
  215 			"Highlight all matches for previous search pattern",
  216 		}
  217 	},
  218 #endif
  219 	{ 'h', &h_optname,
  220 		NUMBER, -1, &back_scroll, NULL,
  221 		{
  222 			"Backwards scroll limit: ",
  223 			"Backwards scroll limit is %d lines",
  224 			NULL
  225 		}
  226 	},
  227 	{ 'i', &i_optname,
  228 		TRIPLE|HL_REPAINT, OPT_OFF, &caseless, opt_i,
  229 		{
  230 			"Case is significant in searches",
  231 			"Ignore case in searches",
  232 			"Ignore case in searches and in patterns"
  233 		}
  234 	},
  235 	{ 'j', &j_optname,
  236 		STRING, 0, NULL, opt_j,
  237 		{
  238 			"Target line: ",
  239 			"0123456789.",
  240 			NULL
  241 		}
  242 	},
  243 	{ 'J', &J__optname,
  244 		BOOL|REPAINT, OPT_OFF, &status_col, NULL,
  245 		{
  246 			"Don't display a status column",
  247 			"Display a status column",
  248 			NULL
  249 		}
  250 	},
  251 #if USERFILE
  252 	{ 'k', &k_optname,
  253 		STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k,
  254 		{ NULL, NULL, NULL }
  255 	},
  256 #endif
  257 	{ 'K', &K__optname,
  258 		BOOL, OPT_OFF, &quit_on_intr, NULL,
  259 		{
  260 			"Interrupt (ctrl-C) returns to prompt",
  261 			"Interrupt (ctrl-C) exits less",
  262 			NULL
  263 		}
  264 	},
  265 	{ 'l', NULL,
  266 		STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_l,
  267 		{ NULL, NULL, NULL }
  268 	},
  269 	{ 'L', &L__optname,
  270 		BOOL, OPT_ON, &use_lessopen, NULL,
  271 		{
  272 			"Don't use the LESSOPEN filter",
  273 			"Use the LESSOPEN filter",
  274 			NULL
  275 		}
  276 	},
  277 	{ 'm', &m_optname,
  278 		TRIPLE, OPT_OFF, &pr_type, NULL,
  279 		{
  280 			"Short prompt",
  281 			"Medium prompt",
  282 			"Long prompt"
  283 		}
  284 	},
  285 	{ 'n', &n_optname,
  286 		TRIPLE|REPAINT, OPT_ON, &linenums, NULL,
  287 		{
  288 			"Don't use line numbers",
  289 			"Use line numbers",
  290 			"Constantly display line numbers"
  291 		}
  292 	},
  293 #if LOGFILE
  294 	{ 'o', &o_optname,
  295 		STRING, 0, NULL, opt_o,
  296 		{ "log file: ", NULL, NULL }
  297 	},
  298 	{ 'O', &O__optname,
  299 		STRING, 0, NULL, opt__O,
  300 		{ "Log file: ", NULL, NULL }
  301 	},
  302 #endif
  303 	{ 'p', &p_optname,
  304 		STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_p,
  305 		{ NULL, NULL, NULL }
  306 	},
  307 	{ 'P', &P__optname,
  308 		STRING, 0, NULL, opt__P,
  309 		{ "prompt: ", NULL, NULL }
  310 	},
  311 	{ 'q', &q_optname,
  312 		TRIPLE, OPT_OFF, &quiet, NULL,
  313 		{
  314 			"Ring the bell for errors AND at eof/bof",
  315 			"Ring the bell for errors but not at eof/bof",
  316 			"Never ring the bell"
  317 		}
  318 	},
  319 	{ 'r', &r_optname,
  320 		TRIPLE|REPAINT, OPT_OFF, &ctldisp, NULL,
  321 		{
  322 			"Display control characters as ^X",
  323 			"Display control characters directly",
  324 			"Display control characters directly, processing ANSI sequences"
  325 		}
  326 	},
  327 	{ 's', &s_optname,
  328 		BOOL|REPAINT, OPT_OFF, &squeeze, NULL,
  329 		{
  330 			"Display all blank lines",
  331 			"Squeeze multiple blank lines",
  332 			NULL
  333 		}
  334 	},
  335 	{ 'S', &S__optname,
  336 		BOOL|REPAINT, OPT_OFF, &chopline, NULL,
  337 		{
  338 			"Fold long lines",
  339 			"Chop long lines",
  340 			NULL
  341 		}
  342 	},
  343 #if TAGS
  344 	{ 't', &t_optname,
  345 		STRING|NO_QUERY, 0, NULL, opt_t,
  346 		{ "tag: ", NULL, NULL }
  347 	},
  348 	{ 'T', &T__optname,
  349 		STRING, 0, NULL, opt__T,
  350 		{ "tags file: ", NULL, NULL }
  351 	},
  352 #endif
  353 	{ 'u', &u_optname,
  354 		TRIPLE|REPAINT, OPT_OFF, &bs_mode, NULL,
  355 		{
  356 			"Display underlined text in underline mode",
  357 			"Backspaces cause overstrike",
  358 			"Print backspace as ^H"
  359 		}
  360 	},
  361 	{ 'V', &V__optname,
  362 		NOVAR, 0, NULL, opt__V,
  363 		{ NULL, NULL, NULL }
  364 	},
  365 	{ 'w', &w_optname,
  366 		TRIPLE|REPAINT, OPT_OFF, &show_attn, NULL,
  367 		{
  368 			"Don't highlight first unread line",
  369 			"Highlight first unread line after forward-screen",
  370 			"Highlight first unread line after any forward movement",
  371 		}
  372 	},
  373 	{ 'x', &x_optname,
  374 		STRING|REPAINT, 0, NULL, opt_x,
  375 		{
  376 			"Tab stops: ",
  377 			"0123456789,",
  378 			NULL
  379 		}
  380 	},
  381 	{ 'X', &X__optname,
  382 		BOOL|NO_TOGGLE, OPT_OFF, &no_init, NULL,
  383 		{
  384 			"Send init/deinit strings to terminal",
  385 			"Don't use init/deinit strings",
  386 			NULL
  387 		}
  388 	},
  389 	{ 'y', &y_optname,
  390 		NUMBER, -1, &forw_scroll, NULL,
  391 		{
  392 			"Forward scroll limit: ",
  393 			"Forward scroll limit is %d lines",
  394 			NULL
  395 		}
  396 	},
  397 	{ 'z', &z_optname,
  398 		NUMBER, -1, &swindow, NULL,
  399 		{
  400 			"Scroll window size: ",
  401 			"Scroll window size is %d lines",
  402 			NULL
  403 		}
  404 	},
  405 	{ '"', &quote_optname,
  406 		STRING, 0, NULL, opt_quote,
  407 		{ "quotes: ", NULL, NULL }
  408 	},
  409 	{ '~', &tilde_optname,
  410 		BOOL|REPAINT, OPT_ON, &twiddle, NULL,
  411 		{
  412 			"Don't show tildes after end of file",
  413 			"Show tildes after end of file",
  414 			NULL
  415 		}
  416 	},
  417 	{ '?', &query_optname,
  418 		NOVAR, 0, NULL, opt_query,
  419 		{ NULL, NULL, NULL }
  420 	},
  421 	{ '#', &pound_optname,
  422 		NUMBER, 0, &shift_count, NULL,
  423 		{
  424 			"Horizontal shift: ",
  425 			"Horizontal shift %d positions",
  426 			NULL
  427 		}
  428 	},
  429 	{ '.', &keypad_optname,
  430 		BOOL|NO_TOGGLE, OPT_OFF, &no_keypad, NULL,
  431 		{
  432 			"Use keypad mode",
  433 			"Don't use keypad mode",
  434 			NULL
  435 		}
  436 	},
  437 	{ '.', &oldbot_optname,
  438 		BOOL, OPT_OFF, &oldbot, NULL,
  439 		{
  440 			"Use new bottom of screen behavior",
  441 			"Use old bottom of screen behavior",
  442 			NULL
  443 		}
  444 	},
  445 	{ '.', &follow_optname,
  446 		BOOL, FOLLOW_DESC, &follow_mode, NULL,
  447 		{
  448 			"F command Follows file descriptor",
  449 			"F command Follows file name",
  450 			NULL
  451 		}
  452 	},
  453 	{ '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } }
  454 };
  455 
  456 
  457 /*
  458  * Initialize each option to its default value.
  459  */
  460 	public void
  461 init_option()
  462 {
  463 	register struct loption *o;
  464 	char *p;
  465 
  466 	p = lgetenv("LESS_IS_MORE");
  467 	if (p != NULL && *p != '\0')
  468 		less_is_more = 1;
  469 
  470 	for (o = option;  o->oletter != '\0';  o++)
  471 	{
  472 		/*
  473 		 * Set each variable to its default.
  474 		 */
  475 		if (o->ovar != NULL)
  476 			*(o->ovar) = o->odefault;
  477 		if (o->otype & INIT_HANDLER)
  478 			(*(o->ofunc))(INIT, (char *) NULL);
  479 	}
  480 }
  481 
  482 /*
  483  * Find an option in the option table, given its option letter.
  484  */
  485 	public struct loption *
  486 findopt(c)
  487 	int c;
  488 {
  489 	register struct loption *o;
  490 
  491 	for (o = option;  o->oletter != '\0';  o++)
  492 	{
  493 		if (o->oletter == c)
  494 			return (o);
  495 		if ((o->otype & TRIPLE) && ASCII_TO_UPPER(o->oletter) == c)
  496 			return (o);
  497 	}
  498 	return (NULL);
  499 }
  500 
  501 /*
  502  *
  503  */
  504 	static int
  505 is_optchar(c)
  506 	char c;
  507 {
  508 	if (ASCII_IS_UPPER(c))
  509 		return 1;
  510 	if (ASCII_IS_LOWER(c))
  511 		return 1;
  512 	if (c == '-')
  513 		return 1;
  514 	return 0;
  515 }
  516 
  517 /*
  518  * Find an option in the option table, given its option name.
  519  * p_optname is the (possibly partial) name to look for, and
  520  * is updated to point after the matched name.
  521  * p_oname if non-NULL is set to point to the full option name.
  522  */
  523 	public struct loption *
  524 findopt_name(p_optname, p_oname, p_err)
  525 	char **p_optname;
  526 	char **p_oname;
  527 	int *p_err;
  528 {
  529 	char *optname = *p_optname;
  530 	register struct loption *o;
  531 	register struct optname *oname;
  532 	register int len;
  533 	int uppercase;
  534 	struct loption *maxo = NULL;
  535 	struct optname *maxoname = NULL;
  536 	int maxlen = 0;
  537 	int ambig = 0;
  538 	int exact = 0;
  539 
  540 	/*
  541 	 * Check all options.
  542 	 */
  543 	for (o = option;  o->oletter != '\0';  o++)
  544 	{
  545 		/*
  546 		 * Check all names for this option.
  547 		 */
  548 		for (oname = o->onames;  oname != NULL;  oname = oname->onext)
  549 		{
  550 			/*
  551 			 * Try normal match first (uppercase == 0),
  552 			 * then, then if it's a TRIPLE option,
  553 			 * try uppercase match (uppercase == 1).
  554 			 */
  555 			for (uppercase = 0;  uppercase <= 1;  uppercase++)
  556 			{
  557 				len = sprefix(optname, oname->oname, uppercase);
  558 				if (len <= 0 || is_optchar(optname[len]))
  559 				{
  560 					/*
  561 					 * We didn't use all of the option name.
  562 					 */
  563 					continue;
  564 				}
  565 				if (!exact && len == maxlen)
  566 					/*
  567 					 * Already had a partial match,
  568 					 * and now there's another one that
  569 					 * matches the same length.
  570 					 */
  571 					ambig = 1;
  572 				else if (len > maxlen)
  573 				{
  574 					/*
  575 					 * Found a better match than
  576 					 * the one we had.
  577 					 */
  578 					maxo = o;
  579 					maxoname = oname;
  580 					maxlen = len;
  581 					ambig = 0;
  582 					exact = (len == (int)strlen(oname->oname));
  583 				}
  584 				if (!(o->otype & TRIPLE))
  585 					break;
  586 			}
  587 		}
  588 	}
  589 	if (ambig)
  590 	{
  591 		/*
  592 		 * Name matched more than one option.
  593 		 */
  594 		if (p_err != NULL)
  595 			*p_err = OPT_AMBIG;
  596 		return (NULL);
  597 	}
  598 	*p_optname = optname + maxlen;
  599 	if (p_oname != NULL)
  600 		*p_oname = maxoname == NULL ? NULL : maxoname->oname;
  601 	return (maxo);
  602 }