xref: /freebsd/contrib/less/opttbl.c (revision 64db83a8ab2d1f72a9b2174b39d2ef42b5b0580c)
1 /*
2  * Copyright (C) 1984-2000  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 about less, or for information on how to
8  * contact the author, see the README file.
9  */
10 
11 
12 /*
13  * The option table.
14  */
15 
16 #include "less.h"
17 #include "option.h"
18 
19 /*
20  * Variables controlled by command line options.
21  */
22 public int quiet;		/* Should we suppress the audible 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 cbufs;		/* Current number of buffers */
38 public int autobuf;		/* Automatically allocate buffers as needed */
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 chopline;		/* Truncate displayed lines at screen width */
44 public int no_init;		/* Disable sending ti/te termcap strings */
45 public int twiddle;             /* Show tildes after EOF */
46 public int show_attn;		/* Hilite first unread line */
47 #if HILITE_SEARCH
48 public int hilite_search;	/* Highlight matched search patterns? */
49 #endif
50 
51 /*
52  * Long option names.
53  */
54 static struct optname a_optname      = { "search-skip-screen",   NULL };
55 static struct optname b_optname      = { "buffers",              NULL };
56 static struct optname B__optname     = { "auto-buffers",         NULL };
57 static struct optname c_optname      = { "clear-screen",         NULL };
58 static struct optname d_optname      = { "dumb",                 NULL };
59 #if MSDOS_COMPILER
60 static struct optname D__optname     = { "color",                NULL };
61 #endif
62 static struct optname e_optname      = { "quit-at-eof",          NULL };
63 static struct optname f_optname      = { "force",                NULL };
64 static struct optname F__optname     = { "quit-if-one-screen",   NULL };
65 #if HILITE_SEARCH
66 static struct optname g_optname      = { "hilite-search",        NULL };
67 #endif
68 static struct optname h_optname      = { "max-back-scroll",      NULL };
69 static struct optname i_optname      = { "ignore-case",          NULL };
70 static struct optname j_optname      = { "jump-target",          NULL };
71 #if USERFILE
72 static struct optname k_optname      = { "lesskey-file",         NULL };
73 #endif
74 static struct optname m_optname      = { "long-prompt",          NULL };
75 static struct optname n_optname      = { "line-numbers",         NULL };
76 #if LOGFILE
77 static struct optname o_optname      = { "log-file",             NULL };
78 static struct optname O__optname     = { "LOG-FILE",             NULL };
79 #endif
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 #if TAGS
88 static struct optname t_optname      = { "tag",                  NULL };
89 static struct optname T__optname     = { "tag-file",             NULL };
90 #endif
91 static struct optname u_optname      = { "underline-special",    NULL };
92 static struct optname V__optname     = { "version",              NULL };
93 static struct optname w_optname      = { "hilite-unread",        NULL };
94 static struct optname x_optname      = { "tabs",                 NULL };
95 static struct optname X__optname     = { "no-init",              NULL };
96 static struct optname y_optname      = { "max-forw-scroll",      NULL };
97 static struct optname z_optname      = { "window",               NULL };
98 static struct optname quote_optname  = { "quotes",               NULL };
99 static struct optname tilde_optname  = { "tilde",                NULL };
100 static struct optname query_optname  = { "help",                 NULL };
101 
102 
103 /*
104  * Table of all options and their semantics.
105  */
106 static struct option option[] =
107 {
108 	{ 'a', &a_optname,
109 		BOOL, OPT_OFF, &how_search, NULL,
110 		"Search includes displayed screen",
111 		"Search skips displayed screen",
112 		NULL
113 	},
114 
115 	{ 'b', &b_optname,
116 		NUMBER, 10, &cbufs, opt_b,
117 		"Buffers: ",
118 		"%d buffers",
119 		NULL
120 	},
121 	{ 'B', &B__optname,
122 		BOOL, OPT_ON, &autobuf, NULL,
123 		"Don't automatically allocate buffers",
124 		"Automatically allocate buffers when needed",
125 		NULL
126 	},
127 	{ 'c', &c_optname,
128 		TRIPLE, OPT_OFF, &top_scroll, NULL,
129 		"Repaint by scrolling from bottom of screen",
130 		"Repaint by clearing each line",
131 		"Repaint by painting from top of screen"
132 	},
133 	{ 'd', &d_optname,
134 		BOOL|NO_TOGGLE, OPT_OFF, &know_dumb, NULL,
135 		"Assume intelligent terminal",
136 		"Assume dumb terminal",
137 		NULL
138 	},
139 #if MSDOS_COMPILER
140 	{ 'D', &D__optname,
141 		STRING|REPAINT|NO_QUERY, 0, NULL, opt_D,
142 		"color desc: ", NULL, NULL
143 	},
144 #endif
145 	{ 'e', &e_optname,
146 		TRIPLE, OPT_OFF, &quit_at_eof, NULL,
147 		"Don't quit at end-of-file",
148 		"Quit at end-of-file",
149 		"Quit immediately at end-of-file"
150 	},
151 	{ 'f', &f_optname,
152 		BOOL, OPT_OFF, &force_open, NULL,
153 		"Open only regular files",
154 		"Open even non-regular files",
155 		NULL
156 	},
157 	{ 'F', &F__optname,
158 		BOOL, OPT_OFF, &quit_if_one_screen, NULL,
159 		"Don't quit if end-of-file on first screen",
160 		"Quit if end-of-file on first screen",
161 		NULL
162 	},
163 #if HILITE_SEARCH
164 	{ 'g', &g_optname,
165 		TRIPLE|HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL,
166 		"Don't highlight search matches",
167 		"Highlight matches for previous search only",
168 		"Highlight all matches for previous search pattern",
169 	},
170 #endif
171 	{ 'h', &h_optname,
172 		NUMBER, -1, &back_scroll, NULL,
173 		"Backwards scroll limit: ",
174 		"Backwards scroll limit is %d lines",
175 		NULL
176 	},
177 	{ 'i', &i_optname,
178 		TRIPLE|HL_REPAINT, OPT_OFF, &caseless, opt_i,
179 		"Case is significant in searches",
180 		"Ignore case in searches",
181 		"Ignore case in searches and in patterns"
182 	},
183 	{ 'j', &j_optname,
184 		NUMBER, 1, &jump_sline, NULL,
185 		"Target line: ",
186 		"Position target at screen line %d",
187 		NULL
188 	},
189 #if USERFILE
190 	{ 'k', &k_optname,
191 		STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k,
192 		NULL, NULL, NULL
193 	},
194 #endif
195 	{ 'l', NULL,
196 		STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_l,
197 		NULL, NULL, NULL
198 	},
199 	{ 'm', &m_optname,
200 		TRIPLE, OPT_OFF, &pr_type, NULL,
201 		"Short prompt",
202 		"Medium prompt",
203 		"Long prompt"
204 	},
205 	{ 'n', &n_optname,
206 		TRIPLE|REPAINT, OPT_ON, &linenums, NULL,
207 		"Don't use line numbers",
208 		"Use line numbers",
209 		"Constantly display line numbers"
210 	},
211 #if LOGFILE
212 	{ 'o', &o_optname,
213 		STRING, 0, NULL, opt_o,
214 		"log file: ", NULL, NULL
215 	},
216 	{ 'O', &O__optname,
217 		STRING, 0, NULL, opt__O,
218 		"Log file: ", NULL, NULL
219 	},
220 #endif
221 	{ 'p', &p_optname,
222 		STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_p,
223 		NULL, NULL, NULL
224 	},
225 	{ 'P', &P__optname,
226 		STRING, 0, NULL, opt__P,
227 		"prompt: ", NULL, NULL
228 	},
229 	{ 'q', &q_optname,
230 		TRIPLE, OPT_OFF, &quiet, NULL,
231 		"Ring the bell for errors AND at eof/bof",
232 		"Ring the bell for errors but not at eof/bof",
233 		"Never ring the bell"
234 	},
235 	{ 'r', &r_optname,
236 		TRIPLE|REPAINT, OPT_OFF, &ctldisp, NULL,
237 		"Display control characters as ^X",
238 		"Display control characters directly",
239 		"Display control characters directly, processing ANSI sequences"
240 	},
241 	{ 's', &s_optname,
242 		BOOL|REPAINT, OPT_OFF, &squeeze, NULL,
243 		"Display all blank lines",
244 		"Squeeze multiple blank lines",
245 		NULL
246 	},
247 	{ 'S', &S__optname,
248 		BOOL|REPAINT, OPT_OFF, &chopline, NULL,
249 		"Fold long lines",
250 		"Chop long lines",
251 		NULL
252 	},
253 #if TAGS
254 	{ 't', &t_optname,
255 		STRING|NO_QUERY, 0, NULL, opt_t,
256 		"tag: ", NULL, NULL
257 	},
258 	{ 'T', &T__optname,
259 		STRING, 0, NULL, opt__T,
260 		"tags file: ", NULL, NULL
261 	},
262 #endif
263 	{ 'u', &u_optname,
264 		TRIPLE|REPAINT, OPT_OFF, &bs_mode, NULL,
265 		"Display underlined text in underline mode",
266 		"Backspaces cause overstrike",
267 		"Print backspace as ^H"
268 	},
269 	{ 'V', &V__optname,
270 		NOVAR, 0, NULL, opt__V,
271 		NULL, NULL, NULL
272 	},
273 	{ 'w', &w_optname,
274 		TRIPLE|REPAINT, OPT_OFF, &show_attn, NULL,
275 		"Don't highlight first unread line",
276 		"Highlight first unread line after forward-screen",
277 		"Highlight first unread line after any forward movement",
278 	},
279 	{ 'x', &x_optname,
280 		NUMBER|REPAINT, 8, &tabstop, NULL,
281 		"Tab stops: ",
282 		"Tab stops every %d spaces",
283 		NULL
284 	},
285 	{ 'X', &X__optname,
286 		BOOL|NO_TOGGLE, OPT_OFF, &no_init, NULL,
287 		"Send init/deinit strings to terminal",
288 		"Don't use init/deinit strings",
289 		NULL
290 	},
291 	{ 'y', &y_optname,
292 		NUMBER, -1, &forw_scroll, NULL,
293 		"Forward scroll limit: ",
294 		"Forward scroll limit is %d lines",
295 		NULL
296 	},
297 	{ 'z', &z_optname,
298 		NUMBER, -1, &swindow, NULL,
299 		"Scroll window size: ",
300 		"Scroll window size is %d lines",
301 		NULL
302 	},
303 	{ '"', &quote_optname,
304 		STRING, 0, NULL, opt_quote,
305 		"quotes: ", NULL, NULL
306 	},
307 	{ '~', &tilde_optname,
308 		BOOL|REPAINT, OPT_ON, &twiddle, NULL,
309 		"Don't show tildes after end of file",
310 		"Show tildes after end of file",
311 		NULL
312 	},
313 	{ '?', &query_optname,
314 		NOVAR, 0, NULL, opt_query,
315 		NULL, NULL, NULL
316 	},
317 	{ '\0', NULL, NOVAR, 0, NULL, NULL, NULL, NULL, NULL }
318 };
319 
320 
321 /*
322  * Initialize each option to its default value.
323  */
324 	public void
325 init_option()
326 {
327 	register struct option *o;
328 
329 	for (o = option;  o->oletter != '\0';  o++)
330 	{
331 		/*
332 		 * Set each variable to its default.
333 		 */
334 		if (o->ovar != NULL)
335 			*(o->ovar) = o->odefault;
336 	}
337 }
338 
339 /*
340  * Find an option in the option table, given its option letter.
341  */
342 	public struct option *
343 findopt(c)
344 	int c;
345 {
346 	register struct option *o;
347 
348 	for (o = option;  o->oletter != '\0';  o++)
349 	{
350 		if (o->oletter == c)
351 			return (o);
352 		if ((o->otype & TRIPLE) && toupper(o->oletter) == c)
353 			return (o);
354 	}
355 	return (NULL);
356 }
357 
358 /*
359  * Find an option in the option table, given its option name.
360  * p_optname is the (possibly partial) name to look for, and
361  * is updated to point after the matched name.
362  * p_oname if non-NULL is set to point to the full option name.
363  */
364 	public struct option *
365 findopt_name(p_optname, p_oname, p_err)
366 	char **p_optname;
367 	char **p_oname;
368 	int *p_err;
369 {
370 	char *optname = *p_optname;
371 	register struct option *o;
372 	register struct optname *oname;
373 	register int len;
374 	int uppercase;
375 	struct option *maxo = NULL;
376 	struct optname *maxoname = NULL;
377 	int maxlen = 0;
378 	int ambig = 0;
379 	int exact = 0;
380 
381 	/*
382 	 * Check all options.
383 	 */
384 	for (o = option;  o->oletter != '\0';  o++)
385 	{
386 		/*
387 		 * Check all names for this option.
388 		 */
389 		for (oname = o->onames;  oname != NULL;  oname = oname->onext)
390 		{
391 			/*
392 			 * Try normal match first (uppercase == 0),
393 			 * then, then if it's a TRIPLE option,
394 			 * try uppercase match (uppercase == 1).
395 			 */
396 			for (uppercase = 0;  uppercase <= 1;  uppercase++)
397 			{
398 				len = sprefix(optname, oname->oname, uppercase);
399 				if (!exact && len == maxlen)
400 					/*
401 					 * Already had a partial match,
402 					 * and now there's another one that
403 					 * matches the same length.
404 					 */
405 					ambig = 1;
406 				else if (len > maxlen)
407 				{
408 					/*
409 					 * Found a better match than
410 					 * the one we had.
411 					 */
412 					maxo = o;
413 					maxoname = oname;
414 					maxlen = len;
415 					ambig = 0;
416 					exact = (len == strlen(oname->oname));
417 				}
418 				if (!(o->otype & TRIPLE))
419 					break;
420 			}
421 		}
422 	}
423 	if (ambig)
424 	{
425 		/*
426 		 * Name matched more than one option.
427 		 */
428 		if (p_err != NULL)
429 			*p_err = OPT_AMBIG;
430 		return (NULL);
431 	}
432 	*p_optname = optname + maxlen;
433 	if (p_oname != NULL)
434 		*p_oname = maxoname->oname;
435 	return (maxo);
436 }
437