2 * Copyright (C) 1984-2012 Mark Nudelman
3 * Modified for use with illumos by Garrett D'Amore.
4 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
6 * You may distribute under the terms of either the GNU General Public
7 * License or the Less License, as specified in the README file.
9 * For more information, see the README file.
20 * Variables controlled by command line options.
22 int quiet
; /* Should we suppress the audible bell? */
23 int how_search
; /* Where should forward searches start? */
24 int top_scroll
; /* Repaint screen from top? (vs scroll from bottom) */
25 int pr_type
; /* Type of prompt (short, medium, long) */
26 int bs_mode
; /* How to process backspaces */
27 int know_dumb
; /* Don't complain about dumb terminals */
28 int quit_at_eof
; /* Quit after hitting end of file twice */
29 int quit_if_one_screen
; /* Quit if EOF on first screen */
30 int squeeze
; /* Squeeze multiple blank lines into one */
31 int back_scroll
; /* Repaint screen on backwards movement */
32 int forw_scroll
; /* Repaint screen on forward movement */
33 int caseless
; /* Do "caseless" searches */
34 int linenums
; /* Use line numbers */
35 int autobuf
; /* Automatically allocate buffers as needed */
36 int bufspace
; /* Max buffer space per file (K) */
37 int ctldisp
; /* Send control chars to screen untranslated */
38 int force_open
; /* Open the file even if not regular file */
39 int swindow
; /* Size of scrolling window */
40 int jump_sline
; /* Screen line of "jump target" */
41 long jump_sline_fraction
= -1;
42 int chopline
; /* Truncate displayed lines at screen width */
43 int no_init
; /* Disable sending ti/te termcap strings */
44 int no_keypad
; /* Disable sending ks/ke termcap strings */
45 int twiddle
; /* Show tildes after EOF */
46 int show_attn
; /* Hilite first unread line */
47 int status_col
; /* Display a status column */
48 int use_lessopen
; /* Use the LESSOPEN filter */
49 int quit_on_intr
; /* Quit on interrupt */
50 int follow_mode
; /* F cmd Follows file desc or file name? */
51 int oldbot
; /* Old bottom of screen behavior {{REMOVE}} */
52 int opt_use_backslash
; /* Use backslash escaping in option parsing */
53 int hilite_search
; /* Highlight matched search patterns? */
55 int less_is_more
= 0; /* Make compatible with POSIX more */
60 static struct optname a_optname
= { "search-skip-screen", NULL
};
61 static struct optname b_optname
= { "buffers", NULL
};
62 static struct optname B__optname
= { "auto-buffers", NULL
};
63 static struct optname c_optname
= { "clear-screen", NULL
};
64 static struct optname d_optname
= { "dumb", NULL
};
65 static struct optname e_optname
= { "quit-at-eof", NULL
};
66 static struct optname f_optname
= { "force", NULL
};
67 static struct optname F__optname
= { "quit-if-one-screen", NULL
};
68 static struct optname g_optname
= { "hilite-search", NULL
};
69 static struct optname h_optname
= { "max-back-scroll", NULL
};
70 static struct optname i_optname
= { "ignore-case", NULL
};
71 static struct optname j_optname
= { "jump-target", NULL
};
72 static struct optname J__optname
= { "status-column", NULL
};
73 static struct optname k_optname
= { "lesskey-file", NULL
};
74 static struct optname K__optname
= { "quit-on-intr", NULL
};
75 static struct optname L__optname
= { "no-lessopen", NULL
};
76 static struct optname m_optname
= { "long-prompt", NULL
};
77 static struct optname n_optname
= { "line-numbers", NULL
};
78 static struct optname o_optname
= { "log-file", NULL
};
79 static struct optname O__optname
= { "LOG-FILE", NULL
};
80 static struct optname p_optname
= { "pattern", NULL
};
81 static struct optname P__optname
= { "prompt", NULL
};
82 static struct optname q2_optname
= { "silent", NULL
};
83 static struct optname q_optname
= { "quiet", &q2_optname
};
84 static struct optname r_optname
= { "raw-control-chars", NULL
};
85 static struct optname s_optname
= { "squeeze-blank-lines", NULL
};
86 static struct optname S__optname
= { "chop-long-lines", NULL
};
87 static struct optname t_optname
= { "tag", NULL
};
88 static struct optname T__optname
= { "tag-file", NULL
};
89 static struct optname u_optname
= { "underline-special", NULL
};
90 static struct optname V__optname
= { "version", NULL
};
91 static struct optname w_optname
= { "hilite-unread", NULL
};
92 static struct optname x_optname
= { "tabs", NULL
};
93 static struct optname X__optname
= { "no-init", NULL
};
94 static struct optname y_optname
= { "max-forw-scroll", NULL
};
95 static struct optname z_optname
= { "window", NULL
};
96 static struct optname quote_optname
= { "quotes", NULL
};
97 static struct optname tilde_optname
= { "tilde", NULL
};
98 static struct optname query_optname
= { "help", NULL
};
99 static struct optname pound_optname
= { "shift", NULL
};
100 static struct optname keypad_optname
= { "no-keypad", NULL
};
101 static struct optname oldbot_optname
= { "old-bot", NULL
};
102 static struct optname follow_optname
= { "follow-name", NULL
};
103 static struct optname use_backslash_optname
= { "use-backslash", NULL
};
107 * Table of all options and their semantics.
109 * For BOOL and TRIPLE options, odesc[0], odesc[1], odesc[2] are
110 * the description of the option when set to 0, 1 or 2, respectively.
111 * For NUMBER options, odesc[0] is the prompt to use when entering
112 * a new value, and odesc[1] is the description, which should contain
113 * one %d which is replaced by the value of the number.
114 * For STRING options, odesc[0] is the prompt to use when entering
115 * a new value, and odesc[1], if not NULL, is the set of characters
116 * that are valid in the string.
118 static struct loption option
[] = {
120 TRIPLE
, OPT_ONPLUS
, &how_search
, NULL
,
122 "Search includes displayed screen",
123 "Search skips displayed screen",
124 "Search includes all of displayed screen"
129 NUMBER
|INIT_HANDLER
, 64, &bufspace
, opt_b
,
131 "Max buffer space per file (K): ",
132 "Max buffer space per file: %dK",
137 BOOL
, OPT_ON
, &autobuf
, NULL
,
139 "Don't automatically allocate buffers",
140 "Automatically allocate buffers when needed",
145 TRIPLE
|MORE_OK
, OPT_ON
, &top_scroll
, NULL
,
147 "Repaint by scrolling from bottom of screen",
148 "Repaint by painting from top of screen",
149 "Repaint by painting from top of screen"
153 BOOL
|MORE_OK
|NO_TOGGLE
, OPT_OFF
, &know_dumb
, NULL
,
155 "Assume intelligent terminal",
156 "Assume dumb terminal",
161 TRIPLE
, OPT_OFF
, &quit_at_eof
, NULL
,
163 "Don't quit at end-of-file",
164 "Quit at end-of-file",
165 "Quit immediately at end-of-file"
169 BOOL
, OPT_OFF
, &force_open
, NULL
,
171 "Open only regular files",
172 "Open even non-regular files",
177 BOOL
, OPT_OFF
, &quit_if_one_screen
, NULL
,
179 "Don't quit if end-of-file on first screen",
180 "Quit if end-of-file on first screen",
185 TRIPLE
|HL_REPAINT
, OPT_ONPLUS
, &hilite_search
, NULL
,
187 "Don't highlight search matches",
188 "Highlight matches for previous search only",
189 "Highlight all matches for previous search pattern",
193 NUMBER
, -1, &back_scroll
, NULL
,
195 "Backwards scroll limit: ",
196 "Backwards scroll limit is %d lines",
201 TRIPLE
|HL_REPAINT
, OPT_OFF
, &caseless
, opt_i
,
203 "Case is significant in searches",
204 "Ignore case in searches",
205 "Ignore case in searches and in patterns"
209 STRING
, 0, NULL
, opt_j
,
217 BOOL
|REPAINT
, OPT_OFF
, &status_col
, NULL
,
219 "Don't display a status column",
220 "Display a status column",
225 STRING
|NO_TOGGLE
|NO_QUERY
, 0, NULL
, opt_k
,
229 BOOL
, OPT_OFF
, &quit_on_intr
, NULL
,
231 "Interrupt (ctrl-C) returns to prompt",
232 "Interrupt (ctrl-C) exits less",
237 BOOL
, OPT_ON
, &use_lessopen
, NULL
,
239 "Don't use the LESSOPEN filter",
240 "Use the LESSOPEN filter",
245 TRIPLE
, OPT_OFF
, &pr_type
, NULL
,
253 TRIPLE
|REPAINT
, OPT_ON
, &linenums
, NULL
,
255 "Don't use line numbers",
257 "Constantly display line numbers"
261 STRING
, 0, NULL
, opt_o
,
262 { "log file: ", NULL
, NULL
}
265 STRING
, 0, NULL
, opt__O
,
266 { "Log file: ", NULL
, NULL
}
269 STRING
|NO_TOGGLE
|NO_QUERY
|MORE_OK
, 0, NULL
, opt_p
,
273 STRING
, 0, NULL
, opt__P
,
274 { "prompt: ", NULL
, NULL
}
277 TRIPLE
, OPT_OFF
, &quiet
, NULL
,
279 "Ring the bell for errors AND at eof/bof",
280 "Ring the bell for errors but not at eof/bof",
281 "Never ring the bell"
285 TRIPLE
|REPAINT
, OPT_OFF
, &ctldisp
, NULL
,
287 "Display control characters as ^X",
288 "Display control characters directly",
289 "Display control characters directly, "
290 "processing ANSI sequences"
294 BOOL
|REPAINT
|MORE_OK
, OPT_OFF
, &squeeze
, NULL
,
296 "Display all blank lines",
297 "Squeeze multiple blank lines",
302 BOOL
|REPAINT
, OPT_OFF
, &chopline
, NULL
,
310 STRING
|NO_QUERY
|MORE_OK
, 0, NULL
, opt_t
,
311 { "tag: ", NULL
, NULL
}
314 STRING
|MORE_OK
, 0, NULL
, opt__T
,
315 { "tags file: ", NULL
, NULL
}
318 TRIPLE
|REPAINT
, OPT_OFF
, &bs_mode
, NULL
,
320 "Display underlined text in underline mode",
321 "Backspaces cause overstrike",
322 "Print backspace as ^H"
326 NOVAR
, 0, NULL
, opt__V
,
330 TRIPLE
|REPAINT
, OPT_OFF
, &show_attn
, NULL
,
332 "Don't highlight first unread line",
333 "Highlight first unread line after forward-screen",
334 "Highlight first unread line after any "
339 STRING
|REPAINT
, 0, NULL
, opt_x
,
347 BOOL
|NO_TOGGLE
, OPT_OFF
, &no_init
, NULL
,
349 "Send init/deinit strings to terminal",
350 "Don't use init/deinit strings",
355 NUMBER
, -1, &forw_scroll
, NULL
,
357 "Forward scroll limit: ",
358 "Forward scroll limit is %d lines",
363 NUMBER
, -1, &swindow
, NULL
,
365 "Scroll window size: ",
366 "Scroll window size is %d lines",
370 { '"', "e_optname
,
371 STRING
, 0, NULL
, opt_quote
,
372 { "quotes: ", NULL
, NULL
}
374 { '~', &tilde_optname
,
375 BOOL
|REPAINT
, OPT_ON
, &twiddle
, NULL
,
377 "Don't show tildes after end of file",
378 "Show tildes after end of file",
382 { '?', &query_optname
,
383 NOVAR
, 0, NULL
, opt_query
,
386 { '#', £_optname
,
387 STRING
, 0, NULL
, opt_shift
,
389 "Horizontal shift: ",
394 { OLETTER_NONE
, &keypad_optname
,
395 BOOL
|NO_TOGGLE
, OPT_OFF
, &no_keypad
, NULL
,
398 "Don't use keypad mode",
402 { OLETTER_NONE
, &oldbot_optname
,
403 BOOL
, OPT_OFF
, &oldbot
, NULL
,
405 "Use new bottom of screen behavior",
406 "Use old bottom of screen behavior",
410 { OLETTER_NONE
, &follow_optname
,
411 BOOL
, FOLLOW_DESC
, &follow_mode
, NULL
,
413 "F command follows file descriptor",
414 "F command follows file name",
418 { OLETTER_NONE
, &use_backslash_optname
,
419 BOOL
, OPT_OFF
, &opt_use_backslash
, NULL
,
421 "Use backslash escaping in command line parameters",
422 "Don't use backslash escaping in command line "
427 { '\0', NULL
, NOVAR
, 0, NULL
, NULL
, { NULL
, NULL
, NULL
} }
432 * Initialize each option to its default value.
439 for (o
= option
; o
->oletter
!= '\0'; o
++) {
441 * Set each variable to its default.
444 *(o
->ovar
) = o
->odefault
;
445 if (o
->otype
& INIT_HANDLER
)
446 (*(o
->ofunc
))(INIT
, NULL
);
451 * Find an option in the option table, given its option letter.
458 for (o
= option
; o
->oletter
!= '\0'; o
++) {
461 if ((o
->otype
& TRIPLE
) &&
462 (toupper((unsigned char)o
->oletter
) == c
))
472 is_optchar(unsigned char c
)
474 if (isupper(c
) || islower(c
) || c
== '-')
481 * Find an option in the option table, given its option name.
482 * p_optname is the (possibly partial) name to look for, and
483 * is updated to point after the matched name.
484 * p_oname if non-NULL is set to point to the full option name.
487 findopt_name(char **p_optname
, char **p_oname
, int *p_err
)
489 char *optname
= *p_optname
;
491 struct optname
*oname
;
494 struct loption
*maxo
= NULL
;
495 struct optname
*maxoname
= NULL
;
503 for (o
= option
; o
->oletter
!= '\0'; o
++) {
505 * Check all names for this option.
507 for (oname
= o
->onames
; oname
!= NULL
; oname
= oname
->onext
) {
509 * Try normal match first (uppercase == 0),
510 * then, then if it's a TRIPLE option,
511 * try uppercase match (uppercase == 1).
513 for (uppercase
= 0; uppercase
<= 1; uppercase
++) {
514 len
= sprefix(optname
, oname
->oname
, uppercase
);
515 if (len
<= 0 || is_optchar(optname
[len
])) {
517 * We didn't use all of the option name.
521 if (!exact
&& len
== maxlen
) {
523 * Already had a partial match,
524 * and now there's another one that
525 * matches the same length.
528 } else if (len
> maxlen
) {
530 * Found a better match than
537 exact
= (len
== strlen(oname
->oname
));
539 if (!(o
->otype
& TRIPLE
))
546 * Name matched more than one option.
552 *p_optname
= optname
+ maxlen
;
554 *p_oname
= maxoname
== NULL
? NULL
: maxoname
->oname
;