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