Annotation of src/usr.bin/less/optfunc.c, Revision 1.5
1.1 etheisen 1: /*
1.4 millert 2: * Copyright (C) 1984-2002 Mark Nudelman
1.1 etheisen 3: *
1.4 millert 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.
1.1 etheisen 6: *
1.4 millert 7: * For more information about less, or for information on how to
8: * contact the author, see the README file.
1.1 etheisen 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;
1.4 millert 32: extern int bufspace;
1.1 etheisen 33: extern int pr_type;
1.5 ! millert 34: extern int nohelp;
1.1 etheisen 35: extern int plusoption;
36: extern int swindow;
37: extern int sc_height;
1.4 millert 38: extern int secure;
1.1 etheisen 39: extern int any_display;
1.4 millert 40: extern char openquote;
41: extern char closequote;
1.1 etheisen 42: extern char *prproto[];
43: extern char *eqproto;
1.4 millert 44: extern char *hproto;
45: extern char *wproto;
1.1 etheisen 46: extern IFILE curr_ifile;
1.4 millert 47: extern char version[];
1.1 etheisen 48: #if LOGFILE
49: extern char *namelogfile;
50: extern int force_logfile;
51: extern int logfile;
52: #endif
53: #if TAGS
54: public char *tagoption = NULL;
55: extern char *tags;
56: extern int jump_sline;
57: #endif
1.4 millert 58: #if MSDOS_COMPILER
1.1 etheisen 59: extern int nm_fg_color, nm_bg_color;
60: extern int bo_fg_color, bo_bg_color;
61: extern int ul_fg_color, ul_bg_color;
62: extern int so_fg_color, so_bg_color;
63: extern int bl_fg_color, bl_bg_color;
64: #endif
65:
66:
67: #if LOGFILE
68: /*
69: * Handler for -o option.
70: */
71: public void
72: opt_o(type, s)
73: int type;
74: char *s;
75: {
76: PARG parg;
77:
1.4 millert 78: if (secure)
79: {
80: error("log file support is not available", NULL_PARG);
81: return;
82: }
1.1 etheisen 83: switch (type)
84: {
85: case INIT:
86: namelogfile = s;
87: break;
88: case TOGGLE:
89: if (ch_getflags() & CH_CANSEEK)
90: {
91: error("Input is not a pipe", NULL_PARG);
92: return;
93: }
94: if (logfile >= 0)
95: {
96: error("Log file is already in use", NULL_PARG);
97: return;
98: }
99: s = skipsp(s);
1.4 millert 100: namelogfile = lglob(s);
1.1 etheisen 101: use_logfile(namelogfile);
102: sync_logfile();
103: break;
104: case QUERY:
105: if (logfile < 0)
106: error("No log file", NULL_PARG);
107: else
108: {
109: parg.p_string = namelogfile;
110: error("Log file \"%s\"", &parg);
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;
1.4 millert 145: n = getnum(&t, "l", &err);
1.1 etheisen 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:
1.4 millert 168: if (lesskey(s, 0))
1.1 etheisen 169: {
170: parg.p_string = s;
171: error("Cannot use lesskey file \"%s\"", &parg);
172: }
173: break;
174: }
175: }
176: #endif
177:
178: #if TAGS
179: /*
180: * Handler for -t option.
181: */
182: public void
183: opt_t(type, s)
184: int type;
185: char *s;
186: {
187: IFILE save_ifile;
188: POSITION pos;
189:
190: switch (type)
191: {
192: case INIT:
193: tagoption = s;
194: /* Do the rest in main() */
195: break;
196: case TOGGLE:
1.4 millert 197: if (secure)
198: {
199: error("tags support is not available", NULL_PARG);
200: break;
201: }
1.1 etheisen 202: findtag(skipsp(s));
1.4 millert 203: save_ifile = save_curr_ifile();
204: if (edit_tagfile())
1.1 etheisen 205: break;
206: if ((pos = tagsearch()) == NULL_POSITION)
207: {
1.4 millert 208: reedit_ifile(save_ifile);
1.1 etheisen 209: break;
210: }
1.4 millert 211: unsave_ifile(save_ifile);
1.1 etheisen 212: jump_loc(pos, jump_sline);
213: break;
214: }
215: }
216:
217: /*
218: * Handler for -T option.
219: */
220: public void
221: opt__T(type, s)
222: int type;
223: char *s;
224: {
225: PARG parg;
226:
227: switch (type)
228: {
229: case INIT:
230: tags = s;
231: break;
232: case TOGGLE:
233: s = skipsp(s);
1.4 millert 234: tags = lglob(s);
1.1 etheisen 235: break;
236: case QUERY:
237: parg.p_string = tags;
238: error("Tags file \"%s\"", &parg);
239: break;
240: }
241: }
242: #endif
243:
244: /*
245: * Handler for -p option.
246: */
247: public void
248: opt_p(type, s)
249: int type;
1.4 millert 250: register char *s;
1.1 etheisen 251: {
252: switch (type)
253: {
254: case INIT:
255: /*
256: * Unget a search command for the specified string.
257: * {{ This won't work if the "/" command is
258: * changed or invalidated by a .lesskey file. }}
259: */
260: plusoption = TRUE;
261: ungetsc(s);
262: ungetsc("/");
263: break;
264: }
265: }
266:
267: /*
268: * Handler for -P option.
269: */
270: public void
271: opt__P(type, s)
272: int type;
1.4 millert 273: register char *s;
1.1 etheisen 274: {
1.4 millert 275: register char **proto;
1.1 etheisen 276: PARG parg;
277:
278: switch (type)
279: {
280: case INIT:
281: case TOGGLE:
282: /*
283: * Figure out which prototype string should be changed.
284: */
285: switch (*s)
286: {
1.4 millert 287: case 's': proto = &prproto[PR_SHORT]; s++; break;
1.1 etheisen 288: case 'm': proto = &prproto[PR_MEDIUM]; s++; break;
289: case 'M': proto = &prproto[PR_LONG]; s++; break;
290: case '=': proto = &eqproto; s++; break;
1.4 millert 291: case 'h': proto = &hproto; s++; break;
292: case 'w': proto = &wproto; s++; break;
1.1 etheisen 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
310: opt_b(type, s)
311: int type;
312: char *s;
313: {
314: switch (type)
315: {
1.4 millert 316: case INIT:
1.1 etheisen 317: case TOGGLE:
318: /*
1.4 millert 319: * Set the new number of buffers.
1.1 etheisen 320: */
1.4 millert 321: ch_setbufspace(bufspace);
1.1 etheisen 322: break;
1.4 millert 323: case QUERY:
1.1 etheisen 324: break;
325: }
326: }
327:
328: /*
329: * Handler for the -i option.
330: */
331: /*ARGSUSED*/
332: public void
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
353: opt__V(type, s)
354: int type;
355: char *s;
356: {
357: switch (type)
358: {
359: case TOGGLE:
360: case QUERY:
1.4 millert 361: dispversion();
362: break;
1.1 etheisen 363: case INIT:
1.4 millert 364: /*
365: * Force output to stdout per GNU standard for --version output.
366: */
367: any_display = 1;
368: putstr("less ");
369: putstr(version);
370: putstr("\nCopyright (C) 2002 Mark Nudelman\n\n");
371: putstr("less comes with NO WARRANTY, to the extent permitted by law.\n");
372: putstr("For information about the terms of redistribution,\n");
373: putstr("see the file named README in the less distribution.\n");
374: putstr("Homepage: http://www.greenwoodsoftware.com/less\n");
375: quit(QUIT_OK);
1.1 etheisen 376: break;
377: }
378: }
379:
1.4 millert 380: #if MSDOS_COMPILER
1.1 etheisen 381: /*
1.4 millert 382: * Parse an MSDOS color descriptor.
1.1 etheisen 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:
1.4 millert 393: fg = getnum(&s, "D", &err);
1.1 etheisen 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++;
1.4 millert 404: bg = getnum(&s, "D", &err);
1.1 etheisen 405: if (err)
406: {
407: error("Missing fg color in -D", NULL_PARG);
408: return;
409: }
410: }
1.4 millert 411: if (*s != '\0')
412: error("Extra characters at end of -D option", NULL_PARG);
1.1 etheisen 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: /*
1.4 millert 464: * Handler for the -x option.
465: */
466: public void
467: opt_x(type, s)
468: int type;
469: register char *s;
470: {
471: extern int tabstops[];
472: extern int ntabstops;
473: extern int tabdefault;
474: char msg[60+(4*TABSTOP_MAX)];
475: int i;
476: PARG p;
477:
478: switch (type)
479: {
480: case INIT:
481: case TOGGLE:
482: /* Start at 1 because tabstops[0] is always zero. */
483: for (i = 1; i < TABSTOP_MAX; )
484: {
485: int n = 0;
486: s = skipsp(s);
487: while (*s >= '0' && *s <= '9')
488: n = (10 * n) + (*s++ - '0');
489: if (n > tabstops[i-1])
490: tabstops[i++] = n;
491: s = skipsp(s);
492: if (*s++ != ',')
493: break;
494: }
495: if (i < 2)
496: return;
497: ntabstops = i;
498: tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2];
499: break;
500: case QUERY:
501: strlcpy(msg, "Tab stops ", sizeof(msg));
502: if (ntabstops > 2)
503: {
504: for (i = 1; i < ntabstops; i++)
505: {
506: if (i > 1)
507: strlcat(msg, ",", sizeof(msg));
508: snprintf(msg+strlen(msg),
509: sizeof(msg)-strlen(msg), "%d", tabstops[i]);
510: }
511: snprintf(msg+strlen(msg), sizeof(msg)-strlen(msg),
512: " and then ");
513: }
514: snprintf(msg+strlen(msg), sizeof(msg)-strlen(msg),
515: "every %d spaces",
516: tabdefault);
517: p.p_string = msg;
518: error("%s", &p);
519: break;
520: }
521: }
522:
523:
524: /*
525: * Handler for the -" option.
526: */
527: public void
528: opt_quote(type, s)
529: int type;
530: register char *s;
531: {
532: char buf[3];
533: PARG parg;
534:
535: switch (type)
536: {
537: case INIT:
538: case TOGGLE:
539: if (s[0] == '\0')
540: {
541: openquote = closequote = '\0';
542: break;
543: }
544: if (s[1] != '\0' && s[2] != '\0')
545: {
546: error("-\" must be followed by 1 or 2 chars", NULL_PARG);
547: return;
548: }
549: openquote = s[0];
550: if (s[1] == '\0')
551: closequote = openquote;
552: else
553: closequote = s[1];
554: break;
555: case QUERY:
556: buf[0] = openquote;
557: buf[1] = closequote;
558: buf[2] = '\0';
559: parg.p_string = buf;
560: error("quotes %s", &parg);
561: break;
562: }
563: }
564:
565: /*
1.1 etheisen 566: * "-?" means display a help message.
567: * If from the command line, exit immediately.
568: */
569: /*ARGSUSED*/
570: public void
571: opt_query(type, s)
572: int type;
573: char *s;
574: {
1.5 ! millert 575: if (nohelp)
! 576: return;
1.1 etheisen 577: switch (type)
578: {
579: case QUERY:
580: case TOGGLE:
581: error("Use \"h\" for help", NULL_PARG);
582: break;
583: case INIT:
1.5 ! millert 584: /*
! 585: * This is "less -?".
! 586: * It rather ungracefully grabs control,
! 587: * does the initializations normally done in main,
! 588: * shows the help file and exits.
! 589: */
! 590: raw_mode(1);
! 591: get_term();
! 592: open_getchr();
! 593: init();
! 594: any_display = TRUE;
! 595: help(1);
! 596: quit(QUIT_OK);
! 597: /*NOTREACHED*/
1.1 etheisen 598: }
599: }
600:
601: /*
602: * Get the "screen window" size.
603: */
604: public int
605: get_swindow()
606: {
607: if (swindow > 0)
608: return (swindow);
609: return (sc_height + swindow);
610: }
611: