Annotation of src/usr.bin/less/optfunc.c, Revision 1.1.1.3
1.1 etheisen 1: /*
1.1.1.3 ! shadchin 2: * Copyright (C) 1984-2011 Mark Nudelman
1.1 etheisen 3: *
1.1.1.2 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.1.1.2 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.1.1.2 millert 32: extern int bufspace;
1.1 etheisen 33: extern int pr_type;
34: extern int plusoption;
35: extern int swindow;
1.1.1.3 ! shadchin 36: extern int sc_width;
1.1 etheisen 37: extern int sc_height;
1.1.1.2 millert 38: extern int secure;
39: extern int dohelp;
1.1 etheisen 40: extern int any_display;
1.1.1.2 millert 41: extern char openquote;
42: extern char closequote;
1.1 etheisen 43: extern char *prproto[];
44: extern char *eqproto;
1.1.1.2 millert 45: extern char *hproto;
46: extern char *wproto;
1.1 etheisen 47: extern IFILE curr_ifile;
1.1.1.2 millert 48: extern char version[];
1.1.1.3 ! shadchin 49: extern int jump_sline;
! 50: extern int jump_sline_fraction;
! 51: extern int shift_count;
! 52: extern int shift_count_fraction;
! 53: extern int less_is_more;
1.1 etheisen 54: #if LOGFILE
55: extern char *namelogfile;
56: extern int force_logfile;
57: extern int logfile;
58: #endif
59: #if TAGS
60: public char *tagoption = NULL;
61: extern char *tags;
62: #endif
1.1.1.2 millert 63: #if MSDOS_COMPILER
1.1 etheisen 64: extern int nm_fg_color, nm_bg_color;
65: extern int bo_fg_color, bo_bg_color;
66: extern int ul_fg_color, ul_bg_color;
67: extern int so_fg_color, so_bg_color;
68: extern int bl_fg_color, bl_bg_color;
69: #endif
70:
71:
72: #if LOGFILE
73: /*
74: * Handler for -o option.
75: */
76: public void
77: opt_o(type, s)
78: int type;
79: char *s;
80: {
81: PARG parg;
82:
1.1.1.2 millert 83: if (secure)
84: {
85: error("log file support is not available", NULL_PARG);
86: return;
87: }
1.1 etheisen 88: switch (type)
89: {
90: case INIT:
91: namelogfile = s;
92: break;
93: case TOGGLE:
94: if (ch_getflags() & CH_CANSEEK)
95: {
96: error("Input is not a pipe", NULL_PARG);
97: return;
98: }
99: if (logfile >= 0)
100: {
101: error("Log file is already in use", NULL_PARG);
102: return;
103: }
104: s = skipsp(s);
1.1.1.2 millert 105: namelogfile = lglob(s);
1.1 etheisen 106: use_logfile(namelogfile);
107: sync_logfile();
108: break;
109: case QUERY:
110: if (logfile < 0)
111: error("No log file", NULL_PARG);
112: else
113: {
114: parg.p_string = namelogfile;
115: error("Log file \"%s\"", &parg);
116: }
117: break;
118: }
119: }
120:
121: /*
122: * Handler for -O option.
123: */
124: public void
125: opt__O(type, s)
126: int type;
127: char *s;
128: {
129: force_logfile = TRUE;
130: opt_o(type, s);
131: }
132: #endif
133:
134: /*
1.1.1.3 ! shadchin 135: * Handlers for -j option.
1.1 etheisen 136: */
137: public void
1.1.1.3 ! shadchin 138: opt_j(type, s)
1.1 etheisen 139: int type;
140: char *s;
141: {
1.1.1.3 ! shadchin 142: PARG parg;
! 143: char buf[16];
! 144: int len;
1.1 etheisen 145: int err;
1.1.1.3 ! shadchin 146:
1.1 etheisen 147: switch (type)
148: {
149: case INIT:
1.1.1.3 ! shadchin 150: case TOGGLE:
! 151: if (*s == '.')
1.1 etheisen 152: {
1.1.1.3 ! shadchin 153: s++;
! 154: jump_sline_fraction = getfraction(&s, "j", &err);
! 155: if (err)
! 156: error("Invalid line fraction", NULL_PARG);
! 157: else
! 158: calc_jump_sline();
! 159: } else
! 160: {
! 161: int sline = getnum(&s, "j", &err);
! 162: if (err)
! 163: error("Invalid line number", NULL_PARG);
! 164: else
! 165: {
! 166: jump_sline = sline;
! 167: jump_sline_fraction = -1;
! 168: }
! 169: }
! 170: break;
! 171: case QUERY:
! 172: if (jump_sline_fraction < 0)
! 173: {
! 174: parg.p_int = jump_sline;
! 175: error("Position target at screen line %d", &parg);
! 176: } else
! 177: {
! 178:
! 179: sprintf(buf, ".%06d", jump_sline_fraction);
! 180: len = strlen(buf);
! 181: while (len > 2 && buf[len-1] == '0')
! 182: len--;
! 183: buf[len] = '\0';
! 184: parg.p_string = buf;
! 185: error("Position target at screen position %s", &parg);
! 186: }
! 187: break;
! 188: }
! 189: }
! 190:
! 191: public void
! 192: calc_jump_sline()
! 193: {
! 194: if (jump_sline_fraction < 0)
! 195: return;
! 196: jump_sline = sc_height * jump_sline_fraction / NUM_FRAC_DENOM;
! 197: }
! 198:
! 199: /*
! 200: * Handlers for -# option.
! 201: */
! 202: public void
! 203: opt_shift(type, s)
! 204: int type;
! 205: char *s;
! 206: {
! 207: PARG parg;
! 208: char buf[16];
! 209: int len;
! 210: int err;
! 211:
! 212: switch (type)
! 213: {
! 214: case INIT:
! 215: case TOGGLE:
! 216: if (*s == '.')
! 217: {
! 218: s++;
! 219: shift_count_fraction = getfraction(&s, "#", &err);
! 220: if (err)
! 221: error("Invalid column fraction", NULL_PARG);
! 222: else
! 223: calc_shift_count();
! 224: } else
! 225: {
! 226: int hs = getnum(&s, "#", &err);
! 227: if (err)
! 228: error("Invalid column number", NULL_PARG);
! 229: else
! 230: {
! 231: shift_count = hs;
! 232: shift_count_fraction = -1;
! 233: }
! 234: }
! 235: break;
! 236: case QUERY:
! 237: if (shift_count_fraction < 0)
! 238: {
! 239: parg.p_int = shift_count;
! 240: error("Horizontal shift %d columns", &parg);
! 241: } else
! 242: {
! 243:
! 244: sprintf(buf, ".%06d", shift_count_fraction);
! 245: len = strlen(buf);
! 246: while (len > 2 && buf[len-1] == '0')
! 247: len--;
! 248: buf[len] = '\0';
! 249: parg.p_string = buf;
! 250: error("Horizontal shift %s of screen width", &parg);
1.1 etheisen 251: }
252: break;
253: }
254: }
1.1.1.3 ! shadchin 255: public void
! 256: calc_shift_count()
! 257: {
! 258: if (shift_count_fraction < 0)
! 259: return;
! 260: shift_count = sc_width * shift_count_fraction / NUM_FRAC_DENOM;
! 261: }
1.1 etheisen 262:
263: #if USERFILE
264: public void
265: opt_k(type, s)
266: int type;
267: char *s;
268: {
269: PARG parg;
270:
271: switch (type)
272: {
273: case INIT:
1.1.1.2 millert 274: if (lesskey(s, 0))
1.1 etheisen 275: {
276: parg.p_string = s;
277: error("Cannot use lesskey file \"%s\"", &parg);
278: }
279: break;
280: }
281: }
282: #endif
283:
284: #if TAGS
285: /*
286: * Handler for -t option.
287: */
288: public void
289: opt_t(type, s)
290: int type;
291: char *s;
292: {
293: IFILE save_ifile;
294: POSITION pos;
295:
296: switch (type)
297: {
298: case INIT:
299: tagoption = s;
300: /* Do the rest in main() */
301: break;
302: case TOGGLE:
1.1.1.2 millert 303: if (secure)
304: {
305: error("tags support is not available", NULL_PARG);
1.1 etheisen 306: break;
1.1.1.2 millert 307: }
308: findtag(skipsp(s));
309: save_ifile = save_curr_ifile();
1.1.1.3 ! shadchin 310: /*
! 311: * Try to open the file containing the tag
! 312: * and search for the tag in that file.
! 313: */
! 314: if (edit_tagfile() || (pos = tagsearch()) == NULL_POSITION)
1.1 etheisen 315: {
1.1.1.3 ! shadchin 316: /* Failed: reopen the old file. */
1.1.1.2 millert 317: reedit_ifile(save_ifile);
1.1 etheisen 318: break;
319: }
1.1.1.2 millert 320: unsave_ifile(save_ifile);
1.1 etheisen 321: jump_loc(pos, jump_sline);
322: break;
323: }
324: }
325:
326: /*
327: * Handler for -T option.
328: */
329: public void
330: opt__T(type, s)
331: int type;
332: char *s;
333: {
334: PARG parg;
335:
336: switch (type)
337: {
338: case INIT:
339: tags = s;
340: break;
341: case TOGGLE:
342: s = skipsp(s);
1.1.1.2 millert 343: tags = lglob(s);
1.1 etheisen 344: break;
345: case QUERY:
346: parg.p_string = tags;
347: error("Tags file \"%s\"", &parg);
348: break;
349: }
350: }
351: #endif
352:
353: /*
354: * Handler for -p option.
355: */
356: public void
357: opt_p(type, s)
358: int type;
359: register char *s;
360: {
361: switch (type)
362: {
363: case INIT:
364: /*
365: * Unget a search command for the specified string.
366: * {{ This won't work if the "/" command is
367: * changed or invalidated by a .lesskey file. }}
368: */
369: plusoption = TRUE;
370: ungetsc(s);
1.1.1.3 ! shadchin 371: /*
! 372: * In "more" mode, the -p argument is a command,
! 373: * not a search string, so we don't need a slash.
! 374: */
! 375: if (!less_is_more)
! 376: ungetsc("/");
1.1 etheisen 377: break;
378: }
379: }
380:
381: /*
382: * Handler for -P option.
383: */
384: public void
385: opt__P(type, s)
386: int type;
387: register char *s;
388: {
389: register char **proto;
390: PARG parg;
391:
392: switch (type)
393: {
394: case INIT:
395: case TOGGLE:
396: /*
397: * Figure out which prototype string should be changed.
398: */
399: switch (*s)
400: {
1.1.1.2 millert 401: case 's': proto = &prproto[PR_SHORT]; s++; break;
1.1 etheisen 402: case 'm': proto = &prproto[PR_MEDIUM]; s++; break;
403: case 'M': proto = &prproto[PR_LONG]; s++; break;
404: case '=': proto = &eqproto; s++; break;
1.1.1.2 millert 405: case 'h': proto = &hproto; s++; break;
406: case 'w': proto = &wproto; s++; break;
1.1 etheisen 407: default: proto = &prproto[PR_SHORT]; break;
408: }
409: free(*proto);
410: *proto = save(s);
411: break;
412: case QUERY:
413: parg.p_string = prproto[pr_type];
414: error("%s", &parg);
415: break;
416: }
417: }
418:
419: /*
420: * Handler for the -b option.
421: */
422: /*ARGSUSED*/
423: public void
424: opt_b(type, s)
425: int type;
426: char *s;
427: {
428: switch (type)
429: {
1.1.1.2 millert 430: case INIT:
1.1 etheisen 431: case TOGGLE:
432: /*
1.1.1.2 millert 433: * Set the new number of buffers.
1.1 etheisen 434: */
1.1.1.2 millert 435: ch_setbufspace(bufspace);
1.1 etheisen 436: break;
1.1.1.2 millert 437: case QUERY:
1.1 etheisen 438: break;
439: }
440: }
441:
442: /*
443: * Handler for the -i option.
444: */
445: /*ARGSUSED*/
446: public void
447: opt_i(type, s)
448: int type;
449: char *s;
450: {
451: switch (type)
452: {
453: case TOGGLE:
454: chg_caseless();
455: break;
456: case QUERY:
457: case INIT:
458: break;
459: }
460: }
461:
462: /*
463: * Handler for the -V option.
464: */
465: /*ARGSUSED*/
466: public void
467: opt__V(type, s)
468: int type;
469: char *s;
470: {
471: switch (type)
472: {
473: case TOGGLE:
474: case QUERY:
475: dispversion();
1.1.1.2 millert 476: break;
477: case INIT:
478: /*
479: * Force output to stdout per GNU standard for --version output.
480: */
481: any_display = 1;
482: putstr("less ");
483: putstr(version);
1.1.1.3 ! shadchin 484: putstr("\nCopyright (C) 1984-2009 Mark Nudelman\n\n");
1.1.1.2 millert 485: putstr("less comes with NO WARRANTY, to the extent permitted by law.\n");
486: putstr("For information about the terms of redistribution,\n");
487: putstr("see the file named README in the less distribution.\n");
488: putstr("Homepage: http://www.greenwoodsoftware.com/less\n");
489: quit(QUIT_OK);
1.1 etheisen 490: break;
491: }
492: }
493:
1.1.1.2 millert 494: #if MSDOS_COMPILER
1.1 etheisen 495: /*
1.1.1.2 millert 496: * Parse an MSDOS color descriptor.
1.1 etheisen 497: */
498: static void
499: colordesc(s, fg_color, bg_color)
500: char *s;
501: int *fg_color;
502: int *bg_color;
503: {
504: int fg, bg;
505: int err;
506:
1.1.1.2 millert 507: fg = getnum(&s, "D", &err);
1.1 etheisen 508: if (err)
509: {
510: error("Missing fg color in -D", NULL_PARG);
511: return;
512: }
513: if (*s != '.')
1.1.1.3 ! shadchin 514: bg = nm_bg_color;
1.1 etheisen 515: else
516: {
517: s++;
1.1.1.2 millert 518: bg = getnum(&s, "D", &err);
1.1 etheisen 519: if (err)
520: {
1.1.1.3 ! shadchin 521: error("Missing bg color in -D", NULL_PARG);
1.1 etheisen 522: return;
523: }
524: }
1.1.1.2 millert 525: if (*s != '\0')
526: error("Extra characters at end of -D option", NULL_PARG);
1.1 etheisen 527: *fg_color = fg;
528: *bg_color = bg;
529: }
530:
531: /*
532: * Handler for the -D option.
533: */
534: /*ARGSUSED*/
535: public void
536: opt_D(type, s)
537: int type;
538: char *s;
539: {
540: switch (type)
541: {
542: case INIT:
543: case TOGGLE:
544: switch (*s++)
545: {
546: case 'n':
547: colordesc(s, &nm_fg_color, &nm_bg_color);
548: break;
549: case 'd':
550: colordesc(s, &bo_fg_color, &bo_bg_color);
551: break;
552: case 'u':
553: colordesc(s, &ul_fg_color, &ul_bg_color);
554: break;
555: case 'k':
556: colordesc(s, &bl_fg_color, &bl_bg_color);
557: break;
558: case 's':
559: colordesc(s, &so_fg_color, &so_bg_color);
560: break;
561: default:
562: error("-D must be followed by n, d, u, k or s", NULL_PARG);
563: break;
564: }
565: if (type == TOGGLE)
566: {
1.1.1.3 ! shadchin 567: at_enter(AT_STANDOUT);
! 568: at_exit();
1.1 etheisen 569: }
570: break;
571: case QUERY:
572: break;
573: }
574: }
575: #endif
576:
577: /*
1.1.1.2 millert 578: * Handler for the -x option.
579: */
580: public void
581: opt_x(type, s)
582: int type;
583: register char *s;
584: {
585: extern int tabstops[];
586: extern int ntabstops;
587: extern int tabdefault;
588: char msg[60+(4*TABSTOP_MAX)];
589: int i;
590: PARG p;
591:
592: switch (type)
593: {
594: case INIT:
595: case TOGGLE:
596: /* Start at 1 because tabstops[0] is always zero. */
597: for (i = 1; i < TABSTOP_MAX; )
598: {
599: int n = 0;
600: s = skipsp(s);
601: while (*s >= '0' && *s <= '9')
602: n = (10 * n) + (*s++ - '0');
603: if (n > tabstops[i-1])
604: tabstops[i++] = n;
605: s = skipsp(s);
606: if (*s++ != ',')
607: break;
608: }
609: if (i < 2)
610: return;
611: ntabstops = i;
612: tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2];
613: break;
614: case QUERY:
615: strcpy(msg, "Tab stops ");
616: if (ntabstops > 2)
617: {
618: for (i = 1; i < ntabstops; i++)
619: {
620: if (i > 1)
621: strcat(msg, ",");
622: sprintf(msg+strlen(msg), "%d", tabstops[i]);
623: }
624: sprintf(msg+strlen(msg), " and then ");
625: }
626: sprintf(msg+strlen(msg), "every %d spaces",
627: tabdefault);
628: p.p_string = msg;
629: error("%s", &p);
630: break;
631: }
632: }
633:
634:
635: /*
636: * Handler for the -" option.
637: */
638: public void
639: opt_quote(type, s)
640: int type;
641: register char *s;
642: {
643: char buf[3];
644: PARG parg;
645:
646: switch (type)
647: {
648: case INIT:
649: case TOGGLE:
650: if (s[0] == '\0')
651: {
652: openquote = closequote = '\0';
653: break;
654: }
655: if (s[1] != '\0' && s[2] != '\0')
656: {
657: error("-\" must be followed by 1 or 2 chars", NULL_PARG);
658: return;
659: }
660: openquote = s[0];
661: if (s[1] == '\0')
662: closequote = openquote;
663: else
664: closequote = s[1];
665: break;
666: case QUERY:
667: buf[0] = openquote;
668: buf[1] = closequote;
669: buf[2] = '\0';
670: parg.p_string = buf;
671: error("quotes %s", &parg);
672: break;
673: }
674: }
675:
676: /*
1.1 etheisen 677: * "-?" means display a help message.
678: * If from the command line, exit immediately.
679: */
680: /*ARGSUSED*/
681: public void
682: opt_query(type, s)
683: int type;
684: char *s;
685: {
686: switch (type)
687: {
688: case QUERY:
689: case TOGGLE:
690: error("Use \"h\" for help", NULL_PARG);
691: break;
692: case INIT:
1.1.1.2 millert 693: dohelp = 1;
1.1 etheisen 694: }
695: }
696:
697: /*
698: * Get the "screen window" size.
699: */
700: public int
701: get_swindow()
702: {
703: if (swindow > 0)
704: return (swindow);
705: return (sc_height + swindow);
706: }
707: