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