1 /* 2 * Copyright (C) 1984-2025 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, see the README file. 8 */ 9 10 11 /* 12 * The option table. 13 */ 14 15 #include "less.h" 16 #include "option.h" 17 18 /* 19 * Variables controlled by command line options. 20 */ 21 public int quiet; /* Should we suppress the audible bell? */ 22 public int no_vbell; /* Should we suppress the visual 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 int jump_sline_arg; 44 public long jump_sline_fraction = -1; 45 public int shift_count; /* Number of positions to shift horizontally */ 46 public long shift_count_fraction = -1; 47 public int chopline; /* Truncate displayed lines at screen width */ 48 public int wordwrap; /* Wrap lines at space */ 49 public int no_init; /* Disable sending ti/te termcap strings */ 50 public int no_keypad; /* Disable sending ks/ke termcap strings */ 51 public int twiddle; /* Show tildes after EOF */ 52 public int show_attn; /* Hilite first unread line */ 53 public int status_col; /* Display a status column */ 54 public int use_lessopen; /* Use the LESSOPEN filter */ 55 public int quit_on_intr; /* Quit on interrupt */ 56 public int follow_mode; /* F cmd Follows file desc or file name? */ 57 public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */ 58 public int opt_use_backslash; /* Use backslash escaping in option parsing */ 59 public LWCHAR rscroll_char; /* Char which marks chopped lines with -S */ 60 public int rscroll_attr; /* Attribute of rscroll_char */ 61 public int no_hist_dups; /* Remove dups from history list */ 62 public int mousecap; /* Allow mouse for scrolling */ 63 public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */ 64 public int perma_marks; /* Save marks in history file */ 65 public int linenum_width; /* Width of line numbers */ 66 public int status_col_width; /* Width of status column */ 67 public int incr_search; /* Incremental search */ 68 public int use_color; /* Use UI color */ 69 public int want_filesize; /* Scan to EOF if necessary to get file size */ 70 public int status_line; /* Highlight entire marked lines */ 71 public int header_lines; /* Freeze header lines at top of screen */ 72 public int header_cols; /* Freeze header columns at left of screen */ 73 public int nonum_headers; /* Don't give headers line numbers */ 74 public int nosearch_header_lines = 0; /* Don't search in header lines */ 75 public int nosearch_header_cols = 0; /* Don't search in header columns */ 76 public int redraw_on_quit; /* Redraw last screen after term deinit */ 77 public int def_search_type; /* */ 78 public int exit_F_on_close; /* Exit F command when input closes */ 79 public int modelines; /* Lines to read looking for modelines */ 80 public int show_preproc_error; /* Display msg when preproc exits with error */ 81 public int proc_backspace; /* Special handling of backspace */ 82 public int proc_tab; /* Special handling of tab */ 83 public int proc_return; /* Special handling of carriage return */ 84 public int match_shift; /* Extra horizontal shift on search match */ 85 public int no_paste; /* Don't accept pasted input */ 86 public int no_edit_warn; /* Don't warn when editing a LESSOPENed file */ 87 public int stop_on_form_feed; /* Stop scrolling on a line starting with form feed */ 88 public long match_shift_fraction = NUM_FRAC_DENOM/2; /* 1/2 of screen width */ 89 public char intr_char = CONTROL('X'); /* Char to interrupt reads */ 90 public char *first_cmd_at_prompt = NULL; /* Command to exec before first prompt */ 91 public char *autosave; /* Actions which do autosave of history file */ 92 #if HILITE_SEARCH 93 public int hilite_search; /* Highlight matched search patterns? */ 94 #endif 95 96 public int less_is_more = 0; /* Make compatible with POSIX more */ 97 98 /* 99 * Long option names. 100 */ 101 static struct optname a_optname = { "search-skip-screen", NULL }; 102 static struct optname b_optname = { "buffers", NULL }; 103 static struct optname B__optname = { "auto-buffers", NULL }; 104 static struct optname c_optname = { "clear-screen", NULL }; 105 static struct optname d_optname = { "dumb", NULL }; 106 static struct optname D__optname = { "color", NULL }; 107 static struct optname e_optname = { "quit-at-eof", NULL }; 108 static struct optname f_optname = { "force", NULL }; 109 static struct optname F__optname = { "quit-if-one-screen", NULL }; 110 #if HILITE_SEARCH 111 static struct optname g_optname = { "hilite-search", NULL }; 112 #endif 113 static struct optname h_optname = { "max-back-scroll", NULL }; 114 static struct optname i_optname = { "ignore-case", NULL }; 115 static struct optname j_optname = { "jump-target", NULL }; 116 static struct optname J__optname = { "status-column", NULL }; 117 #if USERFILE 118 static struct optname k_optname = { "lesskey-file", NULL }; 119 #if HAVE_LESSKEYSRC 120 static struct optname ks_optname = { "lesskey-src", NULL }; 121 static struct optname kc_optname = { "lesskey-content", NULL }; 122 #endif /* HAVE_LESSKEYSRC */ 123 #endif 124 static struct optname K__optname = { "quit-on-intr", NULL }; 125 static struct optname L__optname = { "no-lessopen", NULL }; 126 static struct optname m_optname = { "long-prompt", NULL }; 127 static struct optname n_optname = { "line-numbers", NULL }; 128 #if LOGFILE 129 static struct optname o_optname = { "log-file", NULL }; 130 static struct optname O__optname = { "LOG-FILE", NULL }; 131 #endif 132 static struct optname p_optname = { "pattern", NULL }; 133 static struct optname P__optname = { "prompt", NULL }; 134 static struct optname q2_optname = { "silent", NULL }; 135 static struct optname q_optname = { "quiet", &q2_optname }; 136 static struct optname r_optname = { "raw-control-chars", NULL }; 137 static struct optname s_optname = { "squeeze-blank-lines", NULL }; 138 static struct optname S__optname = { "chop-long-lines", NULL }; 139 #if TAGS 140 static struct optname t_optname = { "tag", NULL }; 141 static struct optname T__optname = { "tag-file", NULL }; 142 #endif 143 static struct optname u_optname = { "underline-special", NULL }; 144 static struct optname V__optname = { "version", NULL }; 145 static struct optname w_optname = { "hilite-unread", NULL }; 146 static struct optname x_optname = { "tabs", NULL }; 147 static struct optname X__optname = { "no-init", NULL }; 148 static struct optname y_optname = { "max-forw-scroll", NULL }; 149 static struct optname z_optname = { "window", NULL }; 150 static struct optname quote_optname = { "quotes", NULL }; 151 static struct optname tilde_optname = { "tilde", NULL }; 152 static struct optname query_optname = { "help", NULL }; 153 static struct optname pound_optname = { "shift", NULL }; 154 static struct optname keypad_optname = { "no-keypad", NULL }; 155 static struct optname oldbot_optname = { "old-bot", NULL }; 156 static struct optname follow_optname = { "follow-name", NULL }; 157 static struct optname use_backslash_optname = { "use-backslash", NULL }; 158 static struct optname rscroll_optname = { "rscroll", NULL }; 159 static struct optname nohistdups_optname = { "no-histdups", NULL }; 160 static struct optname mousecap_optname = { "mouse", NULL }; 161 static struct optname wheel_lines_optname = { "wheel-lines", NULL }; 162 static struct optname perma_marks_optname = { "save-marks", NULL }; 163 static struct optname linenum_width_optname = { "line-num-width", NULL }; 164 static struct optname status_col_width_optname = { "status-col-width", NULL }; 165 static struct optname incr_search_optname = { "incsearch", NULL }; 166 static struct optname use_color_optname = { "use-color", NULL }; 167 static struct optname want_filesize_optname = { "file-size", NULL }; 168 static struct optname status_line_optname = { "status-line", NULL }; 169 static struct optname header_optname = { "header", NULL }; 170 static struct optname no_paste_optname = { "no-paste", NULL }; 171 static struct optname form_feed_optname = { "form-feed", NULL }; 172 static struct optname no_edit_warn_optname2 = { "no-warn-edit", NULL }; 173 static struct optname no_edit_warn_optname = { "no-edit-warn", &no_edit_warn_optname2 }; 174 static struct optname nonum_headers_optname = { "no-number-headers", NULL }; 175 static struct optname nosearch_headers_optname = { "no-search-headers", NULL }; 176 static struct optname nosearch_header_lines_optname = { "no-search-header-lines", NULL }; 177 static struct optname nosearch_header_cols_optname = { "no-search-header-columns", NULL }; 178 static struct optname redraw_on_quit_optname = { "redraw-on-quit", NULL }; 179 static struct optname search_type_optname = { "search-options", NULL }; 180 static struct optname exit_F_on_close_optname = { "exit-follow-on-close", NULL }; 181 static struct optname modelines_optname = { "modelines", NULL }; 182 static struct optname no_vbell_optname = { "no-vbell", NULL }; 183 static struct optname intr_optname = { "intr", NULL }; 184 static struct optname wordwrap_optname = { "wordwrap", NULL }; 185 static struct optname show_preproc_error_optname = { "show-preproc-errors", NULL }; 186 static struct optname proc_backspace_optname = { "proc-backspace", NULL }; 187 static struct optname proc_tab_optname = { "proc-tab", NULL }; 188 static struct optname proc_return_optname = { "proc-return", NULL }; 189 static struct optname match_shift_optname = { "match-shift", NULL }; 190 static struct optname first_cmd_at_prompt_optname = { "cmd", NULL }; 191 static struct optname autosave_optname = { "autosave", NULL }; 192 #if LESSTEST 193 static struct optname ttyin_name_optname = { "tty", NULL }; 194 #endif /*LESSTEST*/ 195 196 197 /* 198 * Table of all options and their semantics. 199 * 200 * For BOOL and TRIPLE options, odesc[0], odesc[1], odesc[2] are 201 * the description of the option when set to 0, 1 or 2, respectively. 202 * For NUMBER options, odesc[0] is the prompt to use when entering 203 * a new value, and odesc[1] is the description, which should contain 204 * one %d which is replaced by the value of the number. 205 * For STRING options, odesc[0] is the prompt to use when entering 206 * a new value, and odesc[1], if not NULL, is the set of characters 207 * that are valid in the string. 208 */ 209 static struct loption option[] = 210 { 211 { 'a', &a_optname, 212 O_TRIPLE, OPT_ONPLUS, &how_search, NULL, 213 { 214 "Search includes displayed screen", 215 "Search skips displayed screen", 216 "Search includes all of displayed screen" 217 } 218 }, 219 220 { 'b', &b_optname, 221 O_NUMBER|O_INIT_HANDLER, 64, &bufspace, opt_b, 222 { 223 "Max buffer space per file (K): ", 224 "Max buffer space per file: %dK", 225 NULL 226 } 227 }, 228 { 'B', &B__optname, 229 O_BOOL, OPT_ON, &autobuf, NULL, 230 { 231 "Don't automatically allocate buffers", 232 "Automatically allocate buffers when needed", 233 NULL 234 } 235 }, 236 { 'c', &c_optname, 237 O_TRIPLE, OPT_OFF, &top_scroll, NULL, 238 { 239 "Repaint by scrolling from bottom of screen", 240 "Repaint by painting from top of screen", 241 "Repaint by painting from top of screen" 242 } 243 }, 244 { 'd', &d_optname, 245 O_BOOL|O_NO_TOGGLE, OPT_OFF, &know_dumb, NULL, 246 { 247 "Assume intelligent terminal", 248 "Assume dumb terminal", 249 NULL 250 } 251 }, 252 { 'D', &D__optname, 253 O_STRING|O_REPAINT|O_NO_QUERY, 0, NULL, opt_D, 254 { "color desc: ", "s", NULL } 255 }, 256 { 'e', &e_optname, 257 O_TRIPLE, OPT_OFF, &quit_at_eof, NULL, 258 { 259 "Don't quit at end-of-file", 260 "Quit at end-of-file", 261 "Quit immediately at end-of-file" 262 } 263 }, 264 { 'f', &f_optname, 265 O_BOOL, OPT_OFF, &force_open, NULL, 266 { 267 "Open only regular files", 268 "Open even non-regular files", 269 NULL 270 } 271 }, 272 { 'F', &F__optname, 273 O_BOOL, OPT_OFF, &quit_if_one_screen, NULL, 274 { 275 "Don't quit if end-of-file on first screen", 276 "Quit if end-of-file on first screen", 277 NULL 278 } 279 }, 280 #if HILITE_SEARCH 281 { 'g', &g_optname, 282 O_TRIPLE|O_HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL, 283 { 284 "Don't highlight search matches", 285 "Highlight matches for previous search only", 286 "Highlight all matches for previous search pattern", 287 } 288 }, 289 #endif 290 { 'h', &h_optname, 291 O_NUMBER, -1, &back_scroll, NULL, 292 { 293 "Backwards scroll limit: ", 294 "Backwards scroll limit is %d lines", 295 NULL 296 } 297 }, 298 { 'i', &i_optname, 299 O_TRIPLE|O_HL_REPAINT, OPT_OFF, &caseless, opt_i, 300 { 301 "Case is significant in searches", 302 "Ignore case in searches", 303 "Ignore case in searches and in patterns" 304 } 305 }, 306 { 'j', &j_optname, 307 O_STRING, 0, NULL, opt_j, 308 { 309 "Target line: ", 310 "-.d", 311 NULL 312 } 313 }, 314 { 'J', &J__optname, 315 O_BOOL|O_REPAINT, OPT_OFF, &status_col, NULL, 316 { 317 "Don't display a status column", 318 "Display a status column", 319 NULL 320 } 321 }, 322 #if USERFILE 323 { 'k', &k_optname, 324 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_k, 325 { NULL, NULL, NULL } 326 }, 327 #if HAVE_LESSKEYSRC 328 { OLETTER_NONE, &kc_optname, 329 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_kc, 330 { NULL, NULL, NULL } 331 }, 332 { OLETTER_NONE, &ks_optname, 333 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_ks, 334 { NULL, NULL, NULL } 335 }, 336 #endif /* HAVE_LESSKEYSRC */ 337 #endif 338 { 'K', &K__optname, 339 O_BOOL, OPT_OFF, &quit_on_intr, NULL, 340 { 341 "Interrupt (ctrl-C) returns to prompt", 342 "Interrupt (ctrl-C) exits less", 343 NULL 344 } 345 }, 346 { 'L', &L__optname, 347 O_BOOL, OPT_ON, &use_lessopen, NULL, 348 { 349 "Don't use the LESSOPEN filter", 350 "Use the LESSOPEN filter", 351 NULL 352 } 353 }, 354 { 'm', &m_optname, 355 O_TRIPLE, OPT_OFF, &pr_type, NULL, 356 { 357 "Short prompt", 358 "Medium prompt", 359 "Long prompt" 360 } 361 }, 362 { 'n', &n_optname, 363 O_TRIPLE|O_REPAINT, OPT_ON, &linenums, NULL, 364 { 365 "Don't use line numbers", 366 "Use line numbers", 367 "Constantly display line numbers" 368 } 369 }, 370 #if LOGFILE 371 { 'o', &o_optname, 372 O_STRING, 0, NULL, opt_o, 373 { "log file: ", NULL, NULL } 374 }, 375 { 'O', &O__optname, 376 O_STRING, 0, NULL, opt__O, 377 { "Log file: ", NULL, NULL } 378 }, 379 #endif 380 { 'p', &p_optname, 381 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_p, 382 { NULL, NULL, NULL } 383 }, 384 { 'P', &P__optname, 385 O_STRING, 0, NULL, opt__P, 386 { "prompt: ", NULL, NULL } 387 }, 388 { 'q', &q_optname, 389 O_TRIPLE, OPT_OFF, &quiet, NULL, 390 { 391 "Ring the bell for errors AND at eof/bof", 392 "Ring the bell for errors but not at eof/bof", 393 "Never ring the bell" 394 } 395 }, 396 { 'r', &r_optname, 397 O_TRIPLE|O_REPAINT, OPT_OFF, &ctldisp, NULL, 398 { 399 "Display control characters as ^X", 400 "Display control characters directly (not recommended)", 401 "Display ANSI sequences directly, other control characters as ^X" 402 } 403 }, 404 { 's', &s_optname, 405 O_BOOL|O_REPAINT, OPT_OFF, &squeeze, NULL, 406 { 407 "Display all blank lines", 408 "Squeeze multiple blank lines", 409 NULL 410 } 411 }, 412 { 'S', &S__optname, 413 O_BOOL|O_REPAINT, OPT_OFF, &chopline, opt__S, 414 { 415 "Fold long lines", 416 "Chop long lines", 417 NULL 418 } 419 }, 420 #if TAGS 421 { 't', &t_optname, 422 O_STRING|O_NO_QUERY, 0, NULL, opt_t, 423 { "tag: ", NULL, NULL } 424 }, 425 { 'T', &T__optname, 426 O_STRING, 0, NULL, opt__T, 427 { "tags file: ", NULL, NULL } 428 }, 429 #endif 430 { 'u', &u_optname, 431 O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &bs_mode, NULL, 432 { 433 "Display underlined text in underline mode", 434 "Backspaces cause overstrike", 435 "Print backspace as ^H" 436 } 437 }, 438 { 'V', &V__optname, 439 O_NOVAR, 0, NULL, opt__V, 440 { NULL, NULL, NULL } 441 }, 442 { 'w', &w_optname, 443 O_TRIPLE|O_REPAINT, OPT_OFF, &show_attn, NULL, 444 { 445 "Don't highlight first unread line", 446 "Highlight first unread line after forward-screen", 447 "Highlight first unread line after any forward movement", 448 } 449 }, 450 { 'x', &x_optname, 451 O_STRING|O_REPAINT, 0, NULL, opt_x, 452 { 453 "Tab stops: ", 454 "d,", 455 NULL 456 } 457 }, 458 { 'X', &X__optname, 459 O_BOOL|O_NO_TOGGLE, OPT_OFF, &no_init, NULL, 460 { 461 "Send init/deinit strings to terminal", 462 "Don't use init/deinit strings", 463 NULL 464 } 465 }, 466 { 'y', &y_optname, 467 O_NUMBER, -1, &forw_scroll, NULL, 468 { 469 "Forward scroll limit: ", 470 "Forward scroll limit is %d lines", 471 NULL 472 } 473 }, 474 { 'z', &z_optname, 475 O_NUMBER, -1, &swindow, NULL, 476 { 477 "Scroll window size: ", 478 "Scroll window size is %d lines", 479 NULL 480 } 481 }, 482 { '"', "e_optname, 483 O_STRING, 0, NULL, opt_quote, 484 { "quotes: ", "s", NULL } 485 }, 486 { '~', &tilde_optname, 487 O_BOOL|O_REPAINT, OPT_ON, &twiddle, NULL, 488 { 489 "Don't show tildes after end of file", 490 "Show tildes after end of file", 491 NULL 492 } 493 }, 494 { '?', &query_optname, 495 O_NOVAR, 0, NULL, opt_query, 496 { NULL, NULL, NULL } 497 }, 498 { '#', £_optname, 499 O_STRING, 0, NULL, opt_shift, 500 { 501 "Horizontal shift: ", 502 ".d", 503 NULL 504 } 505 }, 506 { OLETTER_NONE, &keypad_optname, 507 O_BOOL|O_NO_TOGGLE, OPT_OFF, &no_keypad, NULL, 508 { 509 "Use keypad mode", 510 "Don't use keypad mode", 511 NULL 512 } 513 }, 514 { OLETTER_NONE, &oldbot_optname, 515 O_BOOL, OPT_OFF, &oldbot, NULL, 516 { 517 "Use new bottom of screen behavior", 518 "Use old bottom of screen behavior", 519 NULL 520 } 521 }, 522 { OLETTER_NONE, &follow_optname, 523 O_BOOL, FOLLOW_DESC, &follow_mode, NULL, 524 { 525 "F command follows file descriptor", 526 "F command follows file name", 527 NULL 528 } 529 }, 530 { OLETTER_NONE, &use_backslash_optname, 531 O_BOOL, OPT_OFF, &opt_use_backslash, NULL, 532 { 533 "Use backslash escaping in command line parameters", 534 "Don't use backslash escaping in command line parameters", 535 NULL 536 } 537 }, 538 { OLETTER_NONE, &rscroll_optname, 539 O_STRING|O_REPAINT|O_INIT_HANDLER, 0, NULL, opt_rscroll, 540 { "rscroll character: ", "s", NULL } 541 }, 542 { OLETTER_NONE, &nohistdups_optname, 543 O_BOOL, OPT_OFF, &no_hist_dups, NULL, 544 { 545 "Allow duplicates in history list", 546 "Remove duplicates from history list", 547 NULL 548 } 549 }, 550 { OLETTER_NONE, &mousecap_optname, 551 O_TRIPLE, OPT_OFF, &mousecap, opt_mousecap, 552 { 553 "Ignore mouse input", 554 "Use the mouse for scrolling", 555 "Use the mouse for scrolling (reverse)" 556 } 557 }, 558 { OLETTER_NONE, &wheel_lines_optname, 559 O_NUMBER|O_INIT_HANDLER, 0, &wheel_lines, opt_wheel_lines, 560 { 561 "Lines to scroll on mouse wheel: ", 562 "Scroll %d line(s) on mouse wheel", 563 NULL 564 } 565 }, 566 { OLETTER_NONE, &perma_marks_optname, 567 O_BOOL, OPT_OFF, &perma_marks, NULL, 568 { 569 "Don't save marks in history file", 570 "Save marks in history file", 571 NULL 572 } 573 }, 574 { OLETTER_NONE, &linenum_width_optname, 575 O_NUMBER|O_REPAINT, MIN_LINENUM_WIDTH, &linenum_width, opt_linenum_width, 576 { 577 "Line number width: ", 578 "Line number width is %d chars", 579 NULL 580 } 581 }, 582 { OLETTER_NONE, &status_col_width_optname, 583 O_NUMBER|O_REPAINT, 2, &status_col_width, opt_status_col_width, 584 { 585 "Status column width: ", 586 "Status column width is %d chars", 587 NULL 588 } 589 }, 590 { OLETTER_NONE, &incr_search_optname, 591 O_BOOL, OPT_OFF, &incr_search, NULL, 592 { 593 "Incremental search is off", 594 "Incremental search is on", 595 NULL 596 } 597 }, 598 { OLETTER_NONE, &use_color_optname, 599 O_BOOL|O_REPAINT, OPT_OFF, &use_color, NULL, 600 { 601 "Don't use color", 602 "Use color", 603 NULL 604 } 605 }, 606 { OLETTER_NONE, &want_filesize_optname, 607 O_BOOL|O_REPAINT, OPT_OFF, &want_filesize, opt_filesize, 608 { 609 "Don't get size of each file", 610 "Get size of each file", 611 NULL 612 } 613 }, 614 { OLETTER_NONE, &status_line_optname, 615 O_BOOL|O_REPAINT, OPT_OFF, &status_line, NULL, 616 { 617 "Don't color each line with its status column color", 618 "Color each line with its status column color", 619 NULL 620 } 621 }, 622 { OLETTER_NONE, &header_optname, 623 O_STRING|O_REPAINT, 0, NULL, opt_header, 624 { "Header lines: ", "d,", NULL } 625 }, 626 { OLETTER_NONE, &no_paste_optname, 627 O_BOOL, OPT_OFF, &no_paste, opt_no_paste, 628 { 629 "Accept pasted input", 630 "Ignore pasted input", 631 NULL 632 } 633 }, 634 { OLETTER_NONE, &form_feed_optname, 635 O_BOOL, OPT_OFF, &stop_on_form_feed, NULL, 636 { 637 "Don't stop on form feed", 638 "Stop on form feed", 639 NULL 640 } 641 }, 642 { OLETTER_NONE, &no_edit_warn_optname, 643 O_BOOL, OPT_OFF, &no_edit_warn, NULL, 644 { 645 "Warn when editing a file opened via LESSOPEN", 646 "Don't warn when editing a file opened via LESSOPEN", 647 NULL 648 } 649 }, 650 { OLETTER_NONE, &nonum_headers_optname, 651 O_BOOL|O_REPAINT, 0, &nonum_headers, NULL, 652 { 653 "Number header lines", 654 "Don't number header lines", 655 NULL 656 } 657 }, 658 { OLETTER_NONE, &nosearch_headers_optname, 659 O_BOOL|O_HL_REPAINT, 0, NULL, opt_nosearch_headers, 660 { 661 NULL, NULL, NULL 662 } 663 }, 664 { OLETTER_NONE, &nosearch_header_lines_optname, 665 O_BOOL|O_HL_REPAINT, 0, NULL, opt_nosearch_header_lines, 666 { 667 NULL, NULL, NULL 668 } 669 }, 670 { OLETTER_NONE, &nosearch_header_cols_optname, 671 O_BOOL|O_HL_REPAINT, 0, NULL, opt_nosearch_header_cols, 672 { 673 NULL, NULL, NULL 674 } 675 }, 676 { OLETTER_NONE, &redraw_on_quit_optname, 677 O_BOOL, OPT_OFF, &redraw_on_quit, NULL, 678 { 679 "Don't redraw screen when quitting", 680 "Redraw last screen when quitting", 681 NULL 682 } 683 }, 684 { OLETTER_NONE, &search_type_optname, 685 O_STRING, 0, NULL, opt_search_type, 686 { "Search options: ", "s", NULL } 687 }, 688 { OLETTER_NONE, &exit_F_on_close_optname, 689 O_BOOL, OPT_OFF, &exit_F_on_close, NULL, 690 { 691 "Don't exit F command when input closes", 692 "Exit F command when input closes", 693 NULL 694 } 695 }, 696 { OLETTER_NONE, &no_vbell_optname, 697 O_BOOL, OPT_OFF, &no_vbell, NULL, 698 { 699 "Display visual bell", 700 "Don't display visual bell", 701 NULL 702 } 703 }, 704 { OLETTER_NONE, &modelines_optname, 705 O_NUMBER, 0, &modelines, NULL, 706 { 707 "Lines to read looking for modelines: ", 708 "Read %d lines looking for modelines", 709 NULL 710 } 711 }, 712 { OLETTER_NONE, &intr_optname, 713 O_STRING, 0, NULL, opt_intr, 714 { "interrupt character: ", "s", NULL } 715 }, 716 { OLETTER_NONE, &wordwrap_optname, 717 O_BOOL|O_REPAINT, OPT_OFF, &wordwrap, NULL, 718 { 719 "Wrap lines at any character", 720 "Wrap lines at spaces", 721 NULL 722 } 723 }, 724 { OLETTER_NONE, &show_preproc_error_optname, 725 O_BOOL, OPT_OFF, &show_preproc_error, NULL, 726 { 727 "Don't show error message if preprocessor fails", 728 "Show error message if preprocessor fails", 729 NULL 730 } 731 }, 732 { OLETTER_NONE, &proc_backspace_optname, 733 O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &proc_backspace, NULL, 734 { 735 "Backspace handling is specified by the -U option", 736 "Display underline text in underline mode", 737 "Print backspaces as ^H" 738 } 739 }, 740 { OLETTER_NONE, &proc_tab_optname, 741 O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &proc_tab, NULL, 742 { 743 "Tab handling is specified by the -U option", 744 "Expand tabs to spaces", 745 "Print tabs as ^I" 746 } 747 }, 748 { OLETTER_NONE, &proc_return_optname, 749 O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &proc_return, NULL, 750 { 751 "Carriage return handling is specified by the -U option", 752 "Delete carriage return before newline", 753 "Print carriage return as ^M" 754 } 755 }, 756 { OLETTER_NONE, &first_cmd_at_prompt_optname, 757 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_first_cmd_at_prompt, 758 { NULL, NULL, NULL } 759 }, 760 { OLETTER_NONE, &match_shift_optname, 761 O_STRING|O_INIT_HANDLER, 0, NULL, opt_match_shift, 762 { 763 "Search match shift: ", 764 ".d", 765 NULL 766 } 767 }, 768 { OLETTER_NONE, &autosave_optname, 769 O_STRING|O_INIT_HANDLER, 0, NULL, opt_autosave, 770 { "Autosave actions: ", "s", NULL } 771 }, 772 #if LESSTEST 773 { OLETTER_NONE, &ttyin_name_optname, 774 O_STRING|O_NO_TOGGLE, 0, NULL, opt_ttyin_name, 775 { 776 NULL, 777 NULL, 778 NULL 779 } 780 }, 781 #endif /*LESSTEST*/ 782 { '\0', NULL, O_NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } } 783 }; 784 785 786 /* 787 * Initialize each option to its default value. 788 */ 789 public void init_option(void) 790 { 791 struct loption *o; 792 constant char *p; 793 794 p = lgetenv("LESS_IS_MORE"); 795 if (!isnullenv(p) && !(p[0] == '0' && p[1] == '\0')) 796 less_is_more = 1; 797 798 for (o = option; o->oletter != '\0'; o++) 799 { 800 /* 801 * Set each variable to its default. 802 */ 803 if (o->ovar != NULL) 804 *(o->ovar) = o->odefault; 805 if (o->otype & O_INIT_HANDLER) 806 (*(o->ofunc))(INIT, (char *) NULL); 807 } 808 } 809 810 /* 811 * Find an option in the option table, given its option letter. 812 */ 813 public struct loption * findopt(int c) 814 { 815 struct loption *o; 816 817 for (o = option; o->oletter != '\0'; o++) 818 { 819 if (o->oletter == c) 820 return (o); 821 if ((o->otype & O_TRIPLE) && ASCII_TO_UPPER(o->oletter) == c) 822 return (o); 823 } 824 return (NULL); 825 } 826 827 /* 828 * 829 */ 830 static lbool is_optchar(char c) 831 { 832 if (ASCII_IS_UPPER(c)) 833 return TRUE; 834 if (ASCII_IS_LOWER(c)) 835 return TRUE; 836 if (c == '-') 837 return TRUE; 838 return FALSE; 839 } 840 841 /* 842 * Find an option in the option table, given its option name. 843 * p_optname is the (possibly partial) name to look for, and 844 * is updated to point after the matched name. 845 * p_oname if non-NULL is set to point to the full option name. 846 */ 847 public struct loption * findopt_name(constant char **p_optname, constant char **p_oname, lbool *p_ambig) 848 { 849 constant char *optname = *p_optname; 850 struct loption *o; 851 struct optname *oname; 852 size_t len; 853 int uppercase; 854 struct loption *maxo = NULL; 855 struct optname *maxoname = NULL; 856 size_t maxlen = 0; 857 lbool ambig = FALSE; 858 lbool exact = FALSE; 859 860 /* 861 * Check all options. 862 */ 863 for (o = option; o->oletter != '\0'; o++) 864 { 865 /* 866 * Check all names for this option. 867 */ 868 for (oname = o->onames; oname != NULL; oname = oname->onext) 869 { 870 /* 871 * Try normal match first (uppercase == 0), 872 * then, then if it's a TRIPLE option, 873 * try uppercase match (uppercase == 1). 874 */ 875 for (uppercase = 0; uppercase <= 1; uppercase++) 876 { 877 len = sprefix(optname, oname->oname, uppercase); 878 if (len == 0 || is_optchar(optname[len])) 879 { 880 /* 881 * We didn't use all of the option name. 882 */ 883 continue; 884 } 885 if (!exact && len == maxlen) 886 /* 887 * Already had a partial match, 888 * and now there's another one that 889 * matches the same length. 890 */ 891 ambig = TRUE; 892 else if (len > maxlen) 893 { 894 /* 895 * Found a better match than 896 * the one we had. 897 */ 898 maxo = o; 899 maxoname = oname; 900 maxlen = len; 901 ambig = FALSE; 902 exact = (len == strlen(oname->oname)); 903 } 904 if (!(o->otype & O_TRIPLE)) 905 break; 906 } 907 } 908 } 909 if (p_ambig != NULL) 910 *p_ambig = ambig; 911 if (ambig) 912 { 913 /* 914 * Name matched more than one option. 915 */ 916 return (NULL); 917 } 918 *p_optname = optname + maxlen; 919 if (p_oname != NULL) 920 *p_oname = maxoname == NULL ? NULL : maxoname->oname; 921 return (maxo); 922 } 923 924 /* 925 * Find all toggleable options whose names begin with a specified string. 926 * Return them in a space-separated string. 927 */ 928 public char * findopts_name(constant char *pfx) 929 { 930 constant struct loption *o; 931 constant struct optname *oname; 932 struct xbuffer xbuf; 933 int uppercase; 934 935 xbuf_init(&xbuf); 936 for (o = option; o->oletter != '\0'; o++) 937 { 938 if (o->otype & O_NO_TOGGLE) 939 continue; 940 for (oname = o->onames; oname != NULL; oname = oname->onext) 941 { 942 for (uppercase = 0; uppercase <= 1; uppercase++) 943 { 944 size_t len = sprefix(pfx, oname->oname, uppercase); 945 if (len >= strlen(pfx)) 946 { 947 constant char *np; 948 for (np = oname->oname; *np != '\0'; np++) 949 xbuf_add_char(&xbuf, uppercase && ASCII_IS_LOWER(*np) ? ASCII_TO_UPPER(*np) : *np); 950 xbuf_add_char(&xbuf, ' '); 951 } 952 if (!(o->otype & O_TRIPLE)) 953 break; 954 } 955 } 956 } 957 xbuf_pop(&xbuf); /* remove final space */ 958 xbuf_add_char(&xbuf, '\0'); 959 return (char *) xbuf.data; 960 } 961