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 */
init_option(void)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 */
findopt(int c)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 */
is_optchar(char c)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 */
findopt_name(constant char ** p_optname,constant char ** p_oname,lbool * p_ambig)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 */
findopts_name(constant char * pfx)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