1 /* 2 * Copyright (C) 1984-2026 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 hilite_target; /* Hilite target line */ 54 public int status_col; /* Display a status column */ 55 public int use_lessopen; /* Use the LESSOPEN filter */ 56 public int quit_on_intr; /* Quit on interrupt */ 57 public int follow_mode; /* F cmd Follows file desc or file name? */ 58 public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */ 59 public int opt_use_backslash; /* Use backslash escaping in option parsing */ 60 public LWCHAR rscroll_char; /* Char which marks chopped lines with -S */ 61 public int rscroll_attr; /* Attribute of rscroll_char */ 62 public int no_hist_dups; /* Remove dups from history list */ 63 public int emouse; /* Enabled mouse features */ 64 public int mouse_reverse; /* Reverse mouse wheel scrolling direction */ 65 public int xmouse; /* Old --mouse option, replaced by --emouse */ 66 public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */ 67 public int perma_marks; /* Save marks in history file */ 68 public int linenum_width; /* Width of line numbers */ 69 public int status_col_width; /* Width of status column */ 70 public int incr_search; /* Incremental search */ 71 public int use_color; /* Use UI color */ 72 public int want_filesize; /* Scan to EOF if necessary to get file size */ 73 public int status_line; /* Highlight entire marked lines */ 74 public int header_lines; /* Freeze header lines at top of screen */ 75 public int header_cols; /* Freeze header columns at left of screen */ 76 public int nonum_headers; /* Don't give headers line numbers */ 77 public int nosearch_header_lines = 0; /* Don't search in header lines */ 78 public int nosearch_header_cols = 0; /* Don't search in header columns */ 79 public int redraw_on_quit; /* Redraw last screen after term deinit */ 80 public int def_search_type; /* */ 81 public int exit_F_on_close; /* Exit F command when input closes */ 82 public int modelines; /* Lines to read looking for modelines */ 83 public int show_preproc_error; /* Display msg when preproc exits with error */ 84 public int proc_backspace; /* Special handling of backspace */ 85 public int proc_tab; /* Special handling of tab */ 86 public int proc_return; /* Special handling of carriage return */ 87 public int match_shift; /* Extra horizontal shift on search match */ 88 public int no_paste; /* Don't accept pasted input */ 89 public int no_edit_warn; /* Don't warn when editing a LESSOPENed file */ 90 public int stop_on_form_feed; /* Stop scrolling on a line starting with form feed */ 91 public int past_eof; /* Continue scrolling past EOF */ 92 public long match_shift_fraction = NUM_FRAC_DENOM/2; /* 1/2 of screen width */ 93 public char intr_char = CONTROL('X'); /* Char to interrupt reads */ 94 public char *first_cmd_at_prompt = NULL; /* Command to exec before first prompt */ 95 public char *autosave; /* Actions which do autosave of history file */ 96 public char *end_prompt; /* Printed after clearing the prompt */ 97 #if HILITE_SEARCH 98 public int hilite_search; /* Highlight matched search patterns? */ 99 #endif 100 101 public lbool less_is_more = FALSE; /* Make compatible with POSIX more */ 102 103 /* 104 * Long option names. 105 */ 106 static struct optname a_optname = { "search-skip-screen", NULL }; 107 static struct optname b_optname = { "buffers", NULL }; 108 static struct optname B__optname = { "auto-buffers", NULL }; 109 static struct optname c_optname = { "clear-screen", NULL }; 110 static struct optname d_optname = { "dumb", NULL }; 111 static struct optname D__optname = { "color", NULL }; 112 static struct optname e_optname = { "quit-at-eof", NULL }; 113 static struct optname f_optname = { "force", NULL }; 114 static struct optname F__optname = { "quit-if-one-screen", NULL }; 115 #if HILITE_SEARCH 116 static struct optname g_optname = { "hilite-search", NULL }; 117 #endif 118 static struct optname h_optname = { "max-back-scroll", NULL }; 119 static struct optname i_optname = { "ignore-case", NULL }; 120 static struct optname j_optname = { "jump-target", NULL }; 121 static struct optname J__optname = { "status-column", NULL }; 122 #if USERFILE 123 static struct optname k_optname = { "lesskey-file", NULL }; 124 #if HAVE_LESSKEYSRC 125 static struct optname ks_optname = { "lesskey-src", NULL }; 126 static struct optname kc_optname = { "lesskey-content", NULL }; 127 #endif /* HAVE_LESSKEYSRC */ 128 #endif 129 static struct optname K__optname = { "quit-on-intr", NULL }; 130 static struct optname L__optname = { "no-lessopen", NULL }; 131 static struct optname m_optname = { "long-prompt", NULL }; 132 static struct optname n_optname = { "line-numbers", NULL }; 133 #if LOGFILE 134 static struct optname o_optname = { "log-file", NULL }; 135 static struct optname O__optname = { "LOG-FILE", NULL }; 136 #endif 137 static struct optname p_optname = { "pattern", NULL }; 138 static struct optname P__optname = { "prompt", NULL }; 139 static struct optname q2_optname = { "silent", NULL }; 140 static struct optname q_optname = { "quiet", &q2_optname }; 141 static struct optname r_optname = { "raw-control-chars", NULL }; 142 static struct optname s_optname = { "squeeze-blank-lines", NULL }; 143 static struct optname S__optname = { "chop-long-lines", NULL }; 144 #if TAGS 145 static struct optname t_optname = { "tag", NULL }; 146 static struct optname T__optname = { "tag-file", NULL }; 147 #endif 148 static struct optname u_optname = { "underline-special", NULL }; 149 static struct optname V__optname = { "version", NULL }; 150 static struct optname w_optname = { "hilite-unread", NULL }; 151 static struct optname x_optname = { "tabs", NULL }; 152 static struct optname X__optname = { "no-init", NULL }; 153 static struct optname y_optname = { "max-forw-scroll", NULL }; 154 static struct optname z_optname = { "window", NULL }; 155 static struct optname quote_optname = { "quotes", NULL }; 156 static struct optname tilde_optname = { "tilde", NULL }; 157 static struct optname query_optname = { "help", NULL }; 158 static struct optname pound_optname = { "shift", NULL }; 159 static struct optname keypad_optname = { "no-keypad", NULL }; 160 static struct optname oldbot_optname = { "old-bot", NULL }; 161 static struct optname follow_optname = { "follow-name", NULL }; 162 static struct optname use_backslash_optname = { "use-backslash", NULL }; 163 static struct optname rscroll_optname = { "rscroll", NULL }; 164 static struct optname nohistdups_optname = { "no-histdups", NULL }; 165 static struct optname mouse_optname = { "mouse", NULL }; 166 static struct optname emouse_optname = { "emouse", NULL }; 167 static struct optname mouse_reverse_optname = { "rmouse", NULL }; 168 static struct optname wheel_lines_optname = { "wheel-lines", NULL }; 169 static struct optname perma_marks_optname = { "save-marks", NULL }; 170 static struct optname linenum_width_optname = { "line-num-width", NULL }; 171 static struct optname status_col_width_optname = { "status-col-width", NULL }; 172 static struct optname incr_search_optname = { "incsearch", NULL }; 173 static struct optname use_color_optname = { "use-color", NULL }; 174 static struct optname want_filesize_optname = { "file-size", NULL }; 175 static struct optname status_line_optname = { "status-line", NULL }; 176 static struct optname header_optname = { "header", NULL }; 177 static struct optname no_paste_optname = { "no-paste", NULL }; 178 static struct optname form_feed_optname = { "form-feed", NULL }; 179 static struct optname past_eof_optname = { "past-eof", NULL }; 180 static struct optname no_edit_warn_optname2 = { "no-warn-edit", NULL }; 181 static struct optname no_edit_warn_optname = { "no-edit-warn", &no_edit_warn_optname2 }; 182 static struct optname nonum_headers_optname = { "no-number-headers", NULL }; 183 static struct optname nosearch_headers_optname = { "no-search-headers", NULL }; 184 static struct optname nosearch_header_lines_optname = { "no-search-header-lines", NULL }; 185 static struct optname nosearch_header_cols_optname = { "no-search-header-columns", NULL }; 186 static struct optname redraw_on_quit_optname = { "redraw-on-quit", NULL }; 187 static struct optname search_type_optname = { "search-options", NULL }; 188 static struct optname exit_F_on_close_optname = { "exit-follow-on-close", NULL }; 189 static struct optname modelines_optname = { "modelines", NULL }; 190 static struct optname no_vbell_optname = { "no-vbell", NULL }; 191 static struct optname intr_optname = { "intr", NULL }; 192 static struct optname wordwrap_optname = { "wordwrap", NULL }; 193 static struct optname show_preproc_error_optname = { "show-preproc-errors", NULL }; 194 static struct optname proc_backspace_optname = { "proc-backspace", NULL }; 195 static struct optname proc_tab_optname = { "proc-tab", NULL }; 196 static struct optname proc_return_optname = { "proc-return", NULL }; 197 static struct optname match_shift_optname = { "match-shift", NULL }; 198 static struct optname first_cmd_at_prompt_optname = { "cmd", NULL }; 199 static struct optname autosave_optname = { "autosave", NULL }; 200 static struct optname hilite_target_optname = { "hilite-target", NULL }; 201 static struct optname end_prompt_optname = { "end-prompt", NULL }; 202 #if LESSTEST 203 static struct optname ttyin_name_optname = { "tty", NULL }; 204 #endif /*LESSTEST*/ 205 206 207 /* 208 * Table of all options and their semantics. 209 * 210 * For BOOL and TRIPLE options, odesc[0], odesc[1], odesc[2] are 211 * the description of the option when set to 0, 1 or 2, respectively. 212 * For NUMBER options, odesc[0] is the prompt to use when entering 213 * a new value, and odesc[1] is the description, which should contain 214 * one %d which is replaced by the value of the number. 215 * For STRING options, odesc[0] is the prompt to use when entering 216 * a new value, and odesc[1], if not NULL, is a description of the 217 * characters that are valid in the string (see optstring()). 218 */ 219 static struct loption option[] = 220 { 221 { 'a', &a_optname, 222 O_TRIPLE, OPT_ONPLUS, &how_search, NULL, 223 { 224 LM_Search_includes_displayed_screen, 225 LM_Search_skips_displayed_screen, 226 LM_Search_includes_all_of_displayed_screen 227 }, 228 { NULL, NULL, NULL } 229 }, 230 231 { 'b', &b_optname, 232 O_NUMBER|O_INIT_HANDLER, 64, &bufspace, opt_b, 233 { 234 LM_Max_buffer_space_per_file, 235 LM_Max_buffer_space_per_file_X, 236 LM_NULL 237 }, 238 { NULL, NULL, NULL } 239 }, 240 { 'B', &B__optname, 241 O_BOOL, OPT_ON, &autobuf, NULL, 242 { 243 LM_Dont_automatically_allocate_buffers, 244 LM_Automatically_allocate_buffers_when_needed, 245 LM_NULL 246 }, 247 { NULL, NULL, NULL } 248 }, 249 { 'c', &c_optname, 250 O_TRIPLE, OPT_OFF, &top_scroll, NULL, 251 { 252 LM_Repaint_by_scrolling_from_bottom_of_screen, 253 LM_Repaint_by_painting_from_top_of_screen, 254 LM_Repaint_by_painting_from_top_of_screen, 255 }, 256 { NULL, NULL, NULL } 257 }, 258 { 'd', &d_optname, 259 O_BOOL|O_NO_TOGGLE, OPT_OFF, &know_dumb, NULL, 260 { 261 LM_Assume_intelligent_terminal, 262 LM_Assume_dumb_terminal, 263 LM_NULL 264 }, 265 { NULL, NULL, NULL } 266 }, 267 { 'D', &D__optname, 268 O_STRING|O_REPAINT|O_NO_QUERY, 0, NULL, opt_D, 269 { LM_color_desc, LM_s, LM_NULL }, 270 { NULL, NULL, NULL } 271 }, 272 { 'e', &e_optname, 273 O_TRIPLE, OPT_OFF, &quit_at_eof, NULL, 274 { 275 LM_Dont_quit_at_end_of_file, 276 LM_Quit_at_end_of_file, 277 LM_Quit_immediately_at_end_of_file 278 }, 279 { NULL, NULL, NULL } 280 }, 281 { 'f', &f_optname, 282 O_BOOL, OPT_OFF, &force_open, NULL, 283 { 284 LM_Open_only_regular_files, 285 LM_Open_even_non_regular_files, 286 LM_NULL 287 }, 288 { NULL, NULL, NULL } 289 }, 290 { 'F', &F__optname, 291 O_BOOL, OPT_OFF, &quit_if_one_screen, NULL, 292 { 293 LM_Dont_quit_if_end_of_file_on_first_screen, 294 LM_Quit_if_end_of_file_on_first_screen, 295 LM_NULL 296 }, 297 { NULL, NULL, NULL } 298 }, 299 #if HILITE_SEARCH 300 { 'g', &g_optname, 301 O_TRIPLE|O_HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL, 302 { 303 LM_Dont_highlight_search_matches, 304 LM_Highlight_matches_for_previous_search_only, 305 LM_Highlight_all_matches_for_previous_search_pattern, 306 }, 307 { NULL, NULL, NULL } 308 }, 309 #endif 310 { 'h', &h_optname, 311 O_NUMBER, -1, &back_scroll, NULL, 312 { 313 LM_Backwards_scroll_limit, 314 LM_Backwards_scroll_limit_is_X_lines, 315 LM_NULL 316 }, 317 { NULL, NULL, NULL } 318 }, 319 { 'i', &i_optname, 320 O_TRIPLE|O_HL_REPAINT, OPT_OFF, &caseless, opt_i, 321 { 322 LM_Case_is_significant_in_searches, 323 LM_Ignore_case_in_searches, 324 LM_Ignore_case_in_searches_and_in_patterns, 325 }, 326 { NULL, NULL, NULL } 327 }, 328 { 'j', &j_optname, 329 O_STRING, 0, NULL, opt_j, 330 { 331 LM_Target_line, 332 LM_neg_dot_d, 333 LM_NULL 334 }, 335 { NULL, NULL, NULL } 336 }, 337 { 'J', &J__optname, 338 O_BOOL|O_REPAINT, OPT_OFF, &status_col, NULL, 339 { 340 LM_Dont_display_a_status_column, 341 LM_Display_a_status_column, 342 LM_NULL 343 }, 344 { NULL, NULL, NULL } 345 }, 346 #if USERFILE 347 { 'k', &k_optname, 348 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_k, 349 { LM_NULL, LM_NULL, LM_NULL }, 350 { NULL, NULL, NULL } 351 }, 352 #if HAVE_LESSKEYSRC 353 { OLETTER_NONE, &kc_optname, 354 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_kc, 355 { LM_NULL, LM_NULL, LM_NULL }, 356 { NULL, NULL, NULL } 357 }, 358 { OLETTER_NONE, &ks_optname, 359 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_ks, 360 { LM_NULL, LM_NULL, LM_NULL }, 361 { NULL, NULL, NULL } 362 }, 363 #endif /* HAVE_LESSKEYSRC */ 364 #endif 365 { 'K', &K__optname, 366 O_BOOL, OPT_OFF, &quit_on_intr, NULL, 367 { 368 LM_Dont_quit_if_end_of_file_on_first_screen, 369 LM_Interrupt_exits_less, 370 LM_NULL 371 }, 372 { NULL, NULL, NULL } 373 }, 374 { 'L', &L__optname, 375 O_BOOL, OPT_ON, &use_lessopen, NULL, 376 { 377 LM_Dont_use_the_LESSOPEN_filter, 378 LM_Use_the_LESSOPEN_filter, 379 LM_NULL 380 }, 381 { NULL, NULL, NULL } 382 }, 383 { 'm', &m_optname, 384 O_TRIPLE, OPT_OFF, &pr_type, NULL, 385 { 386 LM_Short_prompt, 387 LM_Medium_prompt, 388 LM_Long_prompt, 389 }, 390 { NULL, NULL, NULL } 391 }, 392 { 'n', &n_optname, 393 O_TRIPLE|O_REPAINT, OPT_ON, &linenums, NULL, 394 { 395 LM_Dont_use_line_numbers, 396 LM_Use_line_numbers, 397 LM_Constantly_display_line_numbers, 398 }, 399 { NULL, NULL, NULL } 400 }, 401 #if LOGFILE 402 { 'o', &o_optname, 403 O_STRING, 0, NULL, opt_o, 404 { LM_log_file, LM_NULL, LM_NULL }, 405 { NULL, NULL, NULL } 406 }, 407 { 'O', &O__optname, 408 O_STRING, 0, NULL, opt__O, 409 { LM_Log_file, LM_NULL, LM_NULL }, 410 { NULL, NULL, NULL } 411 }, 412 #endif 413 { 'p', &p_optname, 414 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_p, 415 { LM_NULL, LM_NULL, LM_NULL }, 416 { NULL, NULL, NULL } 417 }, 418 { 'P', &P__optname, 419 O_STRING, 0, NULL, opt__P, 420 { LM_prompt, LM_NULL, LM_NULL }, 421 { NULL, NULL, NULL } 422 }, 423 { 'q', &q_optname, 424 O_TRIPLE, OPT_OFF, &quiet, NULL, 425 { 426 LM_Ring_the_bell_for_errors_AND_at_eof, 427 LM_Ring_the_bell_for_errors_but_not_at_eof, 428 LM_Never_ring_the_bell, 429 }, 430 { NULL, NULL, NULL } 431 }, 432 { 'r', &r_optname, 433 O_TRIPLE|O_REPAINT, OPT_OFF, &ctldisp, NULL, 434 { 435 LM_Display_control_characters_as_caret, 436 LM_Display_control_characters_directly, 437 LM_Display_ANSI_sequences_directly, 438 }, 439 { NULL, NULL, NULL } 440 }, 441 { 's', &s_optname, 442 O_BOOL|O_REPAINT, OPT_OFF, &squeeze, NULL, 443 { 444 LM_Display_all_blank_lines, 445 LM_Squeeze_multiple_blank_lines, 446 LM_NULL 447 }, 448 { NULL, NULL, NULL } 449 }, 450 { 'S', &S__optname, 451 O_BOOL|O_REPAINT, OPT_OFF, &chopline, opt__S, 452 { 453 LM_Fold_long_lines, 454 LM_Chop_long_lines, 455 LM_NULL 456 }, 457 { NULL, NULL, NULL } 458 }, 459 #if TAGS 460 { 't', &t_optname, 461 O_STRING|O_NO_QUERY, 0, NULL, opt_t, 462 { LM_tag, LM_NULL, LM_NULL }, 463 { NULL, NULL, NULL } 464 }, 465 { 'T', &T__optname, 466 O_STRING, 0, NULL, opt__T, 467 { LM_tags_file, LM_NULL, LM_NULL }, 468 { NULL, NULL, NULL } 469 }, 470 #endif 471 { 'u', &u_optname, 472 O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &bs_mode, NULL, 473 { 474 LM_Display_underlined_text_in_underline_mode, 475 LM_Backspaces_cause_overstrike, 476 LM_Print_backspace_as_caret, 477 }, 478 { NULL, NULL, NULL } 479 }, 480 { 'V', &V__optname, 481 O_NOVAR, 0, NULL, opt__V, 482 { LM_NULL, LM_NULL, LM_NULL }, 483 { NULL, NULL, NULL } 484 }, 485 { OLETTER_NONE, &hilite_target_optname, 486 O_BOOL, OPT_OFF, &hilite_target, opt_hilite_target, 487 { 488 LM_Dont_highlight_target_line, 489 LM_Highlight_target_line, 490 LM_NULL 491 }, 492 { NULL, NULL, NULL } 493 }, 494 { 'w', &w_optname, 495 O_TRIPLE|O_REPAINT, OPT_OFF, &show_attn, NULL, 496 { 497 LM_Dont_highlight_first_unread_line, 498 LM_Highlight_first_unread_line_after_forward_screen, 499 LM_Highlight_first_unread_line_after_any_forward_movement, 500 }, 501 { NULL, NULL, NULL } 502 }, 503 { 'x', &x_optname, 504 O_STRING|O_REPAINT, 0, NULL, opt_x, 505 { LM_Tab_stops_, LM_d_comma, LM_NULL }, 506 { NULL, NULL, NULL } 507 }, 508 { 'X', &X__optname, 509 O_BOOL|O_NO_TOGGLE, OPT_OFF, &no_init, NULL, 510 { 511 LM_Send_init_deinit_strings_to_terminal, 512 LM_Dont_use_init_deinit_strings, 513 LM_NULL 514 }, 515 { NULL, NULL, NULL } 516 }, 517 { 'y', &y_optname, 518 O_NUMBER, -1, &forw_scroll, NULL, 519 { 520 LM_Forward_scroll_limit, 521 LM_Forward_scroll_limit_is_X_lines, 522 LM_NULL 523 }, 524 { NULL, NULL, NULL } 525 }, 526 { 'z', &z_optname, 527 O_NUMBER|O_NEGOK, -1, &swindow, NULL, 528 { 529 LM_Scroll_window_size, 530 LM_Scroll_window_size_is_X_lines, 531 LM_NULL 532 }, 533 { NULL, NULL, NULL } 534 }, 535 { '"', "e_optname, 536 O_STRING, 0, NULL, opt_quote, 537 { LM_quotes, LM_s, LM_NULL }, 538 { NULL, NULL, NULL } 539 }, 540 { '~', &tilde_optname, 541 O_BOOL|O_REPAINT, OPT_ON, &twiddle, NULL, 542 { 543 LM_Dont_show_tildes_after_end_of_file, 544 LM_Show_tildes_after_end_of_file, 545 LM_NULL 546 }, 547 { NULL, NULL, NULL } 548 }, 549 { '?', &query_optname, 550 O_NOVAR, 0, NULL, opt_query, 551 { LM_NULL, LM_NULL, LM_NULL }, 552 { NULL, NULL, NULL } 553 }, 554 { '#', £_optname, 555 O_STRING, 0, NULL, opt_shift, 556 { LM_Horizontal_shift, LM_dot_d, LM_NULL }, 557 { NULL, NULL, NULL } 558 }, 559 { OLETTER_NONE, &keypad_optname, 560 O_BOOL|O_NO_TOGGLE, OPT_OFF, &no_keypad, NULL, 561 { 562 LM_Use_keypad_mode, 563 LM_Dont_use_keypad_mode, 564 LM_NULL 565 }, 566 { NULL, NULL, NULL } 567 }, 568 { OLETTER_NONE, &oldbot_optname, 569 O_BOOL, OPT_OFF, &oldbot, NULL, 570 { 571 LM_Use_new_bottom_of_screen_behavior, 572 LM_Use_old_bottom_of_screen_behavior, 573 LM_NULL 574 }, 575 { NULL, NULL, NULL } 576 }, 577 { OLETTER_NONE, &follow_optname, 578 O_BOOL, FOLLOW_DESC, &follow_mode, NULL, 579 { 580 LM_F_command_follows_file_descriptor, 581 LM_F_command_follows_file_name, 582 LM_NULL 583 }, 584 { NULL, NULL, NULL } 585 }, 586 { OLETTER_NONE, &use_backslash_optname, 587 O_BOOL, OPT_OFF, &opt_use_backslash, NULL, 588 { 589 LM_Dont_use_backslash_escaping_in_command_line_parameters, 590 LM_Use_backslash_escaping_in_command_line_parameters, 591 LM_NULL 592 }, 593 { NULL, NULL, NULL } 594 }, 595 { OLETTER_NONE, &rscroll_optname, 596 O_STRING|O_REPAINT|O_INIT_HANDLER, 0, NULL, opt_rscroll, 597 { LM_rscroll_character, LM_s, LM_NULL }, 598 { NULL, NULL, NULL } 599 }, 600 { OLETTER_NONE, &nohistdups_optname, 601 O_BOOL, OPT_OFF, &no_hist_dups, NULL, 602 { 603 LM_Allow_duplicates_in_history_list, 604 LM_Remove_duplicates_from_history_list, 605 LM_NULL 606 }, 607 { NULL, NULL, NULL } 608 }, 609 { OLETTER_NONE, &mouse_optname, 610 O_TRIPLE, OPT_OFF, &xmouse, opt_mouse, 611 { LM_NULL, LM_NULL, LM_NULL }, 612 { NULL, NULL, NULL } 613 }, 614 { OLETTER_NONE, &emouse_optname, 615 O_STRING, 0, NULL, opt_emouse, 616 { LM_Mouse_features, LM_s, LM_NULL }, 617 { NULL, NULL, NULL } 618 }, 619 { OLETTER_NONE, &mouse_reverse_optname, 620 O_BOOL, OPT_OFF, &mouse_reverse, NULL, 621 { 622 LM_Normal_mouse_scroll_direction, 623 LM_Reverse_mouse_scroll_direction, 624 LM_NULL 625 }, 626 { NULL, NULL, NULL } 627 }, 628 { OLETTER_NONE, &wheel_lines_optname, 629 O_NUMBER|O_INIT_HANDLER, 0, &wheel_lines, opt_wheel_lines, 630 { 631 LM_Lines_to_scroll_on_mouse_wheel, 632 LM_Scroll_X_lines_on_mouse_wheel, 633 LM_NULL 634 }, 635 { NULL, NULL, NULL } 636 }, 637 { OLETTER_NONE, &perma_marks_optname, 638 O_BOOL, OPT_OFF, &perma_marks, NULL, 639 { 640 LM_Dont_save_marks_in_history_file, 641 LM_Save_marks_in_history_file, 642 LM_NULL 643 }, 644 { NULL, NULL, NULL } 645 }, 646 { OLETTER_NONE, &linenum_width_optname, 647 O_NUMBER|O_REPAINT, MIN_LINENUM_WIDTH, &linenum_width, opt_linenum_width, 648 { 649 LM_Line_number_width, 650 LM_Line_number_width_is_X_chars, 651 LM_NULL 652 }, 653 { NULL, NULL, NULL } 654 }, 655 { OLETTER_NONE, &status_col_width_optname, 656 O_NUMBER|O_REPAINT, 2, &status_col_width, opt_status_col_width, 657 { 658 LM_Status_column_width, 659 LM_Status_column_width_is_X_chars, 660 LM_NULL 661 }, 662 { NULL, NULL, NULL } 663 }, 664 { OLETTER_NONE, &incr_search_optname, 665 O_BOOL, OPT_OFF, &incr_search, NULL, 666 { 667 LM_Incremental_search_is_off, 668 LM_Incremental_search_is_on, 669 LM_NULL 670 }, 671 { NULL, NULL, NULL } 672 }, 673 { OLETTER_NONE, &use_color_optname, 674 O_BOOL|O_REPAINT, OPT_OFF, &use_color, NULL, 675 { 676 LM_Dont_use_color, 677 LM_Use_color, 678 LM_NULL 679 }, 680 { NULL, NULL, NULL } 681 }, 682 { OLETTER_NONE, &want_filesize_optname, 683 O_BOOL|O_REPAINT, OPT_OFF, &want_filesize, opt_filesize, 684 { 685 LM_Dont_get_size_of_each_file, 686 LM_Get_size_of_each_file, 687 LM_NULL 688 }, 689 { NULL, NULL, NULL } 690 }, 691 { OLETTER_NONE, &status_line_optname, 692 O_BOOL|O_REPAINT, OPT_OFF, &status_line, NULL, 693 { 694 LM_Line_highlight_applies_to_text_only, 695 LM_Line_highlight_applies_to_entire_width_of_screen, 696 LM_NULL 697 }, 698 { NULL, NULL, NULL } 699 }, 700 { OLETTER_NONE, &header_optname, 701 O_STRING|O_REPAINT, 0, NULL, opt_header, 702 { LM_Header_lines, LM_d_comma, LM_NULL }, 703 { NULL, NULL, NULL } 704 }, 705 { OLETTER_NONE, &no_paste_optname, 706 O_BOOL, OPT_OFF, &no_paste, opt_no_paste, 707 { 708 LM_Accept_pasted_input, 709 LM_Ignore_pasted_input, 710 LM_NULL 711 }, 712 { NULL, NULL, NULL } 713 }, 714 { OLETTER_NONE, &form_feed_optname, 715 O_BOOL, OPT_OFF, &stop_on_form_feed, NULL, 716 { 717 LM_Dont_stop_on_form_feed, 718 LM_Stop_on_form_feed, 719 LM_NULL 720 }, 721 { NULL, NULL, NULL } 722 }, 723 { OLETTER_NONE, &past_eof_optname, 724 O_BOOL, OPT_OFF, &past_eof, NULL, 725 { 726 LM_Stop_scrolling_at_end_of_file, 727 LM_Dont_stop_scrolling_at_end_of_file, 728 LM_NULL 729 }, 730 { NULL, NULL, NULL } 731 }, 732 { OLETTER_NONE, &no_edit_warn_optname, 733 O_BOOL, OPT_OFF, &no_edit_warn, NULL, 734 { 735 LM_Warn_when_editing_a_file_opened_via_LESSOPEN, 736 LM_Dont_warn_when_editing_a_file_opened_via_LESSOPEN, 737 LM_NULL 738 }, 739 { NULL, NULL, NULL } 740 }, 741 { OLETTER_NONE, &nonum_headers_optname, 742 O_BOOL|O_REPAINT, 0, &nonum_headers, NULL, 743 { 744 LM_Number_header_lines, 745 LM_Dont_number_header_lines, 746 LM_NULL 747 }, 748 { NULL, NULL, NULL } 749 }, 750 { OLETTER_NONE, &nosearch_headers_optname, 751 O_BOOL|O_HL_REPAINT, 0, NULL, opt_nosearch_headers, 752 { LM_NULL, LM_NULL, LM_NULL }, 753 { NULL, NULL, NULL } 754 }, 755 { OLETTER_NONE, &nosearch_header_lines_optname, 756 O_BOOL|O_HL_REPAINT, 0, NULL, opt_nosearch_header_lines, 757 { LM_NULL, LM_NULL, LM_NULL }, 758 { NULL, NULL, NULL } 759 }, 760 { OLETTER_NONE, &nosearch_header_cols_optname, 761 O_BOOL|O_HL_REPAINT, 0, NULL, opt_nosearch_header_cols, 762 { LM_NULL, LM_NULL, LM_NULL }, 763 { NULL, NULL, NULL } 764 }, 765 { OLETTER_NONE, &redraw_on_quit_optname, 766 O_BOOL, OPT_OFF, &redraw_on_quit, NULL, 767 { 768 LM_Dont_redraw_screen_when_quitting, 769 LM_Redraw_last_screen_when_quitting, 770 LM_NULL 771 }, 772 { NULL, NULL, NULL } 773 }, 774 { OLETTER_NONE, &search_type_optname, 775 O_STRING, 0, NULL, opt_search_type, 776 { LM_Search_options, LM_s, LM_NULL }, 777 { NULL, NULL, NULL } 778 }, 779 { OLETTER_NONE, &exit_F_on_close_optname, 780 O_BOOL, OPT_OFF, &exit_F_on_close, NULL, 781 { 782 LM_Dont_exit_F_command_when_input_closes, 783 LM_Exit_F_command_when_input_closes, 784 LM_NULL 785 }, 786 { NULL, NULL, NULL } 787 }, 788 { OLETTER_NONE, &no_vbell_optname, 789 O_BOOL, OPT_OFF, &no_vbell, NULL, 790 { 791 LM_Display_visual_bell, 792 LM_Dont_display_visual_bell, 793 LM_NULL 794 }, 795 { NULL, NULL, NULL } 796 }, 797 { OLETTER_NONE, &modelines_optname, 798 O_NUMBER, 0, &modelines, NULL, 799 { 800 LM_Lines_to_read_looking_for_modelines, 801 LM_Read_X_lines_looking_for_modelines, 802 LM_NULL 803 }, 804 { NULL, NULL, NULL } 805 }, 806 { OLETTER_NONE, &intr_optname, 807 O_STRING, 0, NULL, opt_intr, 808 { LM_interrupt_character, LM_s, LM_NULL }, 809 { NULL, NULL, NULL } 810 }, 811 { OLETTER_NONE, &wordwrap_optname, 812 O_BOOL|O_REPAINT, OPT_OFF, &wordwrap, NULL, 813 { 814 LM_Wrap_lines_at_any_character, 815 LM_Wrap_lines_at_spaces, 816 LM_NULL 817 }, 818 { NULL, NULL, NULL } 819 }, 820 { OLETTER_NONE, &show_preproc_error_optname, 821 O_BOOL, OPT_OFF, &show_preproc_error, NULL, 822 { 823 LM_Dont_show_error_message_if_preprocessor_fails, 824 LM_Show_error_message_if_preprocessor_fails, 825 LM_NULL 826 }, 827 { NULL, NULL, NULL } 828 }, 829 { OLETTER_NONE, &proc_backspace_optname, 830 O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &proc_backspace, NULL, 831 { 832 LM_Backspace_handling_is_specified_by_the_U_option, 833 LM_Display_underline_text_in_underline_mode, 834 LM_Print_backspaces_as_caret, 835 }, 836 { NULL, NULL, NULL } 837 }, 838 { OLETTER_NONE, &proc_tab_optname, 839 O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &proc_tab, NULL, 840 { 841 LM_Tab_handling_is_specified_by_the_U_option, 842 LM_Expand_tabs_to_spaces, 843 LM_Print_tabs_as_caret, 844 }, 845 { NULL, NULL, NULL } 846 }, 847 { OLETTER_NONE, &proc_return_optname, 848 O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &proc_return, NULL, 849 { 850 LM_Carriage_return_handling_is_specified_by_the_U_option, 851 LM_Delete_carriage_return_before_newline, 852 LM_Print_carriage_return_as_caret, 853 }, 854 { NULL, NULL, NULL } 855 }, 856 { OLETTER_NONE, &first_cmd_at_prompt_optname, 857 O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_first_cmd_at_prompt, 858 { LM_NULL, LM_NULL, LM_NULL }, 859 { NULL, NULL, NULL } 860 }, 861 { OLETTER_NONE, &match_shift_optname, 862 O_STRING|O_INIT_HANDLER, 0, NULL, opt_match_shift, 863 { LM_Search_match_shift, LM_dot_d, LM_NULL }, 864 { NULL, NULL, NULL } 865 }, 866 { OLETTER_NONE, &autosave_optname, 867 O_STRING|O_INIT_HANDLER, 0, NULL, opt_autosave, 868 { LM_Autosave_actions, LM_s, LM_NULL }, 869 { NULL, NULL, NULL } 870 }, 871 { OLETTER_NONE, &end_prompt_optname, 872 O_STRING, 0, NULL, opt_end_prompt, 873 { LM_Print_after_prompt, LM_s, LM_NULL }, 874 { NULL, NULL, NULL } 875 }, 876 #if LESSTEST 877 { OLETTER_NONE, &ttyin_name_optname, 878 O_STRING|O_NO_TOGGLE, 0, NULL, opt_ttyin_name, 879 { LM_NULL, LM_NULL, LM_NULL }, 880 { NULL, NULL, NULL } 881 }, 882 #endif /*LESSTEST*/ 883 { '\0', NULL, O_NOVAR, 0, NULL, NULL, 884 { LM_NULL, LM_NULL, LM_NULL }, 885 { NULL, NULL, NULL } 886 } 887 }; 888 889 890 /* 891 * Initialize each option to its default value. 892 */ 893 public void init_option(void) 894 { 895 struct loption *o; 896 constant char *p; 897 898 p = lgetenv("LESS_IS_MORE"); 899 if (!isnullenv(p) && !(p[0] == '0' && p[1] == '\0')) 900 less_is_more = TRUE; 901 902 for (o = option; o->oletter != '\0'; o++) 903 { 904 int i; 905 for (i = 0; i < 3; i++) 906 o->odesc[i] = (o->odescid[i] == LM_NULL) ? NULL : lmsg(o->odescid[i]); 907 if (o->ovar != NULL) 908 *(o->ovar) = o->odefault; 909 if (o->otype & O_INIT_HANDLER) 910 (*(o->ofunc))(INIT, (char *) NULL); 911 } 912 } 913 914 /* 915 * Find an option in the option table, given its option letter. 916 */ 917 public struct loption * findopt(int c) 918 { 919 struct loption *o; 920 921 for (o = option; o->oletter != '\0'; o++) 922 { 923 if (o->oletter == c) 924 return (o); 925 if ((o->otype & O_TRIPLE) && ASCII_TO_UPPER(o->oletter) == c) 926 return (o); 927 } 928 return (NULL); 929 } 930 931 /* 932 * 933 */ 934 static lbool is_optchar(char c) 935 { 936 if (ASCII_IS_UPPER(c)) 937 return TRUE; 938 if (ASCII_IS_LOWER(c)) 939 return TRUE; 940 if (c == '-') 941 return TRUE; 942 return FALSE; 943 } 944 945 /* 946 * Find an option in the option table, given its option name. 947 * p_optname is the (possibly partial) name to look for, and 948 * is updated to point after the matched name. 949 * p_oname if non-NULL is set to point to the full option name. 950 */ 951 public struct loption * findopt_name(constant char **p_optname, constant char **p_oname, lbool *p_ambig) 952 { 953 constant char *optname = *p_optname; 954 struct loption *o; 955 struct optname *oname; 956 size_t len; 957 int uppercase; 958 struct loption *maxo = NULL; 959 struct optname *maxoname = NULL; 960 size_t maxlen = 0; 961 lbool ambig = FALSE; 962 lbool exact = FALSE; 963 964 /* 965 * Check all options. 966 */ 967 for (o = option; o->oletter != '\0'; o++) 968 { 969 /* 970 * Check all names for this option. 971 */ 972 for (oname = o->onames; oname != NULL; oname = oname->onext) 973 { 974 /* 975 * Try normal match first (uppercase == 0), 976 * then, then if it's a TRIPLE option, 977 * try uppercase match (uppercase == 1). 978 */ 979 for (uppercase = 0; uppercase <= 1; uppercase++) 980 { 981 len = sprefix(optname, oname->oname, uppercase); 982 if (len == 0 || is_optchar(optname[len])) 983 { 984 /* 985 * We didn't use all of the option name. 986 */ 987 continue; 988 } 989 if (!exact && len == maxlen) 990 /* 991 * Already had a partial match, 992 * and now there's another one that 993 * matches the same length. 994 */ 995 ambig = TRUE; 996 else if (len > maxlen) 997 { 998 /* 999 * Found a better match than 1000 * the one we had. 1001 */ 1002 maxo = o; 1003 maxoname = oname; 1004 maxlen = len; 1005 ambig = FALSE; 1006 exact = (len == strlen(oname->oname)); 1007 } 1008 if (!(o->otype & O_TRIPLE)) 1009 break; 1010 } 1011 } 1012 } 1013 if (p_ambig != NULL) 1014 *p_ambig = ambig; 1015 if (ambig) 1016 { 1017 /* 1018 * Name matched more than one option. 1019 */ 1020 return (NULL); 1021 } 1022 *p_optname = optname + maxlen; 1023 if (p_oname != NULL) 1024 *p_oname = maxoname == NULL ? NULL : maxoname->oname; 1025 return (maxo); 1026 } 1027 1028 /* 1029 * Find all toggleable options whose names begin with a specified string. 1030 * Return them in a space-separated string. 1031 */ 1032 public char * findopts_name(constant char *pfx) 1033 { 1034 constant struct loption *o; 1035 constant struct optname *oname; 1036 struct xbuffer xbuf; 1037 int uppercase; 1038 1039 xbuf_init(&xbuf); 1040 for (o = option; o->oletter != '\0'; o++) 1041 { 1042 if (o->otype & O_NO_TOGGLE) 1043 continue; 1044 for (oname = o->onames; oname != NULL; oname = oname->onext) 1045 { 1046 for (uppercase = 0; uppercase <= 1; uppercase++) 1047 { 1048 size_t len = sprefix(pfx, oname->oname, uppercase); 1049 if (len >= strlen(pfx)) 1050 { 1051 constant char *np; 1052 for (np = oname->oname; *np != '\0'; np++) 1053 xbuf_add_char(&xbuf, uppercase && ASCII_IS_LOWER(*np) ? ASCII_TO_UPPER(*np) : *np); 1054 xbuf_add_char(&xbuf, ' '); 1055 } 1056 if (!(o->otype & O_TRIPLE)) 1057 break; 1058 } 1059 } 1060 } 1061 xbuf_pop(&xbuf); /* remove final space */ 1062 xbuf_add_char(&xbuf, '\0'); 1063 return (char *) xbuf.data; 1064 } 1065