Merge branch 'vendor/DHCPCD'
[dragonfly.git] / contrib / less / optfunc.c
blob7fe947ed94958f365581da13e02b2b9863ff342f
1 /*
2 * Copyright (C) 1984-2019 Mark Nudelman
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.
7 * For more information, see the README file.
8 */
12 * Handling functions for command line options.
14 * Most options are handled by the generic code in option.c.
15 * But all string options, and a few non-string options, require
16 * special handling specific to the particular option.
17 * This special processing is done by the "handling functions" in this file.
19 * Each handling function is passed a "type" and, if it is a string
20 * option, the string which should be "assigned" to the option.
21 * The type may be one of:
22 * INIT The option is being initialized from the command line.
23 * TOGGLE The option is being changed from within the program.
24 * QUERY The setting of the option is merely being queried.
27 #include "less.h"
28 #include "option.h"
30 extern int nbufs;
31 extern int bufspace;
32 extern int pr_type;
33 extern int plusoption;
34 extern int swindow;
35 extern int sc_width;
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 char *wproto;
46 extern char *every_first_cmd;
47 extern IFILE curr_ifile;
48 extern char version[];
49 extern int jump_sline;
50 extern long jump_sline_fraction;
51 extern int shift_count;
52 extern long shift_count_fraction;
53 extern char rscroll_char;
54 extern int rscroll_attr;
55 extern int mousecap;
56 extern int wheel_lines;
57 extern int less_is_more;
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 *tags;
66 extern char ztags[];
67 #endif
68 #if MSDOS_COMPILER
69 extern int nm_fg_color, nm_bg_color;
70 extern int bo_fg_color, bo_bg_color;
71 extern int ul_fg_color, ul_bg_color;
72 extern int so_fg_color, so_bg_color;
73 extern int bl_fg_color, bl_bg_color;
74 extern int sgr_mode;
75 #if MSDOS_COMPILER==WIN32C
76 #ifndef COMMON_LVB_UNDERSCORE
77 #define COMMON_LVB_UNDERSCORE 0x8000
78 #endif
79 #endif
80 #endif
83 #if LOGFILE
85 * Handler for -o option.
87 public void
88 opt_o(type, s)
89 int type;
90 char *s;
92 PARG parg;
93 char *filename;
95 if (secure)
97 error("log file support is not available", NULL_PARG);
98 return;
100 switch (type)
102 case INIT:
103 namelogfile = save(s);
104 break;
105 case TOGGLE:
106 if (ch_getflags() & CH_CANSEEK)
108 error("Input is not a pipe", NULL_PARG);
109 return;
111 if (logfile >= 0)
113 error("Log file is already in use", NULL_PARG);
114 return;
116 s = skipsp(s);
117 if (namelogfile != NULL)
118 free(namelogfile);
119 filename = lglob(s);
120 namelogfile = shell_unquote(filename);
121 free(filename);
122 use_logfile(namelogfile);
123 sync_logfile();
124 break;
125 case QUERY:
126 if (logfile < 0)
127 error("No log file", NULL_PARG);
128 else
130 parg.p_string = namelogfile;
131 error("Log file \"%s\"", &parg);
133 break;
138 * Handler for -O option.
140 public void
141 opt__O(type, s)
142 int type;
143 char *s;
145 force_logfile = TRUE;
146 opt_o(type, s);
148 #endif
151 * Handlers for -j option.
153 public void
154 opt_j(type, s)
155 int type;
156 char *s;
158 PARG parg;
159 char buf[16];
160 int len;
161 int err;
163 switch (type)
165 case INIT:
166 case TOGGLE:
167 if (*s == '.')
169 s++;
170 jump_sline_fraction = getfraction(&s, "j", &err);
171 if (err)
172 error("Invalid line fraction", NULL_PARG);
173 else
174 calc_jump_sline();
175 } else
177 int sline = getnum(&s, "j", &err);
178 if (err)
179 error("Invalid line number", NULL_PARG);
180 else
182 jump_sline = sline;
183 jump_sline_fraction = -1;
186 break;
187 case QUERY:
188 if (jump_sline_fraction < 0)
190 parg.p_int = jump_sline;
191 error("Position target at screen line %d", &parg);
192 } else
195 sprintf(buf, ".%06ld", jump_sline_fraction);
196 len = (int) strlen(buf);
197 while (len > 2 && buf[len-1] == '0')
198 len--;
199 buf[len] = '\0';
200 parg.p_string = buf;
201 error("Position target at screen position %s", &parg);
203 break;
207 public void
208 calc_jump_sline(VOID_PARAM)
210 if (jump_sline_fraction < 0)
211 return;
212 jump_sline = sc_height * jump_sline_fraction / NUM_FRAC_DENOM;
216 * Handlers for -# option.
218 public void
219 opt_shift(type, s)
220 int type;
221 char *s;
223 PARG parg;
224 char buf[16];
225 int len;
226 int err;
228 switch (type)
230 case INIT:
231 case TOGGLE:
232 if (*s == '.')
234 s++;
235 shift_count_fraction = getfraction(&s, "#", &err);
236 if (err)
237 error("Invalid column fraction", NULL_PARG);
238 else
239 calc_shift_count();
240 } else
242 int hs = getnum(&s, "#", &err);
243 if (err)
244 error("Invalid column number", NULL_PARG);
245 else
247 shift_count = hs;
248 shift_count_fraction = -1;
251 break;
252 case QUERY:
253 if (shift_count_fraction < 0)
255 parg.p_int = shift_count;
256 error("Horizontal shift %d columns", &parg);
257 } else
260 sprintf(buf, ".%06ld", shift_count_fraction);
261 len = (int) strlen(buf);
262 while (len > 2 && buf[len-1] == '0')
263 len--;
264 buf[len] = '\0';
265 parg.p_string = buf;
266 error("Horizontal shift %s of screen width", &parg);
268 break;
271 public void
272 calc_shift_count(VOID_PARAM)
274 if (shift_count_fraction < 0)
275 return;
276 shift_count = sc_width * shift_count_fraction / NUM_FRAC_DENOM;
279 #if USERFILE
280 public void
281 opt_k(type, s)
282 int type;
283 char *s;
285 PARG parg;
287 switch (type)
289 case INIT:
290 if (lesskey(s, 0))
292 parg.p_string = s;
293 error("Cannot use lesskey file \"%s\"", &parg);
295 break;
298 #endif
300 #if TAGS
302 * Handler for -t option.
304 public void
305 opt_t(type, s)
306 int type;
307 char *s;
309 IFILE save_ifile;
310 POSITION pos;
312 switch (type)
314 case INIT:
315 tagoption = save(s);
316 /* Do the rest in main() */
317 break;
318 case TOGGLE:
319 if (secure)
321 error("tags support is not available", NULL_PARG);
322 break;
324 findtag(skipsp(s));
325 save_ifile = save_curr_ifile();
327 * Try to open the file containing the tag
328 * and search for the tag in that file.
330 if (edit_tagfile() || (pos = tagsearch()) == NULL_POSITION)
332 /* Failed: reopen the old file. */
333 reedit_ifile(save_ifile);
334 break;
336 unsave_ifile(save_ifile);
337 jump_loc(pos, jump_sline);
338 break;
343 * Handler for -T option.
345 public void
346 opt__T(type, s)
347 int type;
348 char *s;
350 PARG parg;
351 char *filename;
353 switch (type)
355 case INIT:
356 tags = save(s);
357 break;
358 case TOGGLE:
359 s = skipsp(s);
360 if (tags != NULL && tags != ztags)
361 free(tags);
362 filename = lglob(s);
363 tags = shell_unquote(filename);
364 free(filename);
365 break;
366 case QUERY:
367 parg.p_string = tags;
368 error("Tags file \"%s\"", &parg);
369 break;
372 #endif
375 * Handler for -p option.
377 public void
378 opt_p(type, s)
379 int type;
380 char *s;
382 switch (type)
384 case INIT:
386 * Unget a command for the specified string.
388 if (less_is_more)
391 * In "more" mode, the -p argument is a command,
392 * not a search string, so we don't need a slash.
394 every_first_cmd = save(s);
395 } else
397 plusoption = TRUE;
398 ungetcc(CHAR_END_COMMAND);
399 ungetsc(s);
401 * {{ This won't work if the "/" command is
402 * changed or invalidated by a .lesskey file. }}
404 ungetsc("/");
406 break;
411 * Handler for -P option.
413 public void
414 opt__P(type, s)
415 int type;
416 char *s;
418 char **proto;
419 PARG parg;
421 switch (type)
423 case INIT:
424 case TOGGLE:
426 * Figure out which prototype string should be changed.
428 switch (*s)
430 case 's': proto = &prproto[PR_SHORT]; s++; break;
431 case 'm': proto = &prproto[PR_MEDIUM]; s++; break;
432 case 'M': proto = &prproto[PR_LONG]; s++; break;
433 case '=': proto = &eqproto; s++; break;
434 case 'h': proto = &hproto; s++; break;
435 case 'w': proto = &wproto; s++; break;
436 default: proto = &prproto[PR_SHORT]; break;
438 free(*proto);
439 *proto = save(s);
440 break;
441 case QUERY:
442 parg.p_string = prproto[pr_type];
443 error("%s", &parg);
444 break;
449 * Handler for the -b option.
451 /*ARGSUSED*/
452 public void
453 opt_b(type, s)
454 int type;
455 char *s;
457 switch (type)
459 case INIT:
460 case TOGGLE:
462 * Set the new number of buffers.
464 ch_setbufspace(bufspace);
465 break;
466 case QUERY:
467 break;
472 * Handler for the -i option.
474 /*ARGSUSED*/
475 public void
476 opt_i(type, s)
477 int type;
478 char *s;
480 switch (type)
482 case TOGGLE:
483 chg_caseless();
484 break;
485 case QUERY:
486 case INIT:
487 break;
492 * Handler for the -V option.
494 /*ARGSUSED*/
495 public void
496 opt__V(type, s)
497 int type;
498 char *s;
500 switch (type)
502 case TOGGLE:
503 case QUERY:
504 dispversion();
505 break;
506 case INIT:
508 * Force output to stdout per GNU standard for --version output.
510 any_display = 1;
511 putstr("less ");
512 putstr(version);
513 putstr(" (");
514 putstr(pattern_lib_name());
515 putstr(" regular expressions)\n");
516 putstr("Copyright (C) 1984-2019 Mark Nudelman\n\n");
517 putstr("less comes with NO WARRANTY, to the extent permitted by law.\n");
518 putstr("For information about the terms of redistribution,\n");
519 putstr("see the file named README in the less distribution.\n");
520 putstr("Home page: http://www.greenwoodsoftware.com/less\n");
521 quit(QUIT_OK);
522 break;
526 #if MSDOS_COMPILER
528 * Parse an MSDOS color descriptor.
530 static void
531 colordesc(s, fg_color, bg_color)
532 char *s;
533 int *fg_color;
534 int *bg_color;
536 int fg, bg;
537 int err;
538 #if MSDOS_COMPILER==WIN32C
539 int ul = 0;
541 if (*s == 'u')
543 ul = COMMON_LVB_UNDERSCORE;
544 ++s;
546 #endif
547 fg = getnum(&s, "D", &err);
548 if (err)
550 #if MSDOS_COMPILER==WIN32C
551 if (ul)
552 fg = nm_fg_color;
553 else
554 #endif
556 error("Missing fg color in -D", NULL_PARG);
557 return;
560 if (*s != '.')
561 bg = nm_bg_color;
562 else
564 s++;
565 bg = getnum(&s, "D", &err);
566 if (err)
568 error("Missing bg color in -D", NULL_PARG);
569 return;
572 #if MSDOS_COMPILER==WIN32C
573 if (*s == 'u')
575 ul = COMMON_LVB_UNDERSCORE;
576 ++s;
578 fg |= ul;
579 #endif
580 if (*s != '\0')
581 error("Extra characters at end of -D option", NULL_PARG);
582 *fg_color = fg;
583 *bg_color = bg;
587 * Handler for the -D option.
589 /*ARGSUSED*/
590 public void
591 opt_D(type, s)
592 int type;
593 char *s;
595 PARG p;
597 switch (type)
599 case INIT:
600 case TOGGLE:
601 switch (*s++)
603 case 'n':
604 colordesc(s, &nm_fg_color, &nm_bg_color);
605 break;
606 case 'd':
607 colordesc(s, &bo_fg_color, &bo_bg_color);
608 break;
609 case 'u':
610 colordesc(s, &ul_fg_color, &ul_bg_color);
611 break;
612 case 'k':
613 colordesc(s, &bl_fg_color, &bl_bg_color);
614 break;
615 case 's':
616 colordesc(s, &so_fg_color, &so_bg_color);
617 break;
618 case 'a':
619 sgr_mode = !sgr_mode;
620 break;
621 default:
622 error("-D must be followed by n, d, u, k, s or a", NULL_PARG);
623 break;
625 if (type == TOGGLE)
627 at_enter(AT_STANDOUT);
628 at_exit();
630 break;
631 case QUERY:
632 p.p_string = (sgr_mode) ? "on" : "off";
633 error("SGR mode is %s", &p);
634 break;
637 #endif
640 * Handler for the -x option.
642 public void
643 opt_x(type, s)
644 int type;
645 char *s;
647 extern int tabstops[];
648 extern int ntabstops;
649 extern int tabdefault;
650 char msg[60+(4*TABSTOP_MAX)];
651 int i;
652 PARG p;
654 switch (type)
656 case INIT:
657 case TOGGLE:
658 /* Start at 1 because tabstops[0] is always zero. */
659 for (i = 1; i < TABSTOP_MAX; )
661 int n = 0;
662 s = skipsp(s);
663 while (*s >= '0' && *s <= '9')
664 n = (10 * n) + (*s++ - '0');
665 if (n > tabstops[i-1])
666 tabstops[i++] = n;
667 s = skipsp(s);
668 if (*s++ != ',')
669 break;
671 if (i < 2)
672 return;
673 ntabstops = i;
674 tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2];
675 break;
676 case QUERY:
677 strcpy(msg, "Tab stops ");
678 if (ntabstops > 2)
680 for (i = 1; i < ntabstops; i++)
682 if (i > 1)
683 strcat(msg, ",");
684 sprintf(msg+strlen(msg), "%d", tabstops[i]);
686 sprintf(msg+strlen(msg), " and then ");
688 sprintf(msg+strlen(msg), "every %d spaces",
689 tabdefault);
690 p.p_string = msg;
691 error("%s", &p);
692 break;
698 * Handler for the -" option.
700 public void
701 opt_quote(type, s)
702 int type;
703 char *s;
705 char buf[3];
706 PARG parg;
708 switch (type)
710 case INIT:
711 case TOGGLE:
712 if (s[0] == '\0')
714 openquote = closequote = '\0';
715 break;
717 if (s[1] != '\0' && s[2] != '\0')
719 error("-\" must be followed by 1 or 2 chars", NULL_PARG);
720 return;
722 openquote = s[0];
723 if (s[1] == '\0')
724 closequote = openquote;
725 else
726 closequote = s[1];
727 break;
728 case QUERY:
729 buf[0] = openquote;
730 buf[1] = closequote;
731 buf[2] = '\0';
732 parg.p_string = buf;
733 error("quotes %s", &parg);
734 break;
739 * Handler for the --rscroll option.
741 /*ARGSUSED*/
742 public void
743 opt_rscroll(type, s)
744 int type;
745 char *s;
747 PARG p;
749 switch (type)
751 case INIT:
752 case TOGGLE: {
753 char *fmt;
754 int attr = AT_STANDOUT;
755 setfmt(s, &fmt, &attr, "*s>");
756 if (strcmp(fmt, "-") == 0)
758 rscroll_char = 0;
759 } else
761 rscroll_char = *fmt ? *fmt : '>';
762 rscroll_attr = attr;
764 break; }
765 case QUERY: {
766 p.p_string = rscroll_char ? prchar(rscroll_char) : "-";
767 error("rscroll char is %s", &p);
768 break; }
773 * "-?" means display a help message.
774 * If from the command line, exit immediately.
776 /*ARGSUSED*/
777 public void
778 opt_query(type, s)
779 int type;
780 char *s;
782 switch (type)
784 case QUERY:
785 case TOGGLE:
786 error("Use \"h\" for help", NULL_PARG);
787 break;
788 case INIT:
789 dohelp = 1;
794 * Handler for the --mouse option.
796 /*ARGSUSED*/
797 public void
798 opt_mousecap(type, s)
799 int type;
800 char *s;
802 switch (type)
804 case TOGGLE:
805 if (mousecap == OPT_OFF)
806 deinit_mouse();
807 else
808 init_mouse();
809 break;
810 case INIT:
811 case QUERY:
812 break;
817 * Handler for the --wheel-lines option.
819 /*ARGSUSED*/
820 public void
821 opt_wheel_lines(type, s)
822 int type;
823 char *s;
825 switch (type)
827 case INIT:
828 case TOGGLE:
829 if (wheel_lines <= 0)
830 wheel_lines = default_wheel_lines();
831 break;
832 case QUERY:
833 break;
838 * Get the "screen window" size.
840 public int
841 get_swindow(VOID_PARAM)
843 if (swindow > 0)
844 return (swindow);
845 return (sc_height + swindow);