xref: /freebsd/contrib/less/optfunc.c (revision 6990ffd8a95caaba6858ad44ff1b3157d1efba8f)
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  * Handling functions for command line options.
14  *
15  * Most options are handled by the generic code in option.c.
16  * But all string options, and a few non-string options, require
17  * special handling specific to the particular option.
18  * This special processing is done by the "handling functions" in this file.
19  *
20  * Each handling function is passed a "type" and, if it is a string
21  * option, the string which should be "assigned" to the option.
22  * The type may be one of:
23  *	INIT	The option is being initialized from the command line.
24  *	TOGGLE	The option is being changed from within the program.
25  *	QUERY	The setting of the option is merely being queried.
26  */
27 
28 #include "less.h"
29 #include "option.h"
30 
31 extern int nbufs;
32 extern int cbufs;
33 extern int pr_type;
34 extern int plusoption;
35 extern int swindow;
36 extern int sc_height;
37 extern int secure;
38 extern int dohelp;
39 extern int any_display;
40 extern char openquote;
41 extern char closequote;
42 extern char *prproto[];
43 extern char *eqproto;
44 extern char *hproto;
45 extern IFILE curr_ifile;
46 extern char version[];
47 #if LOGFILE
48 extern char *namelogfile;
49 extern int force_logfile;
50 extern int logfile;
51 #endif
52 #if TAGS
53 public char *tagoption = NULL;
54 extern char *tags;
55 extern int jump_sline;
56 #endif
57 #if MSDOS_COMPILER
58 extern int nm_fg_color, nm_bg_color;
59 extern int bo_fg_color, bo_bg_color;
60 extern int ul_fg_color, ul_bg_color;
61 extern int so_fg_color, so_bg_color;
62 extern int bl_fg_color, bl_bg_color;
63 #endif
64 
65 
66 #if LOGFILE
67 /*
68  * Handler for -o option.
69  */
70 	public void
71 opt_o(type, s)
72 	int type;
73 	char *s;
74 {
75 	PARG parg;
76 
77 	if (secure)
78 	{
79 		error("log file support is not available", NULL_PARG);
80 		return;
81 	}
82 	switch (type)
83 	{
84 	case INIT:
85 		namelogfile = s;
86 		break;
87 	case TOGGLE:
88 		if (ch_getflags() & CH_CANSEEK)
89 		{
90 			error("Input is not a pipe", NULL_PARG);
91 			return;
92 		}
93 		if (logfile >= 0)
94 		{
95 			error("Log file is already in use", NULL_PARG);
96 			return;
97 		}
98 		s = skipsp(s);
99 		namelogfile = lglob(s);
100 		use_logfile(namelogfile);
101 		sync_logfile();
102 		break;
103 	case QUERY:
104 		if (logfile < 0)
105 			error("No log file", NULL_PARG);
106 		else
107 		{
108 			parg.p_string = unquote_file(namelogfile);
109 			error("Log file \"%s\"", &parg);
110 			free(parg.p_string);
111 		}
112 		break;
113 	}
114 }
115 
116 /*
117  * Handler for -O option.
118  */
119 	public void
120 opt__O(type, s)
121 	int type;
122 	char *s;
123 {
124 	force_logfile = TRUE;
125 	opt_o(type, s);
126 }
127 #endif
128 
129 /*
130  * Handlers for -l option.
131  */
132 	public void
133 opt_l(type, s)
134 	int type;
135 	char *s;
136 {
137 	int err;
138 	int n;
139 	char *t;
140 
141 	switch (type)
142 	{
143 	case INIT:
144 		t = s;
145 		n = getnum(&t, 'l', &err);
146 		if (err || n <= 0)
147 		{
148 			error("Line number is required after -l", NULL_PARG);
149 			return;
150 		}
151 		plusoption = TRUE;
152 		ungetsc(s);
153 		break;
154 	}
155 }
156 
157 #if USERFILE
158 	public void
159 opt_k(type, s)
160 	int type;
161 	char *s;
162 {
163 	PARG parg;
164 
165 	switch (type)
166 	{
167 	case INIT:
168 		if (lesskey(s, 0))
169 		{
170 			parg.p_string = unquote_file(s);
171 			error("Cannot use lesskey file \"%s\"", &parg);
172 			free(parg.p_string);
173 		}
174 		break;
175 	}
176 }
177 #endif
178 
179 #if TAGS
180 /*
181  * Handler for -t option.
182  */
183 	public void
184 opt_t(type, s)
185 	int type;
186 	char *s;
187 {
188 	IFILE save_ifile;
189 	POSITION pos;
190 
191 	switch (type)
192 	{
193 	case INIT:
194 		tagoption = s;
195 		/* Do the rest in main() */
196 		break;
197 	case TOGGLE:
198 		if (secure)
199 		{
200 			error("tags support is not available", NULL_PARG);
201 			break;
202 		}
203 		findtag(skipsp(s));
204 		save_ifile = save_curr_ifile();
205 		if (edit_tagfile())
206 			break;
207 		if ((pos = tagsearch()) == NULL_POSITION)
208 		{
209 			reedit_ifile(save_ifile);
210 			break;
211 		}
212 		unsave_ifile(save_ifile);
213 		jump_loc(pos, jump_sline);
214 		break;
215 	}
216 }
217 
218 /*
219  * Handler for -T option.
220  */
221 	public void
222 opt__T(type, s)
223 	int type;
224 	char *s;
225 {
226 	PARG parg;
227 
228 	switch (type)
229 	{
230 	case INIT:
231 		tags = s;
232 		break;
233 	case TOGGLE:
234 		s = skipsp(s);
235 		tags = lglob(s);
236 		break;
237 	case QUERY:
238 		parg.p_string = unquote_file(tags);
239 		error("Tags file \"%s\"", &parg);
240 		free(parg.p_string);
241 		break;
242 	}
243 }
244 #endif
245 
246 /*
247  * Handler for -p option.
248  */
249 	public void
250 opt_p(type, s)
251 	int type;
252 	register char *s;
253 {
254 	switch (type)
255 	{
256 	case INIT:
257 		/*
258 		 * Unget a search command for the specified string.
259 		 * {{ This won't work if the "/" command is
260 		 *    changed or invalidated by a .lesskey file. }}
261 		 */
262 		plusoption = TRUE;
263 		ungetsc(s);
264 		ungetsc("/");
265 		break;
266 	}
267 }
268 
269 /*
270  * Handler for -P option.
271  */
272 	public void
273 opt__P(type, s)
274 	int type;
275 	register char *s;
276 {
277 	register char **proto;
278 	PARG parg;
279 
280 	switch (type)
281 	{
282 	case INIT:
283 	case TOGGLE:
284 		/*
285 		 * Figure out which prototype string should be changed.
286 		 */
287 		switch (*s)
288 		{
289 		case 's':  proto = &prproto[PR_SHORT];	s++;	break;
290 		case 'm':  proto = &prproto[PR_MEDIUM];	s++;	break;
291 		case 'M':  proto = &prproto[PR_LONG];	s++;	break;
292 		case '=':  proto = &eqproto;		s++;	break;
293 		case 'h':  proto = &hproto;		s++;	break;
294 		default:   proto = &prproto[PR_SHORT];		break;
295 		}
296 		free(*proto);
297 		*proto = save(s);
298 		break;
299 	case QUERY:
300 		parg.p_string = prproto[pr_type];
301 		error("%s", &parg);
302 		break;
303 	}
304 }
305 
306 /*
307  * Handler for the -b option.
308  */
309 	/*ARGSUSED*/
310 	public void
311 opt_b(type, s)
312 	int type;
313 	char *s;
314 {
315 	switch (type)
316 	{
317 	case TOGGLE:
318 	case QUERY:
319 		/*
320 		 * Allocate the new number of buffers.
321 		 */
322 		cbufs = ch_nbuf(cbufs);
323 		break;
324 	case INIT:
325 		break;
326 	}
327 }
328 
329 /*
330  * Handler for the -i option.
331  */
332 	/*ARGSUSED*/
333 	public void
334 opt_i(type, s)
335 	int type;
336 	char *s;
337 {
338 	switch (type)
339 	{
340 	case TOGGLE:
341 		chg_caseless();
342 		break;
343 	case QUERY:
344 	case INIT:
345 		break;
346 	}
347 }
348 
349 /*
350  * Handler for the -V option.
351  */
352 	/*ARGSUSED*/
353 	public void
354 opt__V(type, s)
355 	int type;
356 	char *s;
357 {
358 	switch (type)
359 	{
360 	case TOGGLE:
361 	case QUERY:
362 		dispversion();
363 		break;
364 	case INIT:
365 		/*
366 		 * Force output to stdout per GNU standard for --version output.
367 		 */
368 		any_display = 1;
369 		putstr("less ");
370 		putstr(version);
371 		putstr("\nCopyright (C) 2000 Mark Nudelman\n\n");
372 		putstr("less comes with NO WARRANTY, to the extent permitted by law.\n");
373 		putstr("For information about the terms of redistribution,\n");
374 		putstr("see the file named README in the less distribution.\n");
375 		quit(QUIT_OK);
376 		break;
377 	}
378 }
379 
380 #if MSDOS_COMPILER
381 /*
382  * Parse an MSDOS color descriptor.
383  */
384    	static void
385 colordesc(s, fg_color, bg_color)
386 	char *s;
387 	int *fg_color;
388 	int *bg_color;
389 {
390 	int fg, bg;
391 	int err;
392 
393 	fg = getnum(&s, 'D', &err);
394 	if (err)
395 	{
396 		error("Missing fg color in -D", NULL_PARG);
397 		return;
398 	}
399 	if (*s != '.')
400 		bg = 0;
401 	else
402 	{
403 		s++;
404 		bg = getnum(&s, 'D', &err);
405 		if (err)
406 		{
407 			error("Missing fg color in -D", NULL_PARG);
408 			return;
409 		}
410 	}
411 	if (*s != '\0')
412 		error("Extra characters at end of -D option", NULL_PARG);
413 	*fg_color = fg;
414 	*bg_color = bg;
415 }
416 
417 /*
418  * Handler for the -D option.
419  */
420 	/*ARGSUSED*/
421 	public void
422 opt_D(type, s)
423 	int type;
424 	char *s;
425 {
426 	switch (type)
427 	{
428 	case INIT:
429 	case TOGGLE:
430 		switch (*s++)
431 		{
432 		case 'n':
433 			colordesc(s, &nm_fg_color, &nm_bg_color);
434 			break;
435 		case 'd':
436 			colordesc(s, &bo_fg_color, &bo_bg_color);
437 			break;
438 		case 'u':
439 			colordesc(s, &ul_fg_color, &ul_bg_color);
440 			break;
441 		case 'k':
442 			colordesc(s, &bl_fg_color, &bl_bg_color);
443 			break;
444 		case 's':
445 			colordesc(s, &so_fg_color, &so_bg_color);
446 			break;
447 		default:
448 			error("-D must be followed by n, d, u, k or s", NULL_PARG);
449 			break;
450 		}
451 		if (type == TOGGLE)
452 		{
453 			so_enter();
454 			so_exit();
455 		}
456 		break;
457 	case QUERY:
458 		break;
459 	}
460 }
461 #endif
462 
463 /*
464  * Handler for the -" option.
465  */
466 	public void
467 opt_quote(type, s)
468 	int type;
469 	register char *s;
470 {
471 	char buf[3];
472 	PARG parg;
473 
474 	switch (type)
475 	{
476 	case INIT:
477 	case TOGGLE:
478 		if (s[1] != '\0' && s[2] != '\0')
479 		{
480 			error("-\" must be followed by 1 or 2 chars", NULL_PARG);
481 			return;
482 		}
483 		openquote = s[0];
484 		if (s[1] == '\0')
485 			closequote = openquote;
486 		else
487 			closequote = s[1];
488 		break;
489 	case QUERY:
490 		buf[0] = openquote;
491 		buf[1] = closequote;
492 		buf[2] = '\0';
493 		parg.p_string = buf;
494 		error("quotes %s", &parg);
495 		break;
496 	}
497 }
498 
499 /*
500  * "-?" means display a help message.
501  * If from the command line, exit immediately.
502  */
503 	/*ARGSUSED*/
504 	public void
505 opt_query(type, s)
506 	int type;
507 	char *s;
508 {
509 	switch (type)
510 	{
511 	case QUERY:
512 	case TOGGLE:
513 		error("Use \"h\" for help", NULL_PARG);
514 		break;
515 	case INIT:
516 		dohelp = 1;
517 	}
518 }
519 
520 /*
521  * Get the "screen window" size.
522  */
523 	public int
524 get_swindow()
525 {
526 	if (swindow > 0)
527 		return (swindow);
528 	return (sc_height + swindow);
529 }
530 
531