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