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