xref: /openbsd-src/usr.bin/less/optfunc.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: optfunc.c,v 1.2 2001/01/29 01:58:03 niklas Exp $	*/
2 
3 /*
4  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice in the documentation and/or other materials provided with
14  *    the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 
30 /*
31  * Handling functions for command line options.
32  *
33  * Most options are handled by the generic code in option.c.
34  * But all string options, and a few non-string options, require
35  * special handling specific to the particular option.
36  * This special processing is done by the "handling functions" in this file.
37  *
38  * Each handling function is passed a "type" and, if it is a string
39  * option, the string which should be "assigned" to the option.
40  * The type may be one of:
41  *	INIT	The option is being initialized from the command line.
42  *	TOGGLE	The option is being changed from within the program.
43  *	QUERY	The setting of the option is merely being queried.
44  */
45 
46 #include "less.h"
47 #include "option.h"
48 
49 extern int nbufs;
50 extern int cbufs;
51 extern int pr_type;
52 extern int nohelp;
53 extern int plusoption;
54 extern int swindow;
55 extern int sc_height;
56 extern int any_display;
57 extern char *prproto[];
58 extern char *eqproto;
59 extern IFILE curr_ifile;
60 #if LOGFILE
61 extern char *namelogfile;
62 extern int force_logfile;
63 extern int logfile;
64 #endif
65 #if TAGS
66 public char *tagoption = NULL;
67 extern char *tagfile;
68 extern char *tags;
69 extern int jump_sline;
70 #endif
71 #if MSOFTC
72 extern int nm_fg_color, nm_bg_color;
73 extern int bo_fg_color, bo_bg_color;
74 extern int ul_fg_color, ul_bg_color;
75 extern int so_fg_color, so_bg_color;
76 extern int bl_fg_color, bl_bg_color;
77 #endif
78 
79 
80 #if LOGFILE
81 /*
82  * Handler for -o option.
83  */
84 	public void
85 opt_o(type, s)
86 	int type;
87 	char *s;
88 {
89 	PARG parg;
90 
91 	switch (type)
92 	{
93 	case INIT:
94 		namelogfile = s;
95 		break;
96 	case TOGGLE:
97 		if (ch_getflags() & CH_CANSEEK)
98 		{
99 			error("Input is not a pipe", NULL_PARG);
100 			return;
101 		}
102 		if (logfile >= 0)
103 		{
104 			error("Log file is already in use", NULL_PARG);
105 			return;
106 		}
107 		s = skipsp(s);
108 		namelogfile = glob(s);
109 		use_logfile(namelogfile);
110 		sync_logfile();
111 		break;
112 	case QUERY:
113 		if (logfile < 0)
114 			error("No log file", NULL_PARG);
115 		else
116 		{
117 			parg.p_string = namelogfile;
118 			error("Log file \"%s\"", &parg);
119 		}
120 		break;
121 	}
122 }
123 
124 /*
125  * Handler for -O option.
126  */
127 	public void
128 opt__O(type, s)
129 	int type;
130 	char *s;
131 {
132 	force_logfile = TRUE;
133 	opt_o(type, s);
134 }
135 #endif
136 
137 /*
138  * Handlers for -l option.
139  */
140 	public void
141 opt_l(type, s)
142 	int type;
143 	char *s;
144 {
145 	int err;
146 	int n;
147 	char *t;
148 
149 	switch (type)
150 	{
151 	case INIT:
152 		t = s;
153 		n = getnum(&t, 'l', &err);
154 		if (err || n <= 0)
155 		{
156 			error("Line number is required after -l", NULL_PARG);
157 			return;
158 		}
159 		plusoption = TRUE;
160 		ungetsc(s);
161 		break;
162 	}
163 }
164 
165 #if USERFILE
166 	public void
167 opt_k(type, s)
168 	int type;
169 	char *s;
170 {
171 	PARG parg;
172 
173 	switch (type)
174 	{
175 	case INIT:
176 		if (lesskey(s))
177 		{
178 			parg.p_string = s;
179 			error("Cannot use lesskey file \"%s\"", &parg);
180 		}
181 		break;
182 	}
183 }
184 #endif
185 
186 #if TAGS
187 /*
188  * Handler for -t option.
189  */
190 	public void
191 opt_t(type, s)
192 	int type;
193 	char *s;
194 {
195 	IFILE save_ifile;
196 	POSITION pos;
197 
198 	switch (type)
199 	{
200 	case INIT:
201 		tagoption = s;
202 		/* Do the rest in main() */
203 		break;
204 	case TOGGLE:
205 		findtag(skipsp(s));
206 		if (tagfile == NULL)
207 			break;
208 		save_ifile = curr_ifile;
209 		if (edit(tagfile))
210 			break;
211 		if ((pos = tagsearch()) == NULL_POSITION)
212 		{
213 			if (edit_ifile(save_ifile))
214 				quit(QUIT_ERROR);
215 			break;
216 		}
217 		jump_loc(pos, jump_sline);
218 		break;
219 	}
220 }
221 
222 /*
223  * Handler for -T option.
224  */
225 	public void
226 opt__T(type, s)
227 	int type;
228 	char *s;
229 {
230 	PARG parg;
231 
232 	switch (type)
233 	{
234 	case INIT:
235 		tags = s;
236 		break;
237 	case TOGGLE:
238 		s = skipsp(s);
239 		tags = glob(s);
240 		break;
241 	case QUERY:
242 		parg.p_string = tags;
243 		error("Tags file \"%s\"", &parg);
244 		break;
245 	}
246 }
247 #endif
248 
249 /*
250  * Handler for -p option.
251  */
252 	public void
253 opt_p(type, s)
254 	int type;
255 	register char *s;
256 {
257 	switch (type)
258 	{
259 	case INIT:
260 		/*
261 		 * Unget a search command for the specified string.
262 		 * {{ This won't work if the "/" command is
263 		 *    changed or invalidated by a .lesskey file. }}
264 		 */
265 		plusoption = TRUE;
266 		ungetsc(s);
267 		ungetsc("/");
268 		break;
269 	}
270 }
271 
272 /*
273  * Handler for -P option.
274  */
275 	public void
276 opt__P(type, s)
277 	int type;
278 	register char *s;
279 {
280 	register char **proto;
281 	PARG parg;
282 
283 	switch (type)
284 	{
285 	case INIT:
286 	case TOGGLE:
287 		/*
288 		 * Figure out which prototype string should be changed.
289 		 */
290 		switch (*s)
291 		{
292 		case 'm':  proto = &prproto[PR_MEDIUM];	s++;	break;
293 		case 'M':  proto = &prproto[PR_LONG];	s++;	break;
294 		case '=':  proto = &eqproto;		s++;	break;
295 		default:   proto = &prproto[PR_SHORT];		break;
296 		}
297 		free(*proto);
298 		*proto = save(s);
299 		break;
300 	case QUERY:
301 		parg.p_string = prproto[pr_type];
302 		error("%s", &parg);
303 		break;
304 	}
305 }
306 
307 /*
308  * Handler for the -b option.
309  */
310 	/*ARGSUSED*/
311 	public void
312 opt_b(type, s)
313 	int type;
314 	char *s;
315 {
316 	switch (type)
317 	{
318 	case TOGGLE:
319 	case QUERY:
320 		/*
321 		 * Allocate the new number of buffers.
322 		 */
323 		cbufs = ch_nbuf(cbufs);
324 		break;
325 	case INIT:
326 		break;
327 	}
328 }
329 
330 /*
331  * Handler for the -i option.
332  */
333 	/*ARGSUSED*/
334 	public void
335 opt_i(type, s)
336 	int type;
337 	char *s;
338 {
339 	switch (type)
340 	{
341 	case TOGGLE:
342 		chg_caseless();
343 		break;
344 	case QUERY:
345 	case INIT:
346 		break;
347 	}
348 }
349 
350 /*
351  * Handler for the -V option.
352  */
353 	/*ARGSUSED*/
354 	public void
355 opt__V(type, s)
356 	int type;
357 	char *s;
358 {
359 	switch (type)
360 	{
361 	case TOGGLE:
362 	case QUERY:
363 	case INIT:
364 		dispversion();
365 		if (type == INIT)
366 			quit(QUIT_OK);
367 		break;
368 	}
369 }
370 
371 #if MSOFTC
372 /*
373  *
374  */
375    	static void
376 colordesc(s, fg_color, bg_color)
377 	char *s;
378 	int *fg_color;
379 	int *bg_color;
380 {
381 	int fg, bg;
382 	int err;
383 
384 	fg = getnum(&s, 'D', &err);
385 	if (err)
386 	{
387 		error("Missing fg color in -D", NULL_PARG);
388 		return;
389 	}
390 	if (*s != '.')
391 		bg = 0;
392 	else
393 	{
394 		s++;
395 		bg = getnum(&s, 'D', &err);
396 		if (err)
397 		{
398 			error("Missing fg color in -D", NULL_PARG);
399 			return;
400 		}
401 	}
402 	*fg_color = fg;
403 	*bg_color = bg;
404 }
405 
406 /*
407  * Handler for the -D option.
408  */
409 	/*ARGSUSED*/
410 	public void
411 opt_D(type, s)
412 	int type;
413 	char *s;
414 {
415 	switch (type)
416 	{
417 	case INIT:
418 	case TOGGLE:
419 		switch (*s++)
420 		{
421 		case 'n':
422 			colordesc(s, &nm_fg_color, &nm_bg_color);
423 			break;
424 		case 'd':
425 			colordesc(s, &bo_fg_color, &bo_bg_color);
426 			break;
427 		case 'u':
428 			colordesc(s, &ul_fg_color, &ul_bg_color);
429 			break;
430 		case 'k':
431 			colordesc(s, &bl_fg_color, &bl_bg_color);
432 			break;
433 		case 's':
434 			colordesc(s, &so_fg_color, &so_bg_color);
435 			break;
436 		default:
437 			error("-D must be followed by n, d, u, k or s", NULL_PARG);
438 			break;
439 		}
440 		if (type == TOGGLE)
441 		{
442 			so_enter();
443 			so_exit();
444 		}
445 		break;
446 	case QUERY:
447 		break;
448 	}
449 }
450 #endif
451 
452 /*
453  * "-?" means display a help message.
454  * If from the command line, exit immediately.
455  */
456 	/*ARGSUSED*/
457 	public void
458 opt_query(type, s)
459 	int type;
460 	char *s;
461 {
462 	if (nohelp)
463 		return;
464 	switch (type)
465 	{
466 	case QUERY:
467 	case TOGGLE:
468 		error("Use \"h\" for help", NULL_PARG);
469 		break;
470 	case INIT:
471 		/*
472 		 * This is "less -?".
473 		 * It rather ungracefully grabs control,
474 		 * does the initializations normally done in main,
475 		 * shows the help file and exits.
476 		 */
477 		raw_mode(1);
478 		get_term();
479 		open_getchr();
480 		init();
481 		any_display = TRUE;
482 		help(1);
483 		quit(QUIT_OK);
484 		/*NOTREACHED*/
485 	}
486 }
487 
488 /*
489  * Get the "screen window" size.
490  */
491 	public int
492 get_swindow()
493 {
494 	if (swindow > 0)
495 		return (swindow);
496 	return (sc_height + swindow);
497 }
498 
499