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