1a5f0fb15SPaul Saab /* 2*c77c4889SXin LI * Copyright (C) 1984-2024 Mark Nudelman 3a5f0fb15SPaul Saab * 4a5f0fb15SPaul Saab * You may distribute under the terms of either the GNU General Public 5a5f0fb15SPaul Saab * License or the Less License, as specified in the README file. 6a5f0fb15SPaul Saab * 796e55cc7SXin LI * For more information, see the README file. 8a5f0fb15SPaul Saab */ 9a5f0fb15SPaul Saab 10a5f0fb15SPaul Saab 11a5f0fb15SPaul Saab /* 12a5f0fb15SPaul Saab * Handling functions for command line options. 13a5f0fb15SPaul Saab * 14a5f0fb15SPaul Saab * Most options are handled by the generic code in option.c. 15a5f0fb15SPaul Saab * But all string options, and a few non-string options, require 16a5f0fb15SPaul Saab * special handling specific to the particular option. 17a5f0fb15SPaul Saab * This special processing is done by the "handling functions" in this file. 18a5f0fb15SPaul Saab * 19a5f0fb15SPaul Saab * Each handling function is passed a "type" and, if it is a string 20a5f0fb15SPaul Saab * option, the string which should be "assigned" to the option. 21a5f0fb15SPaul Saab * The type may be one of: 22a5f0fb15SPaul Saab * INIT The option is being initialized from the command line. 23a5f0fb15SPaul Saab * TOGGLE The option is being changed from within the program. 24a5f0fb15SPaul Saab * QUERY The setting of the option is merely being queried. 25a5f0fb15SPaul Saab */ 26a5f0fb15SPaul Saab 27a5f0fb15SPaul Saab #include "less.h" 28a5f0fb15SPaul Saab #include "option.h" 29*c77c4889SXin LI #include "position.h" 30a5f0fb15SPaul Saab 31000ba3e8STim J. Robbins extern int bufspace; 32a5f0fb15SPaul Saab extern int pr_type; 33*c77c4889SXin LI extern lbool plusoption; 34a5f0fb15SPaul Saab extern int swindow; 35f0be0a1fSXin LI extern int sc_width; 36a5f0fb15SPaul Saab extern int sc_height; 37a5f0fb15SPaul Saab extern int dohelp; 38a5f0fb15SPaul Saab extern char openquote; 39a5f0fb15SPaul Saab extern char closequote; 40a5f0fb15SPaul Saab extern char *prproto[]; 41a5f0fb15SPaul Saab extern char *eqproto; 42a5f0fb15SPaul Saab extern char *hproto; 43c9346414SPaul Saab extern char *wproto; 44a15691bfSXin LI extern char *every_first_cmd; 45a5f0fb15SPaul Saab extern IFILE curr_ifile; 46a5f0fb15SPaul Saab extern char version[]; 47efd72c2eSXin LI extern int jump_sline; 48f6b74a7dSXin LI extern long jump_sline_fraction; 49f0be0a1fSXin LI extern int shift_count; 50f6b74a7dSXin LI extern long shift_count_fraction; 51*c77c4889SXin LI extern int match_shift; 52*c77c4889SXin LI extern long match_shift_fraction; 53*c77c4889SXin LI extern LWCHAR rscroll_char; 54b2ea2440SXin LI extern int rscroll_attr; 55b7780dbeSXin LI extern int mousecap; 56b7780dbeSXin LI extern int wheel_lines; 57efd72c2eSXin LI extern int less_is_more; 582235c7feSXin LI extern int linenum_width; 592235c7feSXin LI extern int status_col_width; 602235c7feSXin LI extern int use_color; 6130a1828cSXin LI extern int want_filesize; 6295270f73SXin LI extern int header_lines; 6395270f73SXin LI extern int header_cols; 6495270f73SXin LI extern int def_search_type; 6595270f73SXin LI extern int chopline; 66d713e089SXin LI extern int tabstops[]; 67d713e089SXin LI extern int ntabstops; 68d713e089SXin LI extern int tabdefault; 69d713e089SXin LI extern char intr_char; 70*c77c4889SXin LI extern int nosearch_header_lines; 71*c77c4889SXin LI extern int nosearch_header_cols; 72*c77c4889SXin LI extern POSITION header_start_pos; 73*c77c4889SXin LI extern char *init_header; 74a5f0fb15SPaul Saab #if LOGFILE 75a5f0fb15SPaul Saab extern char *namelogfile; 76*c77c4889SXin LI extern lbool force_logfile; 77a5f0fb15SPaul Saab extern int logfile; 78a5f0fb15SPaul Saab #endif 79a5f0fb15SPaul Saab #if TAGS 80a5f0fb15SPaul Saab public char *tagoption = NULL; 81a5f0fb15SPaul Saab extern char *tags; 82a15691bfSXin LI extern char ztags[]; 83a5f0fb15SPaul Saab #endif 842235c7feSXin LI #if LESSTEST 85*c77c4889SXin LI extern constant char *ttyin_name; 86*c77c4889SXin LI extern int is_tty; 872235c7feSXin LI #endif /*LESSTEST*/ 88a5f0fb15SPaul Saab #if MSDOS_COMPILER 89*c77c4889SXin LI extern int nm_fg_color, nm_bg_color, nm_attr; 90*c77c4889SXin LI extern int bo_fg_color, bo_bg_color, bo_attr; 91*c77c4889SXin LI extern int ul_fg_color, ul_bg_color, ul_attr; 92*c77c4889SXin LI extern int so_fg_color, so_bg_color, so_attr; 93*c77c4889SXin LI extern int bl_fg_color, bl_bg_color, bl_attr; 94f6b74a7dSXin LI extern int sgr_mode; 95b2ea2440SXin LI #if MSDOS_COMPILER==WIN32C 96b2ea2440SXin LI #ifndef COMMON_LVB_UNDERSCORE 97b2ea2440SXin LI #define COMMON_LVB_UNDERSCORE 0x8000 98b2ea2440SXin LI #endif 99*c77c4889SXin LI #ifndef COMMON_LVB_REVERSE_VIDEO 100*c77c4889SXin LI #define COMMON_LVB_REVERSE_VIDEO 0x4000 101*c77c4889SXin LI #endif 102b2ea2440SXin LI #endif 103a5f0fb15SPaul Saab #endif 104a5f0fb15SPaul Saab 105a5f0fb15SPaul Saab 106a5f0fb15SPaul Saab #if LOGFILE 107a5f0fb15SPaul Saab /* 108a5f0fb15SPaul Saab * Handler for -o option. 109a5f0fb15SPaul Saab */ 110*c77c4889SXin LI public void opt_o(int type, constant char *s) 111a5f0fb15SPaul Saab { 112a5f0fb15SPaul Saab PARG parg; 113b2ea2440SXin LI char *filename; 114a5f0fb15SPaul Saab 115*c77c4889SXin LI if (!secure_allow(SF_LOGFILE)) 116a5f0fb15SPaul Saab { 117a5f0fb15SPaul Saab error("log file support is not available", NULL_PARG); 118a5f0fb15SPaul Saab return; 119a5f0fb15SPaul Saab } 120a5f0fb15SPaul Saab switch (type) 121a5f0fb15SPaul Saab { 122a5f0fb15SPaul Saab case INIT: 123a15691bfSXin LI namelogfile = save(s); 124a5f0fb15SPaul Saab break; 125a5f0fb15SPaul Saab case TOGGLE: 126a5f0fb15SPaul Saab if (ch_getflags() & CH_CANSEEK) 127a5f0fb15SPaul Saab { 128a5f0fb15SPaul Saab error("Input is not a pipe", NULL_PARG); 129a5f0fb15SPaul Saab return; 130a5f0fb15SPaul Saab } 131a5f0fb15SPaul Saab if (logfile >= 0) 132a5f0fb15SPaul Saab { 133a5f0fb15SPaul Saab error("Log file is already in use", NULL_PARG); 134a5f0fb15SPaul Saab return; 135a5f0fb15SPaul Saab } 136*c77c4889SXin LI s = skipspc(s); 137a15691bfSXin LI if (namelogfile != NULL) 138a15691bfSXin LI free(namelogfile); 139b2ea2440SXin LI filename = lglob(s); 140b2ea2440SXin LI namelogfile = shell_unquote(filename); 141b2ea2440SXin LI free(filename); 142a5f0fb15SPaul Saab use_logfile(namelogfile); 143a5f0fb15SPaul Saab sync_logfile(); 144a5f0fb15SPaul Saab break; 145a5f0fb15SPaul Saab case QUERY: 146a5f0fb15SPaul Saab if (logfile < 0) 147a5f0fb15SPaul Saab error("No log file", NULL_PARG); 148a5f0fb15SPaul Saab else 149a5f0fb15SPaul Saab { 150000ba3e8STim J. Robbins parg.p_string = namelogfile; 151a5f0fb15SPaul Saab error("Log file \"%s\"", &parg); 152a5f0fb15SPaul Saab } 153a5f0fb15SPaul Saab break; 154a5f0fb15SPaul Saab } 155a5f0fb15SPaul Saab } 156a5f0fb15SPaul Saab 157a5f0fb15SPaul Saab /* 158a5f0fb15SPaul Saab * Handler for -O option. 159a5f0fb15SPaul Saab */ 160*c77c4889SXin LI public void opt__O(int type, constant char *s) 161a5f0fb15SPaul Saab { 162a5f0fb15SPaul Saab force_logfile = TRUE; 163a5f0fb15SPaul Saab opt_o(type, s); 164a5f0fb15SPaul Saab } 165a5f0fb15SPaul Saab #endif 166a5f0fb15SPaul Saab 167*c77c4889SXin LI static int toggle_fraction(int *num, long *frac, constant char *s, constant char *printopt, void (*calc)(void)) 1687f074f9cSXin LI { 169*c77c4889SXin LI lbool err; 170*c77c4889SXin LI if (s == NULL) 1717f074f9cSXin LI { 172*c77c4889SXin LI (*calc)(); 173*c77c4889SXin LI } else if (*s == '.') 1747f074f9cSXin LI { 175*c77c4889SXin LI long tfrac; 1767f074f9cSXin LI s++; 177*c77c4889SXin LI tfrac = getfraction(&s, printopt, &err); 1787f074f9cSXin LI if (err) 179*c77c4889SXin LI { 180*c77c4889SXin LI error("Invalid fraction", NULL_PARG); 181*c77c4889SXin LI return -1; 182*c77c4889SXin LI } 183*c77c4889SXin LI *frac = tfrac; 184*c77c4889SXin LI (*calc)(); 1857f074f9cSXin LI } else 1867f074f9cSXin LI { 187*c77c4889SXin LI int tnum = getnumc(&s, printopt, &err); 1887f074f9cSXin LI if (err) 1897f074f9cSXin LI { 190*c77c4889SXin LI error("Invalid number", NULL_PARG); 191*c77c4889SXin LI return -1; 1927f074f9cSXin LI } 193*c77c4889SXin LI *frac = -1; 194*c77c4889SXin LI *num = tnum; 1957f074f9cSXin LI } 196*c77c4889SXin LI return 0; 197*c77c4889SXin LI } 198*c77c4889SXin LI 199*c77c4889SXin LI static void query_fraction(int value, long fraction, constant char *int_msg, constant char *frac_msg) 2007f074f9cSXin LI { 201*c77c4889SXin LI PARG parg; 202*c77c4889SXin LI 203*c77c4889SXin LI if (fraction < 0) 204*c77c4889SXin LI { 205*c77c4889SXin LI parg.p_int = value; 206*c77c4889SXin LI error(int_msg, &parg); 2077f074f9cSXin LI } else 2087f074f9cSXin LI { 209f80a33eaSXin LI char buf[INT_STRLEN_BOUND(long)+2]; 210*c77c4889SXin LI size_t len; 211*c77c4889SXin LI SNPRINTF1(buf, sizeof(buf), ".%06ld", fraction); 212*c77c4889SXin LI len = strlen(buf); 2137f074f9cSXin LI while (len > 2 && buf[len-1] == '0') 2147f074f9cSXin LI len--; 2157f074f9cSXin LI buf[len] = '\0'; 2167f074f9cSXin LI parg.p_string = buf; 217*c77c4889SXin LI error(frac_msg, &parg); 2187f074f9cSXin LI } 219*c77c4889SXin LI } 220*c77c4889SXin LI 221*c77c4889SXin LI /* 222*c77c4889SXin LI * Handlers for -j option. 223*c77c4889SXin LI */ 224*c77c4889SXin LI public void opt_j(int type, constant char *s) 225*c77c4889SXin LI { 226*c77c4889SXin LI switch (type) 227*c77c4889SXin LI { 228*c77c4889SXin LI case INIT: 229*c77c4889SXin LI case TOGGLE: 230*c77c4889SXin LI toggle_fraction(&jump_sline, &jump_sline_fraction, 231*c77c4889SXin LI s, "j", calc_jump_sline); 232*c77c4889SXin LI break; 233*c77c4889SXin LI case QUERY: 234*c77c4889SXin LI query_fraction(jump_sline, jump_sline_fraction, 235*c77c4889SXin LI "Position target at screen line %d", "Position target at screen position %s"); 2367f074f9cSXin LI break; 2377f074f9cSXin LI } 2387f074f9cSXin LI } 2397f074f9cSXin LI 240d713e089SXin LI public void calc_jump_sline(void) 2417f074f9cSXin LI { 242*c77c4889SXin LI if (jump_sline_fraction >= 0) 243f80a33eaSXin LI jump_sline = (int) muldiv(sc_height, jump_sline_fraction, NUM_FRAC_DENOM); 244*c77c4889SXin LI if (jump_sline <= header_lines) 245*c77c4889SXin LI jump_sline = header_lines + 1; 2467f074f9cSXin LI } 2477f074f9cSXin LI 248f0be0a1fSXin LI /* 249f0be0a1fSXin LI * Handlers for -# option. 250f0be0a1fSXin LI */ 251*c77c4889SXin LI public void opt_shift(int type, constant char *s) 252f0be0a1fSXin LI { 253f0be0a1fSXin LI switch (type) 254f0be0a1fSXin LI { 255f0be0a1fSXin LI case INIT: 256f0be0a1fSXin LI case TOGGLE: 257*c77c4889SXin LI toggle_fraction(&shift_count, &shift_count_fraction, 258*c77c4889SXin LI s, "#", calc_shift_count); 259f0be0a1fSXin LI break; 260f0be0a1fSXin LI case QUERY: 261*c77c4889SXin LI query_fraction(shift_count, shift_count_fraction, 262*c77c4889SXin LI "Horizontal shift %d columns", "Horizontal shift %s of screen width"); 263f0be0a1fSXin LI break; 264f0be0a1fSXin LI } 265f0be0a1fSXin LI } 26630a1828cSXin LI 267d713e089SXin LI public void calc_shift_count(void) 268f0be0a1fSXin LI { 269f0be0a1fSXin LI if (shift_count_fraction < 0) 270f0be0a1fSXin LI return; 271f80a33eaSXin LI shift_count = (int) muldiv(sc_width, shift_count_fraction, NUM_FRAC_DENOM); 272f0be0a1fSXin LI } 273f0be0a1fSXin LI 274a5f0fb15SPaul Saab #if USERFILE 275*c77c4889SXin LI public void opt_k(int type, constant char *s) 276a5f0fb15SPaul Saab { 277a5f0fb15SPaul Saab PARG parg; 278a5f0fb15SPaul Saab 279a5f0fb15SPaul Saab switch (type) 280a5f0fb15SPaul Saab { 281a5f0fb15SPaul Saab case INIT: 282a5f0fb15SPaul Saab if (lesskey(s, 0)) 283a5f0fb15SPaul Saab { 284000ba3e8STim J. Robbins parg.p_string = s; 285a5f0fb15SPaul Saab error("Cannot use lesskey file \"%s\"", &parg); 286a5f0fb15SPaul Saab } 287a5f0fb15SPaul Saab break; 288a5f0fb15SPaul Saab } 289a5f0fb15SPaul Saab } 29030a1828cSXin LI 29130a1828cSXin LI #if HAVE_LESSKEYSRC 292*c77c4889SXin LI public void opt_ks(int type, constant char *s) 29330a1828cSXin LI { 29430a1828cSXin LI PARG parg; 29530a1828cSXin LI 29630a1828cSXin LI switch (type) 29730a1828cSXin LI { 29830a1828cSXin LI case INIT: 29930a1828cSXin LI if (lesskey_src(s, 0)) 30030a1828cSXin LI { 30130a1828cSXin LI parg.p_string = s; 30230a1828cSXin LI error("Cannot use lesskey source file \"%s\"", &parg); 30330a1828cSXin LI } 30430a1828cSXin LI break; 30530a1828cSXin LI } 30630a1828cSXin LI } 307*c77c4889SXin LI 308*c77c4889SXin LI public void opt_kc(int type, constant char *s) 309*c77c4889SXin LI { 310*c77c4889SXin LI switch (type) 311*c77c4889SXin LI { 312*c77c4889SXin LI case INIT: 313*c77c4889SXin LI if (lesskey_content(s, 0)) 314*c77c4889SXin LI { 315*c77c4889SXin LI error("Error in lesskey content", NULL_PARG); 316*c77c4889SXin LI } 317*c77c4889SXin LI break; 318*c77c4889SXin LI } 319*c77c4889SXin LI } 320*c77c4889SXin LI 32130a1828cSXin LI #endif /* HAVE_LESSKEYSRC */ 32230a1828cSXin LI #endif /* USERFILE */ 323a5f0fb15SPaul Saab 324*c77c4889SXin LI /* 325*c77c4889SXin LI * Handler for -S option. 326*c77c4889SXin LI */ 327*c77c4889SXin LI public void opt__S(int type, constant char *s) 328*c77c4889SXin LI { 329*c77c4889SXin LI switch (type) 330*c77c4889SXin LI { 331*c77c4889SXin LI case TOGGLE: 332*c77c4889SXin LI pos_rehead(); 333*c77c4889SXin LI break; 334*c77c4889SXin LI } 335*c77c4889SXin LI } 336*c77c4889SXin LI 337a5f0fb15SPaul Saab #if TAGS 338a5f0fb15SPaul Saab /* 339a5f0fb15SPaul Saab * Handler for -t option. 340a5f0fb15SPaul Saab */ 341*c77c4889SXin LI public void opt_t(int type, constant char *s) 342a5f0fb15SPaul Saab { 343a5f0fb15SPaul Saab IFILE save_ifile; 344a5f0fb15SPaul Saab POSITION pos; 345a5f0fb15SPaul Saab 346a5f0fb15SPaul Saab switch (type) 347a5f0fb15SPaul Saab { 348a5f0fb15SPaul Saab case INIT: 349a15691bfSXin LI tagoption = save(s); 350a5f0fb15SPaul Saab /* Do the rest in main() */ 351a5f0fb15SPaul Saab break; 352a5f0fb15SPaul Saab case TOGGLE: 353*c77c4889SXin LI if (!secure_allow(SF_TAGS)) 354a5f0fb15SPaul Saab { 355a5f0fb15SPaul Saab error("tags support is not available", NULL_PARG); 356a5f0fb15SPaul Saab break; 357a5f0fb15SPaul Saab } 358*c77c4889SXin LI findtag(skipspc(s)); 359a5f0fb15SPaul Saab save_ifile = save_curr_ifile(); 3606dcb072bSXin LI /* 3616dcb072bSXin LI * Try to open the file containing the tag 3626dcb072bSXin LI * and search for the tag in that file. 3636dcb072bSXin LI */ 3646dcb072bSXin LI if (edit_tagfile() || (pos = tagsearch()) == NULL_POSITION) 365a5f0fb15SPaul Saab { 3666dcb072bSXin LI /* Failed: reopen the old file. */ 367a5f0fb15SPaul Saab reedit_ifile(save_ifile); 368a5f0fb15SPaul Saab break; 369a5f0fb15SPaul Saab } 370a5f0fb15SPaul Saab unsave_ifile(save_ifile); 371a5f0fb15SPaul Saab jump_loc(pos, jump_sline); 372a5f0fb15SPaul Saab break; 373a5f0fb15SPaul Saab } 374a5f0fb15SPaul Saab } 375a5f0fb15SPaul Saab 376a5f0fb15SPaul Saab /* 377a5f0fb15SPaul Saab * Handler for -T option. 378a5f0fb15SPaul Saab */ 379*c77c4889SXin LI public void opt__T(int type, constant char *s) 380a5f0fb15SPaul Saab { 381a5f0fb15SPaul Saab PARG parg; 382b2ea2440SXin LI char *filename; 383a5f0fb15SPaul Saab 384a5f0fb15SPaul Saab switch (type) 385a5f0fb15SPaul Saab { 386a5f0fb15SPaul Saab case INIT: 387a15691bfSXin LI tags = save(s); 388a5f0fb15SPaul Saab break; 389a5f0fb15SPaul Saab case TOGGLE: 390*c77c4889SXin LI s = skipspc(s); 391a15691bfSXin LI if (tags != NULL && tags != ztags) 392a15691bfSXin LI free(tags); 393b2ea2440SXin LI filename = lglob(s); 394b2ea2440SXin LI tags = shell_unquote(filename); 395b2ea2440SXin LI free(filename); 396a5f0fb15SPaul Saab break; 397a5f0fb15SPaul Saab case QUERY: 398000ba3e8STim J. Robbins parg.p_string = tags; 399a5f0fb15SPaul Saab error("Tags file \"%s\"", &parg); 400a5f0fb15SPaul Saab break; 401a5f0fb15SPaul Saab } 402a5f0fb15SPaul Saab } 403a5f0fb15SPaul Saab #endif 404a5f0fb15SPaul Saab 405a5f0fb15SPaul Saab /* 406a5f0fb15SPaul Saab * Handler for -p option. 407a5f0fb15SPaul Saab */ 408*c77c4889SXin LI public void opt_p(int type, constant char *s) 409a5f0fb15SPaul Saab { 410a5f0fb15SPaul Saab switch (type) 411a5f0fb15SPaul Saab { 412a5f0fb15SPaul Saab case INIT: 413a5f0fb15SPaul Saab /* 414a15691bfSXin LI * Unget a command for the specified string. 415a5f0fb15SPaul Saab */ 416a15691bfSXin LI if (less_is_more) 417a15691bfSXin LI { 4186dcb072bSXin LI /* 4196dcb072bSXin LI * In "more" mode, the -p argument is a command, 4206dcb072bSXin LI * not a search string, so we don't need a slash. 4216dcb072bSXin LI */ 422a15691bfSXin LI every_first_cmd = save(s); 423a15691bfSXin LI } else 424a15691bfSXin LI { 425a15691bfSXin LI plusoption = TRUE; 426a15691bfSXin LI /* 427a15691bfSXin LI * {{ This won't work if the "/" command is 428a15691bfSXin LI * changed or invalidated by a .lesskey file. }} 429a15691bfSXin LI */ 430a5f0fb15SPaul Saab ungetsc("/"); 4312235c7feSXin LI ungetsc(s); 432*c77c4889SXin LI ungetcc_end_command(); 433a15691bfSXin LI } 434a5f0fb15SPaul Saab break; 435a5f0fb15SPaul Saab } 436a5f0fb15SPaul Saab } 437a5f0fb15SPaul Saab 438a5f0fb15SPaul Saab /* 439a5f0fb15SPaul Saab * Handler for -P option. 440a5f0fb15SPaul Saab */ 441*c77c4889SXin LI public void opt__P(int type, constant char *s) 442a5f0fb15SPaul Saab { 4431ea31627SRobert Watson char **proto; 444a5f0fb15SPaul Saab PARG parg; 445a5f0fb15SPaul Saab 446a5f0fb15SPaul Saab switch (type) 447a5f0fb15SPaul Saab { 448a5f0fb15SPaul Saab case INIT: 449a5f0fb15SPaul Saab case TOGGLE: 450a5f0fb15SPaul Saab /* 451a5f0fb15SPaul Saab * Figure out which prototype string should be changed. 452a5f0fb15SPaul Saab */ 453a5f0fb15SPaul Saab switch (*s) 454a5f0fb15SPaul Saab { 455a5f0fb15SPaul Saab case 's': proto = &prproto[PR_SHORT]; s++; break; 456a5f0fb15SPaul Saab case 'm': proto = &prproto[PR_MEDIUM]; s++; break; 457a5f0fb15SPaul Saab case 'M': proto = &prproto[PR_LONG]; s++; break; 458a5f0fb15SPaul Saab case '=': proto = &eqproto; s++; break; 459a5f0fb15SPaul Saab case 'h': proto = &hproto; s++; break; 460c9346414SPaul Saab case 'w': proto = &wproto; s++; break; 461a5f0fb15SPaul Saab default: proto = &prproto[PR_SHORT]; break; 462a5f0fb15SPaul Saab } 463a5f0fb15SPaul Saab free(*proto); 464a5f0fb15SPaul Saab *proto = save(s); 465a5f0fb15SPaul Saab break; 466a5f0fb15SPaul Saab case QUERY: 467a5f0fb15SPaul Saab parg.p_string = prproto[pr_type]; 468a5f0fb15SPaul Saab error("%s", &parg); 469a5f0fb15SPaul Saab break; 470a5f0fb15SPaul Saab } 471a5f0fb15SPaul Saab } 472a5f0fb15SPaul Saab 473a5f0fb15SPaul Saab /* 474a5f0fb15SPaul Saab * Handler for the -b option. 475a5f0fb15SPaul Saab */ 476a5f0fb15SPaul Saab /*ARGSUSED*/ 477*c77c4889SXin LI public void opt_b(int type, constant char *s) 478a5f0fb15SPaul Saab { 479a5f0fb15SPaul Saab switch (type) 480a5f0fb15SPaul Saab { 481a5f0fb15SPaul Saab case INIT: 482000ba3e8STim J. Robbins case TOGGLE: 483000ba3e8STim J. Robbins /* 484000ba3e8STim J. Robbins * Set the new number of buffers. 485000ba3e8STim J. Robbins */ 486*c77c4889SXin LI ch_setbufspace((ssize_t) bufspace); 487000ba3e8STim J. Robbins break; 488000ba3e8STim J. Robbins case QUERY: 489a5f0fb15SPaul Saab break; 490a5f0fb15SPaul Saab } 491a5f0fb15SPaul Saab } 492a5f0fb15SPaul Saab 493a5f0fb15SPaul Saab /* 494a5f0fb15SPaul Saab * Handler for the -i option. 495a5f0fb15SPaul Saab */ 496a5f0fb15SPaul Saab /*ARGSUSED*/ 497*c77c4889SXin LI public void opt_i(int type, constant char *s) 498a5f0fb15SPaul Saab { 499a5f0fb15SPaul Saab switch (type) 500a5f0fb15SPaul Saab { 501a5f0fb15SPaul Saab case TOGGLE: 502a5f0fb15SPaul Saab chg_caseless(); 503a5f0fb15SPaul Saab break; 504a5f0fb15SPaul Saab case QUERY: 505a5f0fb15SPaul Saab case INIT: 506a5f0fb15SPaul Saab break; 507a5f0fb15SPaul Saab } 508a5f0fb15SPaul Saab } 509a5f0fb15SPaul Saab 510a5f0fb15SPaul Saab /* 511a5f0fb15SPaul Saab * Handler for the -V option. 512a5f0fb15SPaul Saab */ 513a5f0fb15SPaul Saab /*ARGSUSED*/ 514*c77c4889SXin LI public void opt__V(int type, constant char *s) 515a5f0fb15SPaul Saab { 516a5f0fb15SPaul Saab switch (type) 517a5f0fb15SPaul Saab { 518a5f0fb15SPaul Saab case TOGGLE: 519a5f0fb15SPaul Saab case QUERY: 520a5f0fb15SPaul Saab dispversion(); 521a5f0fb15SPaul Saab break; 522a5f0fb15SPaul Saab case INIT: 5232235c7feSXin LI set_output(1); /* Force output to stdout per GNU standard for --version output. */ 524a5f0fb15SPaul Saab putstr("less "); 525a5f0fb15SPaul Saab putstr(version); 52696e55cc7SXin LI putstr(" ("); 527b7780dbeSXin LI putstr(pattern_lib_name()); 52896e55cc7SXin LI putstr(" regular expressions)\n"); 5292235c7feSXin LI { 53030a1828cSXin LI char constant *copyright = 531*c77c4889SXin LI "Copyright (C) 1984-2024 Mark Nudelman\n\n"; 5322235c7feSXin LI putstr(copyright); 5332235c7feSXin LI } 5342235c7feSXin LI if (version[strlen(version)-1] == 'x') 5352235c7feSXin LI { 5362235c7feSXin LI putstr("** This is an EXPERIMENTAL build of the 'less' software,\n"); 5372235c7feSXin LI putstr("** and may not function correctly.\n"); 5382235c7feSXin LI putstr("** Obtain release builds from the web page below.\n\n"); 5392235c7feSXin LI } 540d713e089SXin LI #if LESSTEST 541d713e089SXin LI putstr("This build supports LESSTEST.\n"); 542d713e089SXin LI #endif /*LESSTEST*/ 543a5f0fb15SPaul Saab putstr("less comes with NO WARRANTY, to the extent permitted by law.\n"); 544a5f0fb15SPaul Saab putstr("For information about the terms of redistribution,\n"); 545a5f0fb15SPaul Saab putstr("see the file named README in the less distribution.\n"); 5462235c7feSXin LI putstr("Home page: https://greenwoodsoftware.com/less\n"); 547a5f0fb15SPaul Saab quit(QUIT_OK); 548a5f0fb15SPaul Saab break; 549a5f0fb15SPaul Saab } 550a5f0fb15SPaul Saab } 551a5f0fb15SPaul Saab 552a5f0fb15SPaul Saab #if MSDOS_COMPILER 553a5f0fb15SPaul Saab /* 554a5f0fb15SPaul Saab * Parse an MSDOS color descriptor. 555a5f0fb15SPaul Saab */ 556*c77c4889SXin LI static void colordesc(constant char *s, int *fg_color, int *bg_color, int *dattr) 557a5f0fb15SPaul Saab { 558a5f0fb15SPaul Saab int fg, bg; 559*c77c4889SXin LI CHAR_ATTR attr; 560*c77c4889SXin LI if (parse_color(s, &fg, &bg, &attr) == CT_NULL) 561b2ea2440SXin LI { 5622235c7feSXin LI PARG p; 5632235c7feSXin LI p.p_string = s; 5642235c7feSXin LI error("Invalid color string \"%s\"", &p); 5652235c7feSXin LI } else 5662235c7feSXin LI { 567a5f0fb15SPaul Saab *fg_color = fg; 568a5f0fb15SPaul Saab *bg_color = bg; 569*c77c4889SXin LI *dattr = 0; 570*c77c4889SXin LI #if MSDOS_COMPILER==WIN32C 571*c77c4889SXin LI if (attr & CATTR_UNDERLINE) 572*c77c4889SXin LI *dattr |= COMMON_LVB_UNDERSCORE; 573*c77c4889SXin LI if (attr & CATTR_STANDOUT) 574*c77c4889SXin LI *dattr |= COMMON_LVB_REVERSE_VIDEO; 575*c77c4889SXin LI #endif 576a5f0fb15SPaul Saab } 5772235c7feSXin LI } 5782235c7feSXin LI #endif 5792235c7feSXin LI 580d713e089SXin LI static int color_from_namechar(char namechar) 5812235c7feSXin LI { 5822235c7feSXin LI switch (namechar) 5832235c7feSXin LI { 5842235c7feSXin LI case 'B': return AT_COLOR_BIN; 5852235c7feSXin LI case 'C': return AT_COLOR_CTRL; 5862235c7feSXin LI case 'E': return AT_COLOR_ERROR; 58795270f73SXin LI case 'H': return AT_COLOR_HEADER; 5882235c7feSXin LI case 'M': return AT_COLOR_MARK; 5892235c7feSXin LI case 'N': return AT_COLOR_LINENUM; 5902235c7feSXin LI case 'P': return AT_COLOR_PROMPT; 5912235c7feSXin LI case 'R': return AT_COLOR_RSCROLL; 5922235c7feSXin LI case 'S': return AT_COLOR_SEARCH; 59395270f73SXin LI case 'W': case 'A': return AT_COLOR_ATTN; 5942235c7feSXin LI case 'n': return AT_NORMAL; 5952235c7feSXin LI case 's': return AT_STANDOUT; 5962235c7feSXin LI case 'd': return AT_BOLD; 5972235c7feSXin LI case 'u': return AT_UNDERLINE; 5982235c7feSXin LI case 'k': return AT_BLINK; 599d713e089SXin LI default: 600d713e089SXin LI if (namechar >= '1' && namechar <= '0'+NUM_SEARCH_COLORS) 601d713e089SXin LI return AT_COLOR_SUBSEARCH(namechar-'0'); 602d713e089SXin LI return -1; 6032235c7feSXin LI } 6042235c7feSXin LI } 605a5f0fb15SPaul Saab 606a5f0fb15SPaul Saab /* 607a5f0fb15SPaul Saab * Handler for the -D option. 608a5f0fb15SPaul Saab */ 609a5f0fb15SPaul Saab /*ARGSUSED*/ 610*c77c4889SXin LI public void opt_D(int type, constant char *s) 611a5f0fb15SPaul Saab { 612f6b74a7dSXin LI PARG p; 6132235c7feSXin LI int attr; 614f6b74a7dSXin LI 615a5f0fb15SPaul Saab switch (type) 616a5f0fb15SPaul Saab { 617a5f0fb15SPaul Saab case INIT: 618a5f0fb15SPaul Saab case TOGGLE: 6192235c7feSXin LI #if MSDOS_COMPILER 6202235c7feSXin LI if (*s == 'a') 621a5f0fb15SPaul Saab { 622f6b74a7dSXin LI sgr_mode = !sgr_mode; 623f6b74a7dSXin LI break; 6242235c7feSXin LI } 6252235c7feSXin LI #endif 6262235c7feSXin LI attr = color_from_namechar(s[0]); 6272235c7feSXin LI if (attr < 0) 6282235c7feSXin LI { 6292235c7feSXin LI p.p_char = s[0]; 6302235c7feSXin LI error("Invalid color specifier '%c'", &p); 6312235c7feSXin LI return; 6322235c7feSXin LI } 6332235c7feSXin LI if (!use_color && (attr & AT_COLOR)) 6342235c7feSXin LI { 6352235c7feSXin LI error("Set --use-color before changing colors", NULL_PARG); 6362235c7feSXin LI return; 6372235c7feSXin LI } 6382235c7feSXin LI s++; 6392235c7feSXin LI #if MSDOS_COMPILER 6402235c7feSXin LI if (!(attr & AT_COLOR)) 6412235c7feSXin LI { 6422235c7feSXin LI switch (attr) 6432235c7feSXin LI { 6442235c7feSXin LI case AT_NORMAL: 645*c77c4889SXin LI colordesc(s, &nm_fg_color, &nm_bg_color, &nm_attr); 6462235c7feSXin LI break; 6472235c7feSXin LI case AT_BOLD: 648*c77c4889SXin LI colordesc(s, &bo_fg_color, &bo_bg_color, &bo_attr); 6492235c7feSXin LI break; 6502235c7feSXin LI case AT_UNDERLINE: 651*c77c4889SXin LI colordesc(s, &ul_fg_color, &ul_bg_color, &ul_attr); 6522235c7feSXin LI break; 6532235c7feSXin LI case AT_BLINK: 654*c77c4889SXin LI colordesc(s, &bl_fg_color, &bl_bg_color, &bl_attr); 6552235c7feSXin LI break; 6562235c7feSXin LI case AT_STANDOUT: 657*c77c4889SXin LI colordesc(s, &so_fg_color, &so_bg_color, &so_attr); 658a5f0fb15SPaul Saab break; 659a5f0fb15SPaul Saab } 660a5f0fb15SPaul Saab if (type == TOGGLE) 661a5f0fb15SPaul Saab { 662*c77c4889SXin LI init_win_colors(); 6636dcb072bSXin LI at_enter(AT_STANDOUT); 6646dcb072bSXin LI at_exit(); 665a5f0fb15SPaul Saab } 6662235c7feSXin LI } else 6672235c7feSXin LI #endif 6682235c7feSXin LI if (set_color_map(attr, s) < 0) 6692235c7feSXin LI { 6702235c7feSXin LI p.p_string = s; 6712235c7feSXin LI error("Invalid color string \"%s\"", &p); 6722235c7feSXin LI return; 6732235c7feSXin LI } 674a5f0fb15SPaul Saab break; 6752235c7feSXin LI #if MSDOS_COMPILER 676a5f0fb15SPaul Saab case QUERY: 677f6b74a7dSXin LI p.p_string = (sgr_mode) ? "on" : "off"; 678f6b74a7dSXin LI error("SGR mode is %s", &p); 679a5f0fb15SPaul Saab break; 680a5f0fb15SPaul Saab #endif 6812235c7feSXin LI } 6822235c7feSXin LI } 683a5f0fb15SPaul Saab 684a5f0fb15SPaul Saab /* 685d713e089SXin LI */ 686*c77c4889SXin LI public void set_tabs(constant char *s, size_t len) 687d713e089SXin LI { 688d713e089SXin LI int i; 689*c77c4889SXin LI constant char *es = s + len; 690d713e089SXin LI /* Start at 1 because tabstops[0] is always zero. */ 691d713e089SXin LI for (i = 1; i < TABSTOP_MAX; ) 692d713e089SXin LI { 693d713e089SXin LI int n = 0; 694*c77c4889SXin LI lbool v = FALSE; 695d713e089SXin LI while (s < es && *s == ' ') 696d713e089SXin LI s++; 697d713e089SXin LI for (; s < es && *s >= '0' && *s <= '9'; s++) 698d713e089SXin LI { 699*c77c4889SXin LI v = v || ckd_mul(&n, n, 10); 700*c77c4889SXin LI v = v || ckd_add(&n, n, *s - '0'); 701d713e089SXin LI } 702d713e089SXin LI if (!v && n > tabstops[i-1]) 703d713e089SXin LI tabstops[i++] = n; 704d713e089SXin LI while (s < es && *s == ' ') 705d713e089SXin LI s++; 706d713e089SXin LI if (s == es || *s++ != ',') 707d713e089SXin LI break; 708d713e089SXin LI } 709d713e089SXin LI if (i < 2) 710d713e089SXin LI return; 711d713e089SXin LI ntabstops = i; 712d713e089SXin LI tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2]; 713d713e089SXin LI } 714d713e089SXin LI 715d713e089SXin LI /* 716c9346414SPaul Saab * Handler for the -x option. 717c9346414SPaul Saab */ 718*c77c4889SXin LI public void opt_x(int type, constant char *s) 719c9346414SPaul Saab { 72095270f73SXin LI char msg[60+((INT_STRLEN_BOUND(int)+1)*TABSTOP_MAX)]; 721c9346414SPaul Saab int i; 722c9346414SPaul Saab PARG p; 723c9346414SPaul Saab 724c9346414SPaul Saab switch (type) 725c9346414SPaul Saab { 726c9346414SPaul Saab case INIT: 727c9346414SPaul Saab case TOGGLE: 728d713e089SXin LI set_tabs(s, strlen(s)); 729c9346414SPaul Saab break; 730c9346414SPaul Saab case QUERY: 731c9346414SPaul Saab strcpy(msg, "Tab stops "); 732c9346414SPaul Saab if (ntabstops > 2) 733c9346414SPaul Saab { 734c9346414SPaul Saab for (i = 1; i < ntabstops; i++) 735c9346414SPaul Saab { 736c9346414SPaul Saab if (i > 1) 737c9346414SPaul Saab strcat(msg, ","); 738c9346414SPaul Saab sprintf(msg+strlen(msg), "%d", tabstops[i]); 739c9346414SPaul Saab } 740c9346414SPaul Saab sprintf(msg+strlen(msg), " and then "); 741c9346414SPaul Saab } 742c9346414SPaul Saab sprintf(msg+strlen(msg), "every %d spaces", 743c9346414SPaul Saab tabdefault); 744c9346414SPaul Saab p.p_string = msg; 745c9346414SPaul Saab error("%s", &p); 746c9346414SPaul Saab break; 747c9346414SPaul Saab } 748c9346414SPaul Saab } 749c9346414SPaul Saab 750c9346414SPaul Saab 751c9346414SPaul Saab /* 752a5f0fb15SPaul Saab * Handler for the -" option. 753a5f0fb15SPaul Saab */ 754*c77c4889SXin LI public void opt_quote(int type, constant char *s) 755a5f0fb15SPaul Saab { 756a5f0fb15SPaul Saab char buf[3]; 757a5f0fb15SPaul Saab PARG parg; 758a5f0fb15SPaul Saab 759a5f0fb15SPaul Saab switch (type) 760a5f0fb15SPaul Saab { 761a5f0fb15SPaul Saab case INIT: 762a5f0fb15SPaul Saab case TOGGLE: 763000ba3e8STim J. Robbins if (s[0] == '\0') 764000ba3e8STim J. Robbins { 765000ba3e8STim J. Robbins openquote = closequote = '\0'; 766000ba3e8STim J. Robbins break; 767000ba3e8STim J. Robbins } 768a5f0fb15SPaul Saab if (s[1] != '\0' && s[2] != '\0') 769a5f0fb15SPaul Saab { 770a5f0fb15SPaul Saab error("-\" must be followed by 1 or 2 chars", NULL_PARG); 771a5f0fb15SPaul Saab return; 772a5f0fb15SPaul Saab } 773a5f0fb15SPaul Saab openquote = s[0]; 774a5f0fb15SPaul Saab if (s[1] == '\0') 775a5f0fb15SPaul Saab closequote = openquote; 776a5f0fb15SPaul Saab else 777a5f0fb15SPaul Saab closequote = s[1]; 778a5f0fb15SPaul Saab break; 779a5f0fb15SPaul Saab case QUERY: 780a5f0fb15SPaul Saab buf[0] = openquote; 781a5f0fb15SPaul Saab buf[1] = closequote; 782a5f0fb15SPaul Saab buf[2] = '\0'; 783a5f0fb15SPaul Saab parg.p_string = buf; 784a5f0fb15SPaul Saab error("quotes %s", &parg); 785a5f0fb15SPaul Saab break; 786a5f0fb15SPaul Saab } 787a5f0fb15SPaul Saab } 788a5f0fb15SPaul Saab 789a5f0fb15SPaul Saab /* 790b2ea2440SXin LI * Handler for the --rscroll option. 791b2ea2440SXin LI */ 792b2ea2440SXin LI /*ARGSUSED*/ 793*c77c4889SXin LI public void opt_rscroll(int type, constant char *s) 794b2ea2440SXin LI { 795b2ea2440SXin LI PARG p; 796b2ea2440SXin LI 797b2ea2440SXin LI switch (type) 798b2ea2440SXin LI { 799b2ea2440SXin LI case INIT: 800b2ea2440SXin LI case TOGGLE: { 801*c77c4889SXin LI constant char *fmt; 802b2ea2440SXin LI int attr = AT_STANDOUT; 803d713e089SXin LI setfmt(s, &fmt, &attr, "*s>", FALSE); 804b2ea2440SXin LI if (strcmp(fmt, "-") == 0) 805b2ea2440SXin LI { 806b2ea2440SXin LI rscroll_char = 0; 807b2ea2440SXin LI } else 808b2ea2440SXin LI { 8092235c7feSXin LI rscroll_attr = attr|AT_COLOR_RSCROLL; 810*c77c4889SXin LI if (*fmt == '\0') 811*c77c4889SXin LI rscroll_char = '>'; 812*c77c4889SXin LI else 813*c77c4889SXin LI { 814*c77c4889SXin LI LWCHAR ch = step_charc(&fmt, +1, fmt+strlen(fmt)); 815*c77c4889SXin LI if (pwidth(ch, rscroll_attr, 0, 0) > 1) 816*c77c4889SXin LI error("cannot set rscroll to a wide character", NULL_PARG); 817*c77c4889SXin LI else 818*c77c4889SXin LI rscroll_char = ch; 819*c77c4889SXin LI } 820b2ea2440SXin LI } 821b2ea2440SXin LI break; } 822b2ea2440SXin LI case QUERY: { 823*c77c4889SXin LI p.p_string = rscroll_char ? prchar((LWCHAR) rscroll_char) : "-"; 824d713e089SXin LI error("rscroll character is %s", &p); 825b2ea2440SXin LI break; } 826b2ea2440SXin LI } 827b2ea2440SXin LI } 828b2ea2440SXin LI 829b2ea2440SXin LI /* 830a5f0fb15SPaul Saab * "-?" means display a help message. 831a5f0fb15SPaul Saab * If from the command line, exit immediately. 832a5f0fb15SPaul Saab */ 833a5f0fb15SPaul Saab /*ARGSUSED*/ 834*c77c4889SXin LI public void opt_query(int type, constant char *s) 835a5f0fb15SPaul Saab { 836a5f0fb15SPaul Saab switch (type) 837a5f0fb15SPaul Saab { 838a5f0fb15SPaul Saab case QUERY: 839a5f0fb15SPaul Saab case TOGGLE: 840a5f0fb15SPaul Saab error("Use \"h\" for help", NULL_PARG); 841a5f0fb15SPaul Saab break; 842a5f0fb15SPaul Saab case INIT: 843a5f0fb15SPaul Saab dohelp = 1; 844a5f0fb15SPaul Saab } 845a5f0fb15SPaul Saab } 846a5f0fb15SPaul Saab 847*c77c4889SXin LI /*ARGSUSED*/ 848*c77c4889SXin LI public void opt_match_shift(int type, constant char *s) 849*c77c4889SXin LI { 850*c77c4889SXin LI switch (type) 851*c77c4889SXin LI { 852*c77c4889SXin LI case INIT: 853*c77c4889SXin LI case TOGGLE: 854*c77c4889SXin LI toggle_fraction(&match_shift, &match_shift_fraction, 855*c77c4889SXin LI s, "--match-shift", calc_match_shift); 856*c77c4889SXin LI break; 857*c77c4889SXin LI case QUERY: 858*c77c4889SXin LI query_fraction(match_shift, match_shift_fraction, 859*c77c4889SXin LI "Search match shift is %d", "Search match shift is %s of screen width"); 860*c77c4889SXin LI break; 861*c77c4889SXin LI } 862*c77c4889SXin LI } 863*c77c4889SXin LI 864*c77c4889SXin LI public void calc_match_shift(void) 865*c77c4889SXin LI { 866*c77c4889SXin LI if (match_shift_fraction < 0) 867*c77c4889SXin LI return; 868*c77c4889SXin LI match_shift = (int) muldiv(sc_width, match_shift_fraction, NUM_FRAC_DENOM); 869*c77c4889SXin LI } 870*c77c4889SXin LI 871a5f0fb15SPaul Saab /* 872b7780dbeSXin LI * Handler for the --mouse option. 873b7780dbeSXin LI */ 874b7780dbeSXin LI /*ARGSUSED*/ 875*c77c4889SXin LI public void opt_mousecap(int type, constant char *s) 876b7780dbeSXin LI { 877b7780dbeSXin LI switch (type) 878b7780dbeSXin LI { 879b7780dbeSXin LI case TOGGLE: 880b7780dbeSXin LI if (mousecap == OPT_OFF) 881b7780dbeSXin LI deinit_mouse(); 882b7780dbeSXin LI else 883b7780dbeSXin LI init_mouse(); 884b7780dbeSXin LI break; 885b7780dbeSXin LI case INIT: 886b7780dbeSXin LI case QUERY: 887b7780dbeSXin LI break; 888b7780dbeSXin LI } 889b7780dbeSXin LI } 890b7780dbeSXin LI 891b7780dbeSXin LI /* 892b7780dbeSXin LI * Handler for the --wheel-lines option. 893b7780dbeSXin LI */ 894b7780dbeSXin LI /*ARGSUSED*/ 895*c77c4889SXin LI public void opt_wheel_lines(int type, constant char *s) 896b7780dbeSXin LI { 897b7780dbeSXin LI switch (type) 898b7780dbeSXin LI { 899b7780dbeSXin LI case INIT: 900b7780dbeSXin LI case TOGGLE: 901b7780dbeSXin LI if (wheel_lines <= 0) 902b7780dbeSXin LI wheel_lines = default_wheel_lines(); 903b7780dbeSXin LI break; 904b7780dbeSXin LI case QUERY: 905b7780dbeSXin LI break; 906b7780dbeSXin LI } 907b7780dbeSXin LI } 908b7780dbeSXin LI 909b7780dbeSXin LI /* 9102235c7feSXin LI * Handler for the --line-number-width option. 9112235c7feSXin LI */ 9122235c7feSXin LI /*ARGSUSED*/ 913*c77c4889SXin LI public void opt_linenum_width(int type, constant char *s) 9142235c7feSXin LI { 9152235c7feSXin LI PARG parg; 9162235c7feSXin LI 9172235c7feSXin LI switch (type) 9182235c7feSXin LI { 9192235c7feSXin LI case INIT: 9202235c7feSXin LI case TOGGLE: 9212235c7feSXin LI if (linenum_width > MAX_LINENUM_WIDTH) 9222235c7feSXin LI { 9232235c7feSXin LI parg.p_int = MAX_LINENUM_WIDTH; 9242235c7feSXin LI error("Line number width must not be larger than %d", &parg); 9252235c7feSXin LI linenum_width = MIN_LINENUM_WIDTH; 9262235c7feSXin LI } 9272235c7feSXin LI break; 9282235c7feSXin LI case QUERY: 9292235c7feSXin LI break; 9302235c7feSXin LI } 9312235c7feSXin LI } 9322235c7feSXin LI 9332235c7feSXin LI /* 9342235c7feSXin LI * Handler for the --status-column-width option. 9352235c7feSXin LI */ 9362235c7feSXin LI /*ARGSUSED*/ 937*c77c4889SXin LI public void opt_status_col_width(int type, constant char *s) 9382235c7feSXin LI { 9392235c7feSXin LI PARG parg; 9402235c7feSXin LI 9412235c7feSXin LI switch (type) 9422235c7feSXin LI { 9432235c7feSXin LI case INIT: 9442235c7feSXin LI case TOGGLE: 9452235c7feSXin LI if (status_col_width > MAX_STATUSCOL_WIDTH) 9462235c7feSXin LI { 9472235c7feSXin LI parg.p_int = MAX_STATUSCOL_WIDTH; 9482235c7feSXin LI error("Status column width must not be larger than %d", &parg); 9492235c7feSXin LI status_col_width = 2; 9502235c7feSXin LI } 9512235c7feSXin LI break; 9522235c7feSXin LI case QUERY: 9532235c7feSXin LI break; 9542235c7feSXin LI } 9552235c7feSXin LI } 9562235c7feSXin LI 95730a1828cSXin LI /* 95830a1828cSXin LI * Handler for the --file-size option. 95930a1828cSXin LI */ 96030a1828cSXin LI /*ARGSUSED*/ 961*c77c4889SXin LI public void opt_filesize(int type, constant char *s) 96230a1828cSXin LI { 96330a1828cSXin LI switch (type) 96430a1828cSXin LI { 96530a1828cSXin LI case INIT: 96630a1828cSXin LI case TOGGLE: 96730a1828cSXin LI if (want_filesize && curr_ifile != NULL && ch_length() == NULL_POSITION) 96830a1828cSXin LI scan_eof(); 96930a1828cSXin LI break; 97030a1828cSXin LI case QUERY: 97130a1828cSXin LI break; 97230a1828cSXin LI } 97330a1828cSXin LI } 97430a1828cSXin LI 97595270f73SXin LI /* 976d713e089SXin LI * Handler for the --intr option. 977d713e089SXin LI */ 978d713e089SXin LI /*ARGSUSED*/ 979*c77c4889SXin LI public void opt_intr(int type, constant char *s) 980d713e089SXin LI { 981d713e089SXin LI PARG p; 982d713e089SXin LI 983d713e089SXin LI switch (type) 984d713e089SXin LI { 985d713e089SXin LI case INIT: 986d713e089SXin LI case TOGGLE: 987d713e089SXin LI intr_char = *s; 988d713e089SXin LI if (intr_char == '^' && s[1] != '\0') 989d713e089SXin LI intr_char = CONTROL(s[1]); 990d713e089SXin LI break; 991d713e089SXin LI case QUERY: { 992*c77c4889SXin LI p.p_string = prchar((LWCHAR) intr_char); 993d713e089SXin LI error("interrupt character is %s", &p); 994d713e089SXin LI break; } 995d713e089SXin LI } 996d713e089SXin LI } 997d713e089SXin LI 998d713e089SXin LI /* 999*c77c4889SXin LI * Return the next number from a comma-separated list. 1000*c77c4889SXin LI * Return -1 if the list entry is missing or empty. 1001*c77c4889SXin LI * Updates *sp to point to the first char of the next number in the list. 1002*c77c4889SXin LI */ 1003*c77c4889SXin LI public int next_cnum(constant char **sp, constant char *printopt, constant char *errmsg, lbool *errp) 1004*c77c4889SXin LI { 1005*c77c4889SXin LI int n; 1006*c77c4889SXin LI *errp = FALSE; 1007*c77c4889SXin LI if (**sp == '\0') /* at end of line */ 1008*c77c4889SXin LI return -1; 1009*c77c4889SXin LI if (**sp == ',') /* that's the next comma; we have an empty string */ 1010*c77c4889SXin LI { 1011*c77c4889SXin LI ++(*sp); 1012*c77c4889SXin LI return -1; 1013*c77c4889SXin LI } 1014*c77c4889SXin LI n = getnumc(sp, printopt, errp); 1015*c77c4889SXin LI if (*errp) 1016*c77c4889SXin LI { 1017*c77c4889SXin LI PARG parg; 1018*c77c4889SXin LI parg.p_string = errmsg; 1019*c77c4889SXin LI error("invalid %s", &parg); 1020*c77c4889SXin LI return -1; 1021*c77c4889SXin LI } 1022*c77c4889SXin LI if (**sp == ',') 1023*c77c4889SXin LI ++(*sp); 1024*c77c4889SXin LI return n; 1025*c77c4889SXin LI } 1026*c77c4889SXin LI 1027*c77c4889SXin LI /* 1028*c77c4889SXin LI * Parse a parameter to the --header option. 1029*c77c4889SXin LI * Value is "L,C,N", where each field is a decimal number or empty. 1030*c77c4889SXin LI */ 1031*c77c4889SXin LI static lbool parse_header(constant char *s, int *lines, int *cols, POSITION *start_pos) 1032*c77c4889SXin LI { 1033*c77c4889SXin LI int n; 1034*c77c4889SXin LI lbool err; 1035*c77c4889SXin LI 1036*c77c4889SXin LI if (*s == '-') 1037*c77c4889SXin LI s = "0,0"; 1038*c77c4889SXin LI 1039*c77c4889SXin LI n = next_cnum(&s, "header", "number of lines", &err); 1040*c77c4889SXin LI if (err) return FALSE; 1041*c77c4889SXin LI if (n >= 0) *lines = n; 1042*c77c4889SXin LI 1043*c77c4889SXin LI n = next_cnum(&s, "header", "number of columns", &err); 1044*c77c4889SXin LI if (err) return FALSE; 1045*c77c4889SXin LI if (n >= 0) *cols = n; 1046*c77c4889SXin LI 1047*c77c4889SXin LI n = next_cnum(&s, "header", "line number", &err); 1048*c77c4889SXin LI if (err) return FALSE; 1049*c77c4889SXin LI if (n > 0) 1050*c77c4889SXin LI { 1051*c77c4889SXin LI LINENUM lnum = (LINENUM) n; 1052*c77c4889SXin LI if (lnum < 1) lnum = 1; 1053*c77c4889SXin LI *start_pos = find_pos(lnum); 1054*c77c4889SXin LI } 1055*c77c4889SXin LI return TRUE; 1056*c77c4889SXin LI } 1057*c77c4889SXin LI 1058*c77c4889SXin LI /* 105995270f73SXin LI * Handler for the --header option. 106095270f73SXin LI */ 106195270f73SXin LI /*ARGSUSED*/ 1062*c77c4889SXin LI public void opt_header(int type, constant char *s) 106395270f73SXin LI { 106495270f73SXin LI switch (type) 106595270f73SXin LI { 106695270f73SXin LI case INIT: 1067*c77c4889SXin LI /* Can't call parse_header now because input file is not yet opened, 1068*c77c4889SXin LI * so find_pos won't work. */ 1069*c77c4889SXin LI init_header = save(s); 107095270f73SXin LI break; 1071*c77c4889SXin LI case TOGGLE: { 1072*c77c4889SXin LI int lines = header_lines; 1073*c77c4889SXin LI int cols = header_cols; 1074*c77c4889SXin LI POSITION start_pos = (type == INIT) ? ch_zero() : position(TOP); 1075*c77c4889SXin LI if (start_pos == NULL_POSITION) start_pos = ch_zero(); 1076*c77c4889SXin LI if (!parse_header(s, &lines, &cols, &start_pos)) 1077*c77c4889SXin LI break; 1078*c77c4889SXin LI header_lines = lines; 1079*c77c4889SXin LI header_cols = cols; 1080*c77c4889SXin LI set_header(start_pos); 1081*c77c4889SXin LI calc_jump_sline(); 1082*c77c4889SXin LI break; } 1083*c77c4889SXin LI case QUERY: { 1084*c77c4889SXin LI char buf[3*INT_STRLEN_BOUND(long)+3]; 108595270f73SXin LI PARG parg; 1086*c77c4889SXin LI SNPRINTF3(buf, sizeof(buf), "%ld,%ld,%ld", (long) header_lines, (long) header_cols, (long) find_linenum(header_start_pos)); 108795270f73SXin LI parg.p_string = buf; 1088*c77c4889SXin LI error("Header (lines,columns,line-number) is %s", &parg); 1089*c77c4889SXin LI break; } 109095270f73SXin LI } 109195270f73SXin LI } 109295270f73SXin LI 109395270f73SXin LI /* 109495270f73SXin LI * Handler for the --search-options option. 109595270f73SXin LI */ 109695270f73SXin LI /*ARGSUSED*/ 1097*c77c4889SXin LI public void opt_search_type(int type, constant char *s) 109895270f73SXin LI { 109995270f73SXin LI int st; 110095270f73SXin LI PARG parg; 110195270f73SXin LI char buf[16]; 110295270f73SXin LI char *bp; 1103d713e089SXin LI int i; 110495270f73SXin LI 110595270f73SXin LI switch (type) 110695270f73SXin LI { 110795270f73SXin LI case INIT: 110895270f73SXin LI case TOGGLE: 110995270f73SXin LI st = 0; 111095270f73SXin LI for (; *s != '\0'; s++) 111195270f73SXin LI { 111295270f73SXin LI switch (*s) 111395270f73SXin LI { 111495270f73SXin LI case 'E': case 'e': case CONTROL('E'): st |= SRCH_PAST_EOF; break; 111595270f73SXin LI case 'F': case 'f': case CONTROL('F'): st |= SRCH_FIRST_FILE; break; 111695270f73SXin LI case 'K': case 'k': case CONTROL('K'): st |= SRCH_NO_MOVE; break; 111795270f73SXin LI case 'N': case 'n': case CONTROL('N'): st |= SRCH_NO_MATCH; break; 111895270f73SXin LI case 'R': case 'r': case CONTROL('R'): st |= SRCH_NO_REGEX; break; 111995270f73SXin LI case 'W': case 'w': case CONTROL('W'): st |= SRCH_WRAP; break; 112095270f73SXin LI case '-': st = 0; break; 112195270f73SXin LI case '^': break; 112295270f73SXin LI default: 1123d713e089SXin LI if (*s >= '1' && *s <= '0'+NUM_SEARCH_COLORS) 1124d713e089SXin LI { 1125d713e089SXin LI st |= SRCH_SUBSEARCH(*s-'0'); 1126d713e089SXin LI break; 1127d713e089SXin LI } 112895270f73SXin LI parg.p_char = *s; 112995270f73SXin LI error("invalid search option '%c'", &parg); 113095270f73SXin LI return; 113195270f73SXin LI } 113295270f73SXin LI } 113395270f73SXin LI def_search_type = norm_search_type(st); 113495270f73SXin LI break; 113595270f73SXin LI case QUERY: 113695270f73SXin LI bp = buf; 113795270f73SXin LI if (def_search_type & SRCH_PAST_EOF) *bp++ = 'E'; 113895270f73SXin LI if (def_search_type & SRCH_FIRST_FILE) *bp++ = 'F'; 113995270f73SXin LI if (def_search_type & SRCH_NO_MOVE) *bp++ = 'K'; 114095270f73SXin LI if (def_search_type & SRCH_NO_MATCH) *bp++ = 'N'; 114195270f73SXin LI if (def_search_type & SRCH_NO_REGEX) *bp++ = 'R'; 114295270f73SXin LI if (def_search_type & SRCH_WRAP) *bp++ = 'W'; 1143d713e089SXin LI for (i = 1; i <= NUM_SEARCH_COLORS; i++) 1144d713e089SXin LI if (def_search_type & SRCH_SUBSEARCH(i)) 1145*c77c4889SXin LI *bp++ = (char) ('0'+i); 114695270f73SXin LI if (bp == buf) 114795270f73SXin LI *bp++ = '-'; 114895270f73SXin LI *bp = '\0'; 114995270f73SXin LI parg.p_string = buf; 115095270f73SXin LI error("search options: %s", &parg); 115195270f73SXin LI break; 115295270f73SXin LI } 115395270f73SXin LI } 115495270f73SXin LI 1155*c77c4889SXin LI /* 1156*c77c4889SXin LI * Handler for the --no-search-headers, --no-search-header-lines 1157*c77c4889SXin LI * and --no-search-header-cols options. 1158*c77c4889SXin LI */ 1159*c77c4889SXin LI static void do_nosearch_headers(int type, int no_header_lines, int no_header_cols) 1160*c77c4889SXin LI { 1161*c77c4889SXin LI switch (type) 1162*c77c4889SXin LI { 1163*c77c4889SXin LI case INIT: 1164*c77c4889SXin LI case TOGGLE: 1165*c77c4889SXin LI nosearch_header_lines = no_header_lines; 1166*c77c4889SXin LI nosearch_header_cols = no_header_cols; 1167*c77c4889SXin LI break; 1168*c77c4889SXin LI case QUERY: 1169*c77c4889SXin LI if (nosearch_header_lines && nosearch_header_cols) 1170*c77c4889SXin LI error("Search does not include header lines or columns", NULL_PARG); 1171*c77c4889SXin LI else if (nosearch_header_lines) 1172*c77c4889SXin LI error("Search includes header columns but not header lines", NULL_PARG); 1173*c77c4889SXin LI else if (nosearch_header_cols) 1174*c77c4889SXin LI error("Search includes header lines but not header columns", NULL_PARG); 1175*c77c4889SXin LI else 1176*c77c4889SXin LI error("Search includes header lines and columns", NULL_PARG); 1177*c77c4889SXin LI } 1178*c77c4889SXin LI } 1179*c77c4889SXin LI 1180*c77c4889SXin LI /*ARGSUSED*/ 1181*c77c4889SXin LI public void opt_nosearch_headers(int type, constant char *s) 1182*c77c4889SXin LI { 1183*c77c4889SXin LI do_nosearch_headers(type, 1, 1); 1184*c77c4889SXin LI } 1185*c77c4889SXin LI 1186*c77c4889SXin LI /*ARGSUSED*/ 1187*c77c4889SXin LI public void opt_nosearch_header_lines(int type, constant char *s) 1188*c77c4889SXin LI { 1189*c77c4889SXin LI do_nosearch_headers(type, 1, 0); 1190*c77c4889SXin LI } 1191*c77c4889SXin LI 1192*c77c4889SXin LI /*ARGSUSED*/ 1193*c77c4889SXin LI public void opt_nosearch_header_cols(int type, constant char *s) 1194*c77c4889SXin LI { 1195*c77c4889SXin LI do_nosearch_headers(type, 0, 1); 1196*c77c4889SXin LI } 1197*c77c4889SXin LI 11982235c7feSXin LI #if LESSTEST 11992235c7feSXin LI /* 12002235c7feSXin LI * Handler for the --tty option. 12012235c7feSXin LI */ 12022235c7feSXin LI /*ARGSUSED*/ 1203*c77c4889SXin LI public void opt_ttyin_name(int type, constant char *s) 12042235c7feSXin LI { 12052235c7feSXin LI switch (type) 12062235c7feSXin LI { 12072235c7feSXin LI case INIT: 12082235c7feSXin LI ttyin_name = s; 12092235c7feSXin LI is_tty = 1; 12102235c7feSXin LI break; 12112235c7feSXin LI } 12122235c7feSXin LI } 12132235c7feSXin LI #endif /*LESSTEST*/ 12142235c7feSXin LI 1215d713e089SXin LI public int chop_line(void) 121695270f73SXin LI { 121795270f73SXin LI return (chopline || header_cols > 0 || header_lines > 0); 121895270f73SXin LI } 121995270f73SXin LI 12202235c7feSXin LI /* 1221a5f0fb15SPaul Saab * Get the "screen window" size. 1222a5f0fb15SPaul Saab */ 1223d713e089SXin LI public int get_swindow(void) 1224a5f0fb15SPaul Saab { 1225a5f0fb15SPaul Saab if (swindow > 0) 1226a5f0fb15SPaul Saab return (swindow); 122795270f73SXin LI return (sc_height - header_lines + swindow); 1228a5f0fb15SPaul Saab } 1229a5f0fb15SPaul Saab 1230