1 /* 2 * Copyright (C) 1984-2000 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 about less, or for information on how to 8 * contact the author, see the README file. 9 */ 10 11 12 /* 13 * The option table. 14 */ 15 16 #include "less.h" 17 #include "option.h" 18 19 /* 20 * Variables controlled by command line options. 21 */ 22 public int quiet; /* Should we suppress the audible bell? */ 23 public int how_search; /* Where should forward searches start? */ 24 public int top_scroll; /* Repaint screen from top? 25 (alternative is scroll from bottom) */ 26 public int pr_type; /* Type of prompt (short, medium, long) */ 27 public int bs_mode; /* How to process backspaces */ 28 public int know_dumb; /* Don't complain about dumb terminals */ 29 public int quit_at_eof; /* Quit after hitting end of file twice */ 30 public int quit_if_one_screen; /* Quit if EOF on first screen */ 31 public int squeeze; /* Squeeze multiple blank lines into one */ 32 public int tabstop; /* Tab settings */ 33 public int back_scroll; /* Repaint screen on backwards movement */ 34 public int forw_scroll; /* Repaint screen on forward movement */ 35 public int caseless; /* Do "caseless" searches */ 36 public int linenums; /* Use line numbers */ 37 public int cbufs; /* Current number of buffers */ 38 public int autobuf; /* Automatically allocate buffers as needed */ 39 public int ctldisp; /* Send control chars to screen untranslated */ 40 public int force_open; /* Open the file even if not regular file */ 41 public int swindow; /* Size of scrolling window */ 42 public int jump_sline; /* Screen line of "jump target" */ 43 public int chopline; /* Truncate displayed lines at screen width */ 44 public int no_init; /* Disable sending ti/te termcap strings */ 45 public int no_keypad; /* Disable sending ks/ke termcap strings */ 46 public int twiddle; /* Show tildes after EOF */ 47 public int show_attn; /* Hilite first unread line */ 48 public int shift_count; /* Number of positions to shift horizontally */ 49 public int status_col; /* Display a status column */ 50 #if HILITE_SEARCH 51 public int hilite_search; /* Highlight matched search patterns? */ 52 #endif 53 54 /* 55 * Long option names. 56 */ 57 static struct optname a_optname = { "search-skip-screen", NULL }; 58 static struct optname b_optname = { "buffers", NULL }; 59 static struct optname B__optname = { "auto-buffers", NULL }; 60 static struct optname c_optname = { "clear-screen", NULL }; 61 static struct optname d_optname = { "dumb", NULL }; 62 #if MSDOS_COMPILER 63 static struct optname D__optname = { "color", NULL }; 64 #endif 65 static struct optname e_optname = { "quit-at-eof", NULL }; 66 static struct optname f_optname = { "force", NULL }; 67 static struct optname F__optname = { "quit-if-one-screen", NULL }; 68 #if HILITE_SEARCH 69 static struct optname g_optname = { "hilite-search", NULL }; 70 #endif 71 static struct optname h_optname = { "max-back-scroll", NULL }; 72 static struct optname i_optname = { "ignore-case", NULL }; 73 static struct optname j_optname = { "jump-target", NULL }; 74 static struct optname J__optname = { "status-column", NULL }; 75 #if USERFILE 76 static struct optname k_optname = { "lesskey-file", NULL }; 77 #endif 78 static struct optname m_optname = { "long-prompt", NULL }; 79 static struct optname n_optname = { "line-numbers", NULL }; 80 #if LOGFILE 81 static struct optname o_optname = { "log-file", NULL }; 82 static struct optname O__optname = { "LOG-FILE", NULL }; 83 #endif 84 static struct optname p_optname = { "pattern", NULL }; 85 static struct optname P__optname = { "prompt", NULL }; 86 static struct optname q2_optname = { "silent", NULL }; 87 static struct optname q_optname = { "quiet", &q2_optname }; 88 static struct optname r_optname = { "raw-control-chars", NULL }; 89 static struct optname s_optname = { "squeeze-blank-lines", NULL }; 90 static struct optname S__optname = { "chop-long-lines", NULL }; 91 #if TAGS 92 static struct optname t_optname = { "tag", NULL }; 93 static struct optname T__optname = { "tag-file", NULL }; 94 #endif 95 static struct optname u_optname = { "underline-special", NULL }; 96 static struct optname V__optname = { "version", NULL }; 97 static struct optname w_optname = { "hilite-unread", NULL }; 98 static struct optname x_optname = { "tabs", NULL }; 99 static struct optname X__optname = { "no-init", NULL }; 100 static struct optname y_optname = { "max-forw-scroll", NULL }; 101 static struct optname z_optname = { "window", NULL }; 102 static struct optname quote_optname = { "quotes", NULL }; 103 static struct optname tilde_optname = { "tilde", NULL }; 104 static struct optname query_optname = { "help", NULL }; 105 static struct optname pound_optname = { "shift", NULL }; 106 static struct optname keypad_optname = { "no-keypad", NULL }; 107 108 109 /* 110 * Table of all options and their semantics. 111 * 112 * For BOOL and TRIPLE options, odesc[0], odesc[1], odesc[2] are 113 * the description of the option when set to 0, 1 or 2, respectively. 114 * For NUMBER options, odesc[0] is the prompt to use when entering 115 * a new value, and odesc[1] is the description, which should contain 116 * one %d which is replaced by the value of the number. 117 * For STRING options, odesc[0] is the prompt to use when entering 118 * a new value, and odesc[1], if not NULL, is the set of characters 119 * that are valid in the string. 120 */ 121 static struct option option[] = 122 { 123 { 'a', &a_optname, 124 BOOL, OPT_OFF, &how_search, NULL, 125 "Search includes displayed screen", 126 "Search skips displayed screen", 127 NULL 128 }, 129 130 { 'b', &b_optname, 131 NUMBER, 10, &cbufs, opt_b, 132 "Buffers: ", 133 "%d buffers", 134 NULL 135 }, 136 { 'B', &B__optname, 137 BOOL, OPT_ON, &autobuf, NULL, 138 "Don't automatically allocate buffers", 139 "Automatically allocate buffers when needed", 140 NULL 141 }, 142 { 'c', &c_optname, 143 TRIPLE, OPT_OFF, &top_scroll, NULL, 144 "Repaint by scrolling from bottom of screen", 145 "Repaint by clearing each line", 146 "Repaint by painting from top of screen" 147 }, 148 { 'd', &d_optname, 149 BOOL|NO_TOGGLE, OPT_OFF, &know_dumb, NULL, 150 "Assume intelligent terminal", 151 "Assume dumb terminal", 152 NULL 153 }, 154 #if MSDOS_COMPILER 155 { 'D', &D__optname, 156 STRING|REPAINT|NO_QUERY, 0, NULL, opt_D, 157 "color desc: ", 158 "Ddknsu0123456789.", 159 NULL 160 }, 161 #endif 162 { 'e', &e_optname, 163 TRIPLE, OPT_OFF, &quit_at_eof, NULL, 164 "Don't quit at end-of-file", 165 "Quit at end-of-file", 166 "Quit immediately at end-of-file" 167 }, 168 { 'f', &f_optname, 169 BOOL, OPT_OFF, &force_open, NULL, 170 "Open only regular files", 171 "Open even non-regular files", 172 NULL 173 }, 174 { 'F', &F__optname, 175 BOOL, OPT_OFF, &quit_if_one_screen, NULL, 176 "Don't quit if end-of-file on first screen", 177 "Quit if end-of-file on first screen", 178 NULL 179 }, 180 #if HILITE_SEARCH 181 { 'g', &g_optname, 182 TRIPLE|HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL, 183 "Don't highlight search matches", 184 "Highlight matches for previous search only", 185 "Highlight all matches for previous search pattern", 186 }, 187 #endif 188 { 'h', &h_optname, 189 NUMBER, -1, &back_scroll, NULL, 190 "Backwards scroll limit: ", 191 "Backwards scroll limit is %d lines", 192 NULL 193 }, 194 { 'i', &i_optname, 195 TRIPLE|HL_REPAINT, OPT_OFF, &caseless, opt_i, 196 "Case is significant in searches", 197 "Ignore case in searches", 198 "Ignore case in searches and in patterns" 199 }, 200 { 'j', &j_optname, 201 NUMBER, 1, &jump_sline, NULL, 202 "Target line: ", 203 "Position target at screen line %d", 204 NULL 205 }, 206 { 'J', &J__optname, 207 BOOL|REPAINT, OPT_OFF, &status_col, NULL, 208 "Don't display a status column", 209 "Display a status column", 210 NULL 211 }, 212 #if USERFILE 213 { 'k', &k_optname, 214 STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k, 215 NULL, NULL, NULL 216 }, 217 #endif 218 { 'l', NULL, 219 STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_l, 220 NULL, NULL, NULL 221 }, 222 { 'm', &m_optname, 223 TRIPLE, OPT_OFF, &pr_type, NULL, 224 "Short prompt", 225 "Medium prompt", 226 "Long prompt" 227 }, 228 { 'n', &n_optname, 229 TRIPLE|REPAINT, OPT_ON, &linenums, NULL, 230 "Don't use line numbers", 231 "Use line numbers", 232 "Constantly display line numbers" 233 }, 234 #if LOGFILE 235 { 'o', &o_optname, 236 STRING, 0, NULL, opt_o, 237 "log file: ", NULL, NULL 238 }, 239 { 'O', &O__optname, 240 STRING, 0, NULL, opt__O, 241 "Log file: ", NULL, NULL 242 }, 243 #endif 244 { 'p', &p_optname, 245 STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_p, 246 NULL, NULL, NULL 247 }, 248 { 'P', &P__optname, 249 STRING, 0, NULL, opt__P, 250 "prompt: ", NULL, NULL 251 }, 252 { 'q', &q_optname, 253 TRIPLE, OPT_OFF, &quiet, NULL, 254 "Ring the bell for errors AND at eof/bof", 255 "Ring the bell for errors but not at eof/bof", 256 "Never ring the bell" 257 }, 258 { 'r', &r_optname, 259 TRIPLE|REPAINT, OPT_OFF, &ctldisp, NULL, 260 "Display control characters as ^X", 261 "Display control characters directly", 262 "Display control characters directly, processing ANSI sequences" 263 }, 264 { 's', &s_optname, 265 BOOL|REPAINT, OPT_OFF, &squeeze, NULL, 266 "Display all blank lines", 267 "Squeeze multiple blank lines", 268 NULL 269 }, 270 { 'S', &S__optname, 271 BOOL|REPAINT, OPT_OFF, &chopline, NULL, 272 "Fold long lines", 273 "Chop long lines", 274 NULL 275 }, 276 #if TAGS 277 { 't', &t_optname, 278 STRING|NO_QUERY, 0, NULL, opt_t, 279 "tag: ", NULL, NULL 280 }, 281 { 'T', &T__optname, 282 STRING, 0, NULL, opt__T, 283 "tags file: ", NULL, NULL 284 }, 285 #endif 286 { 'u', &u_optname, 287 TRIPLE|REPAINT, OPT_OFF, &bs_mode, NULL, 288 "Display underlined text in underline mode", 289 "Backspaces cause overstrike", 290 "Print backspace as ^H" 291 }, 292 { 'V', &V__optname, 293 NOVAR, 0, NULL, opt__V, 294 NULL, NULL, NULL 295 }, 296 { 'w', &w_optname, 297 TRIPLE|REPAINT, OPT_OFF, &show_attn, NULL, 298 "Don't highlight first unread line", 299 "Highlight first unread line after forward-screen", 300 "Highlight first unread line after any forward movement", 301 }, 302 { 'x', &x_optname, 303 STRING|REPAINT, 0, NULL, opt_x, 304 "Tab stops: ", 305 "0123456789,", 306 NULL 307 }, 308 { 'X', &X__optname, 309 BOOL|NO_TOGGLE, OPT_OFF, &no_init, NULL, 310 "Send init/deinit strings to terminal", 311 "Don't use init/deinit strings", 312 NULL 313 }, 314 { 'y', &y_optname, 315 NUMBER, -1, &forw_scroll, NULL, 316 "Forward scroll limit: ", 317 "Forward scroll limit is %d lines", 318 NULL 319 }, 320 { 'z', &z_optname, 321 NUMBER, -1, &swindow, NULL, 322 "Scroll window size: ", 323 "Scroll window size is %d lines", 324 NULL 325 }, 326 { '"', "e_optname, 327 STRING, 0, NULL, opt_quote, 328 "quotes: ", NULL, NULL 329 }, 330 { '~', &tilde_optname, 331 BOOL|REPAINT, OPT_ON, &twiddle, NULL, 332 "Don't show tildes after end of file", 333 "Show tildes after end of file", 334 NULL 335 }, 336 { '?', &query_optname, 337 NOVAR, 0, NULL, opt_query, 338 NULL, NULL, NULL 339 }, 340 { '#', £_optname, 341 NUMBER, 0, &shift_count, NULL, 342 "Horizontal shift: ", 343 "Horizontal shift %d positions", 344 NULL 345 }, 346 { '.', &keypad_optname, 347 BOOL|NO_TOGGLE, OPT_OFF, &no_keypad, NULL, 348 "Use keypad mode", 349 "Don't use keypad mode", 350 NULL 351 }, 352 { '\0', NULL, NOVAR, 0, NULL, NULL, NULL, NULL, NULL } 353 }; 354 355 356 /* 357 * Initialize each option to its default value. 358 */ 359 public void 360 init_option() 361 { 362 register struct option *o; 363 364 for (o = option; o->oletter != '\0'; o++) 365 { 366 /* 367 * Set each variable to its default. 368 */ 369 if (o->ovar != NULL) 370 *(o->ovar) = o->odefault; 371 } 372 } 373 374 /* 375 * Find an option in the option table, given its option letter. 376 */ 377 public struct option * 378 findopt(c) 379 int c; 380 { 381 register struct option *o; 382 383 for (o = option; o->oletter != '\0'; o++) 384 { 385 if (o->oletter == c) 386 return (o); 387 if ((o->otype & TRIPLE) && toupper(o->oletter) == c) 388 return (o); 389 } 390 return (NULL); 391 } 392 393 /* 394 * Find an option in the option table, given its option name. 395 * p_optname is the (possibly partial) name to look for, and 396 * is updated to point after the matched name. 397 * p_oname if non-NULL is set to point to the full option name. 398 */ 399 public struct option * 400 findopt_name(p_optname, p_oname, p_err) 401 char **p_optname; 402 char **p_oname; 403 int *p_err; 404 { 405 char *optname = *p_optname; 406 register struct option *o; 407 register struct optname *oname; 408 register int len; 409 int uppercase; 410 struct option *maxo = NULL; 411 struct optname *maxoname = NULL; 412 int maxlen = 0; 413 int ambig = 0; 414 int exact = 0; 415 416 /* 417 * Check all options. 418 */ 419 for (o = option; o->oletter != '\0'; o++) 420 { 421 /* 422 * Check all names for this option. 423 */ 424 for (oname = o->onames; oname != NULL; oname = oname->onext) 425 { 426 /* 427 * Try normal match first (uppercase == 0), 428 * then, then if it's a TRIPLE option, 429 * try uppercase match (uppercase == 1). 430 */ 431 for (uppercase = 0; uppercase <= 1; uppercase++) 432 { 433 len = sprefix(optname, oname->oname, uppercase); 434 if (!exact && len == maxlen) 435 /* 436 * Already had a partial match, 437 * and now there's another one that 438 * matches the same length. 439 */ 440 ambig = 1; 441 else if (len > maxlen) 442 { 443 /* 444 * Found a better match than 445 * the one we had. 446 */ 447 maxo = o; 448 maxoname = oname; 449 maxlen = len; 450 ambig = 0; 451 exact = (len == (int)strlen(oname->oname)); 452 } 453 if (!(o->otype & TRIPLE)) 454 break; 455 } 456 } 457 } 458 if (ambig) 459 { 460 /* 461 * Name matched more than one option. 462 */ 463 if (p_err != NULL) 464 *p_err = OPT_AMBIG; 465 return (NULL); 466 } 467 *p_optname = optname + maxlen; 468 if (p_oname != NULL) 469 *p_oname = maxoname->oname; 470 return (maxo); 471 } 472