2 * Copyright (C) 1984-2022 Mark Nudelman
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.
7 * For more information, see the README file.
19 * Variables controlled by command line options.
21 public int quiet
; /* Should we suppress the audible bell? */
22 public int how_search
; /* Where should forward searches start? */
23 public int top_scroll
; /* Repaint screen from top?
24 (alternative is scroll from bottom) */
25 public int pr_type
; /* Type of prompt (short, medium, long) */
26 public int bs_mode
; /* How to process backspaces */
27 public int know_dumb
; /* Don't complain about dumb terminals */
28 public int quit_at_eof
; /* Quit after hitting end of file twice */
29 public int quit_if_one_screen
; /* Quit if EOF on first screen */
30 public int squeeze
; /* Squeeze multiple blank lines into one */
31 public int tabstop
; /* Tab settings */
32 public int back_scroll
; /* Repaint screen on backwards movement */
33 public int forw_scroll
; /* Repaint screen on forward movement */
34 public int caseless
; /* Do "caseless" searches */
35 public int linenums
; /* Use line numbers */
36 public int autobuf
; /* Automatically allocate buffers as needed */
37 public int bufspace
; /* Max buffer space per file (K) */
38 public int ctldisp
; /* Send control chars to screen untranslated */
39 public int force_open
; /* Open the file even if not regular file */
40 public int swindow
; /* Size of scrolling window */
41 public int jump_sline
; /* Screen line of "jump target" */
42 public long jump_sline_fraction
= -1;
43 public long shift_count_fraction
= -1;
44 public int chopline
; /* Truncate displayed lines at screen width */
45 public int no_init
; /* Disable sending ti/te termcap strings */
46 public int no_keypad
; /* Disable sending ks/ke termcap strings */
47 public int twiddle
; /* Show tildes after EOF */
48 public int show_attn
; /* Hilite first unread line */
49 public int shift_count
; /* Number of positions to shift horizontally */
50 public int status_col
; /* Display a status column */
51 public int use_lessopen
; /* Use the LESSOPEN filter */
52 public int quit_on_intr
; /* Quit on interrupt */
53 public int follow_mode
; /* F cmd Follows file desc or file name? */
54 public int oldbot
; /* Old bottom of screen behavior {{REMOVE}} */
55 public int opt_use_backslash
; /* Use backslash escaping in option parsing */
56 public char rscroll_char
; /* Char which marks chopped lines with -S */
57 public int rscroll_attr
; /* Attribute of rscroll_char */
58 public int no_hist_dups
; /* Remove dups from history list */
59 public int mousecap
; /* Allow mouse for scrolling */
60 public int wheel_lines
; /* Number of lines to scroll on mouse wheel scroll */
61 public int perma_marks
; /* Save marks in history file */
62 public int linenum_width
; /* Width of line numbers */
63 public int status_col_width
; /* Width of status column */
64 public int incr_search
; /* Incremental search */
65 public int use_color
; /* Use UI color */
66 public int want_filesize
; /* Scan to EOF if necessary to get file size */
67 public int status_line
; /* Highlight entire marked lines */
68 public int header_lines
; /* Freeze header lines at top of screen */
69 public int header_cols
; /* Freeze header columns at left of screen */
70 public int nonum_headers
; /* Don't give headers line numbers */
71 public int redraw_on_quit
; /* Redraw last screen after term deinit */
72 public int def_search_type
; /* */
73 public int exit_F_on_close
; /* Exit F command when input closes */
75 public int hilite_search
; /* Highlight matched search patterns? */
78 public int less_is_more
= 0; /* Make compatible with POSIX more */
83 static struct optname a_optname
= { "search-skip-screen", NULL
};
84 static struct optname b_optname
= { "buffers", NULL
};
85 static struct optname B__optname
= { "auto-buffers", NULL
};
86 static struct optname c_optname
= { "clear-screen", NULL
};
87 static struct optname d_optname
= { "dumb", NULL
};
88 static struct optname D__optname
= { "color", NULL
};
89 static struct optname e_optname
= { "quit-at-eof", NULL
};
90 static struct optname f_optname
= { "force", NULL
};
91 static struct optname F__optname
= { "quit-if-one-screen", NULL
};
93 static struct optname g_optname
= { "hilite-search", NULL
};
95 static struct optname h_optname
= { "max-back-scroll", NULL
};
96 static struct optname i_optname
= { "ignore-case", NULL
};
97 static struct optname j_optname
= { "jump-target", NULL
};
98 static struct optname J__optname
= { "status-column", NULL
};
100 static struct optname k_optname
= { "lesskey-file", NULL
};
102 static struct optname ks_optname
= { "lesskey-src", NULL
};
103 #endif /* HAVE_LESSKEYSRC */
105 static struct optname K__optname
= { "quit-on-intr", NULL
};
106 static struct optname L__optname
= { "no-lessopen", NULL
};
107 static struct optname m_optname
= { "long-prompt", NULL
};
108 static struct optname n_optname
= { "line-numbers", NULL
};
110 static struct optname o_optname
= { "log-file", NULL
};
111 static struct optname O__optname
= { "LOG-FILE", NULL
};
113 static struct optname p_optname
= { "pattern", NULL
};
114 static struct optname P__optname
= { "prompt", NULL
};
115 static struct optname q2_optname
= { "silent", NULL
};
116 static struct optname q_optname
= { "quiet", &q2_optname
};
117 static struct optname r_optname
= { "raw-control-chars", NULL
};
118 static struct optname s_optname
= { "squeeze-blank-lines", NULL
};
119 static struct optname S__optname
= { "chop-long-lines", NULL
};
121 static struct optname t_optname
= { "tag", NULL
};
122 static struct optname T__optname
= { "tag-file", NULL
};
124 static struct optname u_optname
= { "underline-special", NULL
};
125 static struct optname V__optname
= { "version", NULL
};
126 static struct optname w_optname
= { "hilite-unread", NULL
};
127 static struct optname x_optname
= { "tabs", NULL
};
128 static struct optname X__optname
= { "no-init", NULL
};
129 static struct optname y_optname
= { "max-forw-scroll", NULL
};
130 static struct optname z_optname
= { "window", NULL
};
131 static struct optname quote_optname
= { "quotes", NULL
};
132 static struct optname tilde_optname
= { "tilde", NULL
};
133 static struct optname query_optname
= { "help", NULL
};
134 static struct optname pound_optname
= { "shift", NULL
};
135 static struct optname keypad_optname
= { "no-keypad", NULL
};
136 static struct optname oldbot_optname
= { "old-bot", NULL
};
137 static struct optname follow_optname
= { "follow-name", NULL
};
138 static struct optname use_backslash_optname
= { "use-backslash", NULL
};
139 static struct optname rscroll_optname
= { "rscroll", NULL
};
140 static struct optname nohistdups_optname
= { "no-histdups", NULL
};
141 static struct optname mousecap_optname
= { "mouse", NULL
};
142 static struct optname wheel_lines_optname
= { "wheel-lines", NULL
};
143 static struct optname perma_marks_optname
= { "save-marks", NULL
};
144 static struct optname linenum_width_optname
= { "line-num-width", NULL
};
145 static struct optname status_col_width_optname
= { "status-col-width", NULL
};
146 static struct optname incr_search_optname
= { "incsearch", NULL
};
147 static struct optname use_color_optname
= { "use-color", NULL
};
148 static struct optname want_filesize_optname
= { "file-size", NULL
};
149 static struct optname status_line_optname
= { "status-line", NULL
};
150 static struct optname header_optname
= { "header", NULL
};
151 static struct optname nonum_headers_optname
= { "no-number-headers", NULL
};
152 static struct optname redraw_on_quit_optname
= { "redraw-on-quit", NULL
};
153 static struct optname search_type_optname
= { "search-options", NULL
};
154 static struct optname exit_F_on_close_optname
= { "exit-follow-on-close", NULL
};
156 static struct optname ttyin_name_optname
= { "tty", NULL
};
157 static struct optname rstat_optname
= { "rstat", NULL
};
162 * Table of all options and their semantics.
164 * For BOOL and TRIPLE options, odesc[0], odesc[1], odesc[2] are
165 * the description of the option when set to 0, 1 or 2, respectively.
166 * For NUMBER options, odesc[0] is the prompt to use when entering
167 * a new value, and odesc[1] is the description, which should contain
168 * one %d which is replaced by the value of the number.
169 * For STRING options, odesc[0] is the prompt to use when entering
170 * a new value, and odesc[1], if not NULL, is the set of characters
171 * that are valid in the string.
173 static struct loption option
[] =
176 TRIPLE
, OPT_ONPLUS
, &how_search
, NULL
,
178 "Search includes displayed screen",
179 "Search skips displayed screen",
180 "Search includes all of displayed screen"
185 NUMBER
|INIT_HANDLER
, 64, &bufspace
, opt_b
,
187 "Max buffer space per file (K): ",
188 "Max buffer space per file: %dK",
193 BOOL
, OPT_ON
, &autobuf
, NULL
,
195 "Don't automatically allocate buffers",
196 "Automatically allocate buffers when needed",
201 TRIPLE
, OPT_OFF
, &top_scroll
, NULL
,
203 "Repaint by scrolling from bottom of screen",
204 "Repaint by painting from top of screen",
205 "Repaint by painting from top of screen"
209 BOOL
|NO_TOGGLE
, OPT_OFF
, &know_dumb
, NULL
,
211 "Assume intelligent terminal",
212 "Assume dumb terminal",
217 STRING
|REPAINT
|NO_QUERY
, 0, NULL
, opt_D
,
225 TRIPLE
, OPT_OFF
, &quit_at_eof
, NULL
,
227 "Don't quit at end-of-file",
228 "Quit at end-of-file",
229 "Quit immediately at end-of-file"
233 BOOL
, OPT_OFF
, &force_open
, NULL
,
235 "Open only regular files",
236 "Open even non-regular files",
241 BOOL
, OPT_OFF
, &quit_if_one_screen
, NULL
,
243 "Don't quit if end-of-file on first screen",
244 "Quit if end-of-file on first screen",
250 TRIPLE
|HL_REPAINT
, OPT_ONPLUS
, &hilite_search
, NULL
,
252 "Don't highlight search matches",
253 "Highlight matches for previous search only",
254 "Highlight all matches for previous search pattern",
259 NUMBER
, -1, &back_scroll
, NULL
,
261 "Backwards scroll limit: ",
262 "Backwards scroll limit is %d lines",
267 TRIPLE
|HL_REPAINT
, OPT_OFF
, &caseless
, opt_i
,
269 "Case is significant in searches",
270 "Ignore case in searches",
271 "Ignore case in searches and in patterns"
275 STRING
, 0, NULL
, opt_j
,
283 BOOL
|REPAINT
, OPT_OFF
, &status_col
, NULL
,
285 "Don't display a status column",
286 "Display a status column",
292 STRING
|NO_TOGGLE
|NO_QUERY
, 0, NULL
, opt_k
,
296 { OLETTER_NONE
, &ks_optname
,
297 STRING
|NO_TOGGLE
|NO_QUERY
, 0, NULL
, opt_ks
,
300 #endif /* HAVE_LESSKEYSRC */
303 BOOL
, OPT_OFF
, &quit_on_intr
, NULL
,
305 "Interrupt (ctrl-C) returns to prompt",
306 "Interrupt (ctrl-C) exits less",
311 BOOL
, OPT_ON
, &use_lessopen
, NULL
,
313 "Don't use the LESSOPEN filter",
314 "Use the LESSOPEN filter",
319 TRIPLE
, OPT_OFF
, &pr_type
, NULL
,
327 TRIPLE
|REPAINT
, OPT_ON
, &linenums
, NULL
,
329 "Don't use line numbers",
331 "Constantly display line numbers"
336 STRING
, 0, NULL
, opt_o
,
337 { "log file: ", NULL
, NULL
}
340 STRING
, 0, NULL
, opt__O
,
341 { "Log file: ", NULL
, NULL
}
345 STRING
|NO_TOGGLE
|NO_QUERY
, 0, NULL
, opt_p
,
349 STRING
, 0, NULL
, opt__P
,
350 { "prompt: ", NULL
, NULL
}
353 TRIPLE
, OPT_OFF
, &quiet
, NULL
,
355 "Ring the bell for errors AND at eof/bof",
356 "Ring the bell for errors but not at eof/bof",
357 "Never ring the bell"
361 TRIPLE
|REPAINT
, OPT_OFF
, &ctldisp
, NULL
,
363 "Display control characters as ^X",
364 "Display control characters directly (not recommended)",
365 "Display ANSI sequences directly, other control characters as ^X"
369 BOOL
|REPAINT
, OPT_OFF
, &squeeze
, NULL
,
371 "Display all blank lines",
372 "Squeeze multiple blank lines",
377 BOOL
|REPAINT
, OPT_OFF
, &chopline
, NULL
,
386 STRING
|NO_QUERY
, 0, NULL
, opt_t
,
387 { "tag: ", NULL
, NULL
}
390 STRING
, 0, NULL
, opt__T
,
391 { "tags file: ", NULL
, NULL
}
395 TRIPLE
|REPAINT
, OPT_OFF
, &bs_mode
, NULL
,
397 "Display underlined text in underline mode",
398 "Backspaces cause overstrike",
399 "Print backspace as ^H"
403 NOVAR
, 0, NULL
, opt__V
,
407 TRIPLE
|REPAINT
, OPT_OFF
, &show_attn
, NULL
,
409 "Don't highlight first unread line",
410 "Highlight first unread line after forward-screen",
411 "Highlight first unread line after any forward movement",
415 STRING
|REPAINT
, 0, NULL
, opt_x
,
423 BOOL
|NO_TOGGLE
, OPT_OFF
, &no_init
, NULL
,
425 "Send init/deinit strings to terminal",
426 "Don't use init/deinit strings",
431 NUMBER
, -1, &forw_scroll
, NULL
,
433 "Forward scroll limit: ",
434 "Forward scroll limit is %d lines",
439 NUMBER
, -1, &swindow
, NULL
,
441 "Scroll window size: ",
442 "Scroll window size is %d lines",
446 { '"', "e_optname
,
447 STRING
, 0, NULL
, opt_quote
,
448 { "quotes: ", NULL
, NULL
}
450 { '~', &tilde_optname
,
451 BOOL
|REPAINT
, OPT_ON
, &twiddle
, NULL
,
453 "Don't show tildes after end of file",
454 "Show tildes after end of file",
458 { '?', &query_optname
,
459 NOVAR
, 0, NULL
, opt_query
,
462 { '#', £_optname
,
463 STRING
, 0, NULL
, opt_shift
,
465 "Horizontal shift: ",
470 { OLETTER_NONE
, &keypad_optname
,
471 BOOL
|NO_TOGGLE
, OPT_OFF
, &no_keypad
, NULL
,
474 "Don't use keypad mode",
478 { OLETTER_NONE
, &oldbot_optname
,
479 BOOL
, OPT_OFF
, &oldbot
, NULL
,
481 "Use new bottom of screen behavior",
482 "Use old bottom of screen behavior",
486 { OLETTER_NONE
, &follow_optname
,
487 BOOL
, FOLLOW_DESC
, &follow_mode
, NULL
,
489 "F command follows file descriptor",
490 "F command follows file name",
494 { OLETTER_NONE
, &use_backslash_optname
,
495 BOOL
, OPT_OFF
, &opt_use_backslash
, NULL
,
497 "Use backslash escaping in command line parameters",
498 "Don't use backslash escaping in command line parameters",
502 { OLETTER_NONE
, &rscroll_optname
,
503 STRING
|REPAINT
|INIT_HANDLER
, 0, NULL
, opt_rscroll
,
504 { "right scroll character: ", NULL
, NULL
}
506 { OLETTER_NONE
, &nohistdups_optname
,
507 BOOL
, OPT_OFF
, &no_hist_dups
, NULL
,
509 "Allow duplicates in history list",
510 "Remove duplicates from history list",
514 { OLETTER_NONE
, &mousecap_optname
,
515 TRIPLE
, OPT_OFF
, &mousecap
, opt_mousecap
,
517 "Ignore mouse input",
518 "Use the mouse for scrolling",
519 "Use the mouse for scrolling (reverse)"
522 { OLETTER_NONE
, &wheel_lines_optname
,
523 NUMBER
|INIT_HANDLER
, 0, &wheel_lines
, opt_wheel_lines
,
525 "Lines to scroll on mouse wheel: ",
526 "Scroll %d line(s) on mouse wheel",
530 { OLETTER_NONE
, &perma_marks_optname
,
531 BOOL
, OPT_OFF
, &perma_marks
, NULL
,
533 "Don't save marks in history file",
534 "Save marks in history file",
538 { OLETTER_NONE
, &linenum_width_optname
,
539 NUMBER
|REPAINT
, MIN_LINENUM_WIDTH
, &linenum_width
, opt_linenum_width
,
541 "Line number width: ",
542 "Line number width is %d chars",
546 { OLETTER_NONE
, &status_col_width_optname
,
547 NUMBER
|REPAINT
, 2, &status_col_width
, opt_status_col_width
,
549 "Status column width: ",
550 "Status column width is %d chars",
554 { OLETTER_NONE
, &incr_search_optname
,
555 BOOL
, OPT_OFF
, &incr_search
, NULL
,
557 "Incremental search is off",
558 "Incremental search is on",
562 { OLETTER_NONE
, &use_color_optname
,
563 BOOL
|REPAINT
, OPT_OFF
, &use_color
, NULL
,
570 { OLETTER_NONE
, &want_filesize_optname
,
571 BOOL
|REPAINT
, OPT_OFF
, &want_filesize
, opt_filesize
,
573 "Don't get size of each file",
574 "Get size of each file",
578 { OLETTER_NONE
, &status_line_optname
,
579 BOOL
|REPAINT
, OPT_OFF
, &status_line
, NULL
,
581 "Don't color each line with its status column color",
582 "Color each line with its status column color",
586 { OLETTER_NONE
, &header_optname
,
587 STRING
|REPAINT
, 0, NULL
, opt_header
,
594 { OLETTER_NONE
, &nonum_headers_optname
,
595 BOOL
|REPAINT
, 0, &nonum_headers
, NULL
,
597 "Number header lines",
598 "Don't number header lines",
602 { OLETTER_NONE
, &redraw_on_quit_optname
,
603 BOOL
, OPT_OFF
, &redraw_on_quit
, NULL
,
605 "Don't redraw screen when quitting",
606 "Redraw last screen when quitting",
610 { OLETTER_NONE
, &search_type_optname
,
611 STRING
, 0, NULL
, opt_search_type
,
618 { OLETTER_NONE
, &exit_F_on_close_optname
,
619 BOOL
, OPT_OFF
, &exit_F_on_close
, NULL
,
621 "Don't exit F command when input closes",
622 "Exit F command when input closes",
627 { OLETTER_NONE
, &ttyin_name_optname
,
628 STRING
|NO_TOGGLE
, 0, NULL
, opt_ttyin_name
,
635 { OLETTER_NONE
, &rstat_optname
,
636 STRING
|NO_TOGGLE
, 0, NULL
, opt_rstat
,
644 { '\0', NULL
, NOVAR
, 0, NULL
, NULL
, { NULL
, NULL
, NULL
} }
649 * Initialize each option to its default value.
652 init_option(VOID_PARAM
)
657 p
= lgetenv("LESS_IS_MORE");
661 for (o
= option
; o
->oletter
!= '\0'; o
++)
664 * Set each variable to its default.
667 *(o
->ovar
) = o
->odefault
;
668 if (o
->otype
& INIT_HANDLER
)
669 (*(o
->ofunc
))(INIT
, (char *) NULL
);
674 * Find an option in the option table, given its option letter.
676 public struct loption
*
682 for (o
= option
; o
->oletter
!= '\0'; o
++)
686 if ((o
->otype
& TRIPLE
) && ASCII_TO_UPPER(o
->oletter
) == c
)
699 if (ASCII_IS_UPPER(c
))
701 if (ASCII_IS_LOWER(c
))
709 * Find an option in the option table, given its option name.
710 * p_optname is the (possibly partial) name to look for, and
711 * is updated to point after the matched name.
712 * p_oname if non-NULL is set to point to the full option name.
714 public struct loption
*
715 findopt_name(p_optname
, p_oname
, p_err
)
720 char *optname
= *p_optname
;
722 struct optname
*oname
;
725 struct loption
*maxo
= NULL
;
726 struct optname
*maxoname
= NULL
;
734 for (o
= option
; o
->oletter
!= '\0'; o
++)
737 * Check all names for this option.
739 for (oname
= o
->onames
; oname
!= NULL
; oname
= oname
->onext
)
742 * Try normal match first (uppercase == 0),
743 * then, then if it's a TRIPLE option,
744 * try uppercase match (uppercase == 1).
746 for (uppercase
= 0; uppercase
<= 1; uppercase
++)
748 len
= sprefix(optname
, oname
->oname
, uppercase
);
749 if (len
<= 0 || is_optchar(optname
[len
]))
752 * We didn't use all of the option name.
756 if (!exact
&& len
== maxlen
)
758 * Already had a partial match,
759 * and now there's another one that
760 * matches the same length.
763 else if (len
> maxlen
)
766 * Found a better match than
773 exact
= (len
== (int)strlen(oname
->oname
));
775 if (!(o
->otype
& TRIPLE
))
783 * Name matched more than one option.
789 *p_optname
= optname
+ maxlen
;
791 *p_oname
= maxoname
== NULL
? NULL
: maxoname
->oname
;