1 /* 2 * Copyright (C) 1984-2022 Mark Nudelman 3 * 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. 6 * 7 * For more information, see the README file. 8 */ 9 10 11 /* 12 * Handling functions for command line options. 13 * 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. 18 * 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. 25 */ 26 27 #include "less.h" 28 #include "option.h" 29 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 is_tty; 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 extern int linenum_width; 59 extern int status_col_width; 60 extern int use_color; 61 extern int want_filesize; 62 extern int header_lines; 63 extern int header_cols; 64 extern int def_search_type; 65 extern int chopline; 66 #if LOGFILE 67 extern char *namelogfile; 68 extern int force_logfile; 69 extern int logfile; 70 #endif 71 #if TAGS 72 public char *tagoption = NULL; 73 extern char *tags; 74 extern char ztags[]; 75 #endif 76 #if LESSTEST 77 extern char *ttyin_name; 78 extern int rstat_file; 79 #endif /*LESSTEST*/ 80 #if MSDOS_COMPILER 81 extern int nm_fg_color, nm_bg_color; 82 extern int bo_fg_color, bo_bg_color; 83 extern int ul_fg_color, ul_bg_color; 84 extern int so_fg_color, so_bg_color; 85 extern int bl_fg_color, bl_bg_color; 86 extern int sgr_mode; 87 #if MSDOS_COMPILER==WIN32C 88 #ifndef COMMON_LVB_UNDERSCORE 89 #define COMMON_LVB_UNDERSCORE 0x8000 90 #endif 91 #endif 92 #endif 93 94 95 #if LOGFILE 96 /* 97 * Handler for -o option. 98 */ 99 public void 100 opt_o(type, s) 101 int type; 102 char *s; 103 { 104 PARG parg; 105 char *filename; 106 107 if (secure) 108 { 109 error("log file support is not available", NULL_PARG); 110 return; 111 } 112 switch (type) 113 { 114 case INIT: 115 namelogfile = save(s); 116 break; 117 case TOGGLE: 118 if (ch_getflags() & CH_CANSEEK) 119 { 120 error("Input is not a pipe", NULL_PARG); 121 return; 122 } 123 if (logfile >= 0) 124 { 125 error("Log file is already in use", NULL_PARG); 126 return; 127 } 128 s = skipsp(s); 129 if (namelogfile != NULL) 130 free(namelogfile); 131 filename = lglob(s); 132 namelogfile = shell_unquote(filename); 133 free(filename); 134 use_logfile(namelogfile); 135 sync_logfile(); 136 break; 137 case QUERY: 138 if (logfile < 0) 139 error("No log file", NULL_PARG); 140 else 141 { 142 parg.p_string = namelogfile; 143 error("Log file \"%s\"", &parg); 144 } 145 break; 146 } 147 } 148 149 /* 150 * Handler for -O option. 151 */ 152 public void 153 opt__O(type, s) 154 int type; 155 char *s; 156 { 157 force_logfile = TRUE; 158 opt_o(type, s); 159 } 160 #endif 161 162 /* 163 * Handlers for -j option. 164 */ 165 public void 166 opt_j(type, s) 167 int type; 168 char *s; 169 { 170 PARG parg; 171 int len; 172 int err; 173 174 switch (type) 175 { 176 case INIT: 177 case TOGGLE: 178 if (*s == '.') 179 { 180 s++; 181 jump_sline_fraction = getfraction(&s, "j", &err); 182 if (err) 183 error("Invalid line fraction", NULL_PARG); 184 else 185 calc_jump_sline(); 186 } else 187 { 188 int sline = getnum(&s, "j", &err); 189 if (err) 190 error("Invalid line number", NULL_PARG); 191 else 192 { 193 jump_sline = sline; 194 jump_sline_fraction = -1; 195 } 196 } 197 break; 198 case QUERY: 199 if (jump_sline_fraction < 0) 200 { 201 parg.p_int = jump_sline; 202 error("Position target at screen line %d", &parg); 203 } else 204 { 205 char buf[24]; 206 SNPRINTF1(buf, sizeof(buf), ".%06ld", jump_sline_fraction); 207 len = (int) strlen(buf); 208 while (len > 2 && buf[len-1] == '0') 209 len--; 210 buf[len] = '\0'; 211 parg.p_string = buf; 212 error("Position target at screen position %s", &parg); 213 } 214 break; 215 } 216 } 217 218 public void 219 calc_jump_sline(VOID_PARAM) 220 { 221 if (jump_sline_fraction < 0) 222 return; 223 jump_sline = sc_height * jump_sline_fraction / NUM_FRAC_DENOM; 224 } 225 226 /* 227 * Handlers for -# option. 228 */ 229 public void 230 opt_shift(type, s) 231 int type; 232 char *s; 233 { 234 PARG parg; 235 int len; 236 int err; 237 238 switch (type) 239 { 240 case INIT: 241 case TOGGLE: 242 if (*s == '.') 243 { 244 s++; 245 shift_count_fraction = getfraction(&s, "#", &err); 246 if (err) 247 error("Invalid column fraction", NULL_PARG); 248 else 249 calc_shift_count(); 250 } else 251 { 252 int hs = getnum(&s, "#", &err); 253 if (err) 254 error("Invalid column number", NULL_PARG); 255 else 256 { 257 shift_count = hs; 258 shift_count_fraction = -1; 259 } 260 } 261 break; 262 case QUERY: 263 if (shift_count_fraction < 0) 264 { 265 parg.p_int = shift_count; 266 error("Horizontal shift %d columns", &parg); 267 } else 268 { 269 char buf[24]; 270 SNPRINTF1(buf, sizeof(buf), ".%06ld", shift_count_fraction); 271 len = (int) strlen(buf); 272 while (len > 2 && buf[len-1] == '0') 273 len--; 274 buf[len] = '\0'; 275 parg.p_string = buf; 276 error("Horizontal shift %s of screen width", &parg); 277 } 278 break; 279 } 280 } 281 282 public void 283 calc_shift_count(VOID_PARAM) 284 { 285 if (shift_count_fraction < 0) 286 return; 287 shift_count = sc_width * shift_count_fraction / NUM_FRAC_DENOM; 288 } 289 290 #if USERFILE 291 public void 292 opt_k(type, s) 293 int type; 294 char *s; 295 { 296 PARG parg; 297 298 switch (type) 299 { 300 case INIT: 301 if (lesskey(s, 0)) 302 { 303 parg.p_string = s; 304 error("Cannot use lesskey file \"%s\"", &parg); 305 } 306 break; 307 } 308 } 309 310 #if HAVE_LESSKEYSRC 311 public void 312 opt_ks(type, s) 313 int type; 314 char *s; 315 { 316 PARG parg; 317 318 switch (type) 319 { 320 case INIT: 321 if (lesskey_src(s, 0)) 322 { 323 parg.p_string = s; 324 error("Cannot use lesskey source file \"%s\"", &parg); 325 } 326 break; 327 } 328 } 329 #endif /* HAVE_LESSKEYSRC */ 330 #endif /* USERFILE */ 331 332 #if TAGS 333 /* 334 * Handler for -t option. 335 */ 336 public void 337 opt_t(type, s) 338 int type; 339 char *s; 340 { 341 IFILE save_ifile; 342 POSITION pos; 343 344 switch (type) 345 { 346 case INIT: 347 tagoption = save(s); 348 /* Do the rest in main() */ 349 break; 350 case TOGGLE: 351 if (secure) 352 { 353 error("tags support is not available", NULL_PARG); 354 break; 355 } 356 findtag(skipsp(s)); 357 save_ifile = save_curr_ifile(); 358 /* 359 * Try to open the file containing the tag 360 * and search for the tag in that file. 361 */ 362 if (edit_tagfile() || (pos = tagsearch()) == NULL_POSITION) 363 { 364 /* Failed: reopen the old file. */ 365 reedit_ifile(save_ifile); 366 break; 367 } 368 unsave_ifile(save_ifile); 369 jump_loc(pos, jump_sline); 370 break; 371 } 372 } 373 374 /* 375 * Handler for -T option. 376 */ 377 public void 378 opt__T(type, s) 379 int type; 380 char *s; 381 { 382 PARG parg; 383 char *filename; 384 385 switch (type) 386 { 387 case INIT: 388 tags = save(s); 389 break; 390 case TOGGLE: 391 s = skipsp(s); 392 if (tags != NULL && tags != ztags) 393 free(tags); 394 filename = lglob(s); 395 tags = shell_unquote(filename); 396 free(filename); 397 break; 398 case QUERY: 399 parg.p_string = tags; 400 error("Tags file \"%s\"", &parg); 401 break; 402 } 403 } 404 #endif 405 406 /* 407 * Handler for -p option. 408 */ 409 public void 410 opt_p(type, s) 411 int type; 412 char *s; 413 { 414 switch (type) 415 { 416 case INIT: 417 /* 418 * Unget a command for the specified string. 419 */ 420 if (less_is_more) 421 { 422 /* 423 * In "more" mode, the -p argument is a command, 424 * not a search string, so we don't need a slash. 425 */ 426 every_first_cmd = save(s); 427 } else 428 { 429 plusoption = TRUE; 430 /* 431 * {{ This won't work if the "/" command is 432 * changed or invalidated by a .lesskey file. }} 433 */ 434 ungetsc("/"); 435 ungetsc(s); 436 ungetcc_back(CHAR_END_COMMAND); 437 } 438 break; 439 } 440 } 441 442 /* 443 * Handler for -P option. 444 */ 445 public void 446 opt__P(type, s) 447 int type; 448 char *s; 449 { 450 char **proto; 451 PARG parg; 452 453 switch (type) 454 { 455 case INIT: 456 case TOGGLE: 457 /* 458 * Figure out which prototype string should be changed. 459 */ 460 switch (*s) 461 { 462 case 's': proto = &prproto[PR_SHORT]; s++; break; 463 case 'm': proto = &prproto[PR_MEDIUM]; s++; break; 464 case 'M': proto = &prproto[PR_LONG]; s++; break; 465 case '=': proto = &eqproto; s++; break; 466 case 'h': proto = &hproto; s++; break; 467 case 'w': proto = &wproto; s++; break; 468 default: proto = &prproto[PR_SHORT]; break; 469 } 470 free(*proto); 471 *proto = save(s); 472 break; 473 case QUERY: 474 parg.p_string = prproto[pr_type]; 475 error("%s", &parg); 476 break; 477 } 478 } 479 480 /* 481 * Handler for the -b option. 482 */ 483 /*ARGSUSED*/ 484 public void 485 opt_b(type, s) 486 int type; 487 char *s; 488 { 489 switch (type) 490 { 491 case INIT: 492 case TOGGLE: 493 /* 494 * Set the new number of buffers. 495 */ 496 ch_setbufspace(bufspace); 497 break; 498 case QUERY: 499 break; 500 } 501 } 502 503 /* 504 * Handler for the -i option. 505 */ 506 /*ARGSUSED*/ 507 public void 508 opt_i(type, s) 509 int type; 510 char *s; 511 { 512 switch (type) 513 { 514 case TOGGLE: 515 chg_caseless(); 516 break; 517 case QUERY: 518 case INIT: 519 break; 520 } 521 } 522 523 /* 524 * Handler for the -V option. 525 */ 526 /*ARGSUSED*/ 527 public void 528 opt__V(type, s) 529 int type; 530 char *s; 531 { 532 switch (type) 533 { 534 case TOGGLE: 535 case QUERY: 536 dispversion(); 537 break; 538 case INIT: 539 set_output(1); /* Force output to stdout per GNU standard for --version output. */ 540 putstr("less "); 541 putstr(version); 542 putstr(" ("); 543 putstr(pattern_lib_name()); 544 putstr(" regular expressions)\n"); 545 { 546 char constant *copyright = 547 "Copyright (C) 1984-2022 Mark Nudelman\n\n"; 548 putstr(copyright); 549 } 550 if (version[strlen(version)-1] == 'x') 551 { 552 putstr("** This is an EXPERIMENTAL build of the 'less' software,\n"); 553 putstr("** and may not function correctly.\n"); 554 putstr("** Obtain release builds from the web page below.\n\n"); 555 } 556 putstr("less comes with NO WARRANTY, to the extent permitted by law.\n"); 557 putstr("For information about the terms of redistribution,\n"); 558 putstr("see the file named README in the less distribution.\n"); 559 putstr("Home page: https://greenwoodsoftware.com/less\n"); 560 quit(QUIT_OK); 561 break; 562 } 563 } 564 565 #if MSDOS_COMPILER 566 /* 567 * Parse an MSDOS color descriptor. 568 */ 569 static void 570 colordesc(s, fg_color, bg_color) 571 char *s; 572 int *fg_color; 573 int *bg_color; 574 { 575 int fg, bg; 576 #if MSDOS_COMPILER==WIN32C 577 int ul = 0; 578 579 if (*s == 'u') 580 { 581 ul = COMMON_LVB_UNDERSCORE; 582 s++; 583 if (*s == '\0') 584 { 585 *fg_color = nm_fg_color | ul; 586 *bg_color = nm_bg_color; 587 return; 588 } 589 } 590 #endif 591 if (parse_color(s, &fg, &bg) == CT_NULL) 592 { 593 PARG p; 594 p.p_string = s; 595 error("Invalid color string \"%s\"", &p); 596 } else 597 { 598 if (fg == CV_NOCHANGE) 599 fg = nm_fg_color; 600 if (bg == CV_NOCHANGE) 601 bg = nm_bg_color; 602 #if MSDOS_COMPILER==WIN32C 603 fg |= ul; 604 #endif 605 *fg_color = fg; 606 *bg_color = bg; 607 } 608 } 609 #endif 610 611 static int 612 color_from_namechar(namechar) 613 char namechar; 614 { 615 switch (namechar) 616 { 617 case 'B': return AT_COLOR_BIN; 618 case 'C': return AT_COLOR_CTRL; 619 case 'E': return AT_COLOR_ERROR; 620 case 'H': return AT_COLOR_HEADER; 621 case 'M': return AT_COLOR_MARK; 622 case 'N': return AT_COLOR_LINENUM; 623 case 'P': return AT_COLOR_PROMPT; 624 case 'R': return AT_COLOR_RSCROLL; 625 case 'S': return AT_COLOR_SEARCH; 626 case 'W': case 'A': return AT_COLOR_ATTN; 627 case 'n': return AT_NORMAL; 628 case 's': return AT_STANDOUT; 629 case 'd': return AT_BOLD; 630 case 'u': return AT_UNDERLINE; 631 case 'k': return AT_BLINK; 632 default: return -1; 633 } 634 } 635 636 /* 637 * Handler for the -D option. 638 */ 639 /*ARGSUSED*/ 640 public void 641 opt_D(type, s) 642 int type; 643 char *s; 644 { 645 PARG p; 646 int attr; 647 648 switch (type) 649 { 650 case INIT: 651 case TOGGLE: 652 #if MSDOS_COMPILER 653 if (*s == 'a') 654 { 655 sgr_mode = !sgr_mode; 656 break; 657 } 658 #endif 659 attr = color_from_namechar(s[0]); 660 if (attr < 0) 661 { 662 p.p_char = s[0]; 663 error("Invalid color specifier '%c'", &p); 664 return; 665 } 666 if (!use_color && (attr & AT_COLOR)) 667 { 668 error("Set --use-color before changing colors", NULL_PARG); 669 return; 670 } 671 s++; 672 #if MSDOS_COMPILER 673 if (!(attr & AT_COLOR)) 674 { 675 switch (attr) 676 { 677 case AT_NORMAL: 678 colordesc(s, &nm_fg_color, &nm_bg_color); 679 break; 680 case AT_BOLD: 681 colordesc(s, &bo_fg_color, &bo_bg_color); 682 break; 683 case AT_UNDERLINE: 684 colordesc(s, &ul_fg_color, &ul_bg_color); 685 break; 686 case AT_BLINK: 687 colordesc(s, &bl_fg_color, &bl_bg_color); 688 break; 689 case AT_STANDOUT: 690 colordesc(s, &so_fg_color, &so_bg_color); 691 break; 692 } 693 if (type == TOGGLE) 694 { 695 at_enter(AT_STANDOUT); 696 at_exit(); 697 } 698 } else 699 #endif 700 if (set_color_map(attr, s) < 0) 701 { 702 p.p_string = s; 703 error("Invalid color string \"%s\"", &p); 704 return; 705 } 706 break; 707 #if MSDOS_COMPILER 708 case QUERY: 709 p.p_string = (sgr_mode) ? "on" : "off"; 710 error("SGR mode is %s", &p); 711 break; 712 #endif 713 } 714 } 715 716 /* 717 * Handler for the -x option. 718 */ 719 public void 720 opt_x(type, s) 721 int type; 722 char *s; 723 { 724 extern int tabstops[]; 725 extern int ntabstops; 726 extern int tabdefault; 727 char msg[60+((INT_STRLEN_BOUND(int)+1)*TABSTOP_MAX)]; 728 int i; 729 PARG p; 730 731 switch (type) 732 { 733 case INIT: 734 case TOGGLE: 735 /* Start at 1 because tabstops[0] is always zero. */ 736 for (i = 1; i < TABSTOP_MAX; ) 737 { 738 int n = 0; 739 s = skipsp(s); 740 while (*s >= '0' && *s <= '9') 741 n = (10 * n) + (*s++ - '0'); 742 if (n > tabstops[i-1]) 743 tabstops[i++] = n; 744 s = skipsp(s); 745 if (*s++ != ',') 746 break; 747 } 748 if (i < 2) 749 return; 750 ntabstops = i; 751 tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2]; 752 break; 753 case QUERY: 754 strcpy(msg, "Tab stops "); 755 if (ntabstops > 2) 756 { 757 for (i = 1; i < ntabstops; i++) 758 { 759 if (i > 1) 760 strcat(msg, ","); 761 sprintf(msg+strlen(msg), "%d", tabstops[i]); 762 } 763 sprintf(msg+strlen(msg), " and then "); 764 } 765 sprintf(msg+strlen(msg), "every %d spaces", 766 tabdefault); 767 p.p_string = msg; 768 error("%s", &p); 769 break; 770 } 771 } 772 773 774 /* 775 * Handler for the -" option. 776 */ 777 public void 778 opt_quote(type, s) 779 int type; 780 char *s; 781 { 782 char buf[3]; 783 PARG parg; 784 785 switch (type) 786 { 787 case INIT: 788 case TOGGLE: 789 if (s[0] == '\0') 790 { 791 openquote = closequote = '\0'; 792 break; 793 } 794 if (s[1] != '\0' && s[2] != '\0') 795 { 796 error("-\" must be followed by 1 or 2 chars", NULL_PARG); 797 return; 798 } 799 openquote = s[0]; 800 if (s[1] == '\0') 801 closequote = openquote; 802 else 803 closequote = s[1]; 804 break; 805 case QUERY: 806 buf[0] = openquote; 807 buf[1] = closequote; 808 buf[2] = '\0'; 809 parg.p_string = buf; 810 error("quotes %s", &parg); 811 break; 812 } 813 } 814 815 /* 816 * Handler for the --rscroll option. 817 */ 818 /*ARGSUSED*/ 819 public void 820 opt_rscroll(type, s) 821 int type; 822 char *s; 823 { 824 PARG p; 825 826 switch (type) 827 { 828 case INIT: 829 case TOGGLE: { 830 char *fmt; 831 int attr = AT_STANDOUT; 832 setfmt(s, &fmt, &attr, "*s>"); 833 if (strcmp(fmt, "-") == 0) 834 { 835 rscroll_char = 0; 836 } else 837 { 838 rscroll_char = *fmt ? *fmt : '>'; 839 rscroll_attr = attr|AT_COLOR_RSCROLL; 840 } 841 break; } 842 case QUERY: { 843 p.p_string = rscroll_char ? prchar(rscroll_char) : "-"; 844 error("rscroll char is %s", &p); 845 break; } 846 } 847 } 848 849 /* 850 * "-?" means display a help message. 851 * If from the command line, exit immediately. 852 */ 853 /*ARGSUSED*/ 854 public void 855 opt_query(type, s) 856 int type; 857 char *s; 858 { 859 switch (type) 860 { 861 case QUERY: 862 case TOGGLE: 863 error("Use \"h\" for help", NULL_PARG); 864 break; 865 case INIT: 866 dohelp = 1; 867 } 868 } 869 870 /* 871 * Handler for the --mouse option. 872 */ 873 /*ARGSUSED*/ 874 public void 875 opt_mousecap(type, s) 876 int type; 877 char *s; 878 { 879 switch (type) 880 { 881 case TOGGLE: 882 if (mousecap == OPT_OFF) 883 deinit_mouse(); 884 else 885 init_mouse(); 886 break; 887 case INIT: 888 case QUERY: 889 break; 890 } 891 } 892 893 /* 894 * Handler for the --wheel-lines option. 895 */ 896 /*ARGSUSED*/ 897 public void 898 opt_wheel_lines(type, s) 899 int type; 900 char *s; 901 { 902 switch (type) 903 { 904 case INIT: 905 case TOGGLE: 906 if (wheel_lines <= 0) 907 wheel_lines = default_wheel_lines(); 908 break; 909 case QUERY: 910 break; 911 } 912 } 913 914 /* 915 * Handler for the --line-number-width option. 916 */ 917 /*ARGSUSED*/ 918 public void 919 opt_linenum_width(type, s) 920 int type; 921 char *s; 922 { 923 PARG parg; 924 925 switch (type) 926 { 927 case INIT: 928 case TOGGLE: 929 if (linenum_width > MAX_LINENUM_WIDTH) 930 { 931 parg.p_int = MAX_LINENUM_WIDTH; 932 error("Line number width must not be larger than %d", &parg); 933 linenum_width = MIN_LINENUM_WIDTH; 934 } 935 break; 936 case QUERY: 937 break; 938 } 939 } 940 941 /* 942 * Handler for the --status-column-width option. 943 */ 944 /*ARGSUSED*/ 945 public void 946 opt_status_col_width(type, s) 947 int type; 948 char *s; 949 { 950 PARG parg; 951 952 switch (type) 953 { 954 case INIT: 955 case TOGGLE: 956 if (status_col_width > MAX_STATUSCOL_WIDTH) 957 { 958 parg.p_int = MAX_STATUSCOL_WIDTH; 959 error("Status column width must not be larger than %d", &parg); 960 status_col_width = 2; 961 } 962 break; 963 case QUERY: 964 break; 965 } 966 } 967 968 /* 969 * Handler for the --file-size option. 970 */ 971 /*ARGSUSED*/ 972 public void 973 opt_filesize(type, s) 974 int type; 975 char *s; 976 { 977 switch (type) 978 { 979 case INIT: 980 case TOGGLE: 981 if (want_filesize && curr_ifile != NULL && ch_length() == NULL_POSITION) 982 scan_eof(); 983 break; 984 case QUERY: 985 break; 986 } 987 } 988 989 /* 990 * Handler for the --header option. 991 */ 992 /*ARGSUSED*/ 993 public void 994 opt_header(type, s) 995 int type; 996 char *s; 997 { 998 int err; 999 int n; 1000 1001 switch (type) 1002 { 1003 case INIT: 1004 case TOGGLE: 1005 n = getnum(&s, "header", &err); 1006 if (err) 1007 error("invalid number of lines", NULL_PARG); 1008 else 1009 { 1010 header_lines = n; 1011 header_cols = 0; 1012 if (*s == ',') 1013 { 1014 ++s; 1015 n = getnum(&s, "header", &err); 1016 if (err) 1017 error("invalid number of columns", NULL_PARG); 1018 else 1019 header_cols = n; 1020 } 1021 } 1022 break; 1023 case QUERY: 1024 { 1025 char buf[2*INT_STRLEN_BOUND(int)+2]; 1026 PARG parg; 1027 SNPRINTF2(buf, sizeof(buf), "%d,%d", header_lines, header_cols); 1028 parg.p_string = buf; 1029 error("header (lines,columns) is %s", &parg); 1030 } 1031 break; 1032 } 1033 } 1034 1035 /* 1036 * Handler for the --search-options option. 1037 */ 1038 /*ARGSUSED*/ 1039 public void 1040 opt_search_type(type, s) 1041 int type; 1042 char *s; 1043 { 1044 int st; 1045 PARG parg; 1046 char buf[16]; 1047 char *bp; 1048 1049 switch (type) 1050 { 1051 case INIT: 1052 case TOGGLE: 1053 st = 0; 1054 for (; *s != '\0'; s++) 1055 { 1056 switch (*s) 1057 { 1058 case 'E': case 'e': case CONTROL('E'): st |= SRCH_PAST_EOF; break; 1059 case 'F': case 'f': case CONTROL('F'): st |= SRCH_FIRST_FILE; break; 1060 case 'K': case 'k': case CONTROL('K'): st |= SRCH_NO_MOVE; break; 1061 case 'N': case 'n': case CONTROL('N'): st |= SRCH_NO_MATCH; break; 1062 case 'R': case 'r': case CONTROL('R'): st |= SRCH_NO_REGEX; break; 1063 case 'W': case 'w': case CONTROL('W'): st |= SRCH_WRAP; break; 1064 case '-': st = 0; break; 1065 case '^': break; 1066 default: 1067 parg.p_char = *s; 1068 error("invalid search option '%c'", &parg); 1069 return; 1070 } 1071 } 1072 def_search_type = norm_search_type(st); 1073 break; 1074 case QUERY: 1075 bp = buf; 1076 if (def_search_type & SRCH_PAST_EOF) *bp++ = 'E'; 1077 if (def_search_type & SRCH_FIRST_FILE) *bp++ = 'F'; 1078 if (def_search_type & SRCH_NO_MOVE) *bp++ = 'K'; 1079 if (def_search_type & SRCH_NO_MATCH) *bp++ = 'N'; 1080 if (def_search_type & SRCH_NO_REGEX) *bp++ = 'R'; 1081 if (def_search_type & SRCH_WRAP) *bp++ = 'W'; 1082 if (bp == buf) 1083 *bp++ = '-'; 1084 *bp = '\0'; 1085 parg.p_string = buf; 1086 error("search options: %s", &parg); 1087 break; 1088 } 1089 } 1090 1091 #if LESSTEST 1092 /* 1093 * Handler for the --tty option. 1094 */ 1095 /*ARGSUSED*/ 1096 public void 1097 opt_ttyin_name(type, s) 1098 int type; 1099 char *s; 1100 { 1101 switch (type) 1102 { 1103 case INIT: 1104 ttyin_name = s; 1105 is_tty = 1; 1106 break; 1107 } 1108 } 1109 1110 /* 1111 * Handler for the --rstat option. 1112 */ 1113 /*ARGSUSED*/ 1114 public void 1115 opt_rstat(type, s) 1116 int type; 1117 char *s; 1118 { 1119 switch (type) 1120 { 1121 case INIT: 1122 rstat_file = open(s, O_WRONLY|O_CREAT, 0664); 1123 if (rstat_file < 0) 1124 { 1125 PARG parg; 1126 parg.p_string = s; 1127 error("Cannot create rstat file \"%s\"", &parg); 1128 } 1129 break; 1130 } 1131 } 1132 #endif /*LESSTEST*/ 1133 1134 public int 1135 chop_line(VOID_PARAM) 1136 { 1137 return (chopline || header_cols > 0 || header_lines > 0); 1138 } 1139 1140 /* 1141 * Get the "screen window" size. 1142 */ 1143 public int 1144 get_swindow(VOID_PARAM) 1145 { 1146 if (swindow > 0) 1147 return (swindow); 1148 return (sc_height - header_lines + swindow); 1149 } 1150 1151