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