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 * Handling functions for command line options. 14 * 15 * Most options are handled by the generic code in option.c. 16 * But all string options, and a few non-string options, require 17 * special handling specific to the particular option. 18 * This special processing is done by the "handling functions" in this file. 19 * 20 * Each handling function is passed a "type" and, if it is a string 21 * option, the string which should be "assigned" to the option. 22 * The type may be one of: 23 * INIT The option is being initialized from the command line. 24 * TOGGLE The option is being changed from within the program. 25 * QUERY The setting of the option is merely being queried. 26 */ 27 28 #include "less.h" 29 #include "option.h" 30 31 extern int nbufs; 32 extern int cbufs; 33 extern int pr_type; 34 extern int plusoption; 35 extern int swindow; 36 extern int sc_height; 37 extern int secure; 38 extern int dohelp; 39 extern int any_display; 40 extern char openquote; 41 extern char closequote; 42 extern char *prproto[]; 43 extern char *eqproto; 44 extern char *hproto; 45 extern IFILE curr_ifile; 46 extern char version[]; 47 #if LOGFILE 48 extern char *namelogfile; 49 extern int force_logfile; 50 extern int logfile; 51 #endif 52 #if TAGS 53 public char *tagoption = NULL; 54 extern char *tags; 55 extern int jump_sline; 56 #endif 57 #if MSDOS_COMPILER 58 extern int nm_fg_color, nm_bg_color; 59 extern int bo_fg_color, bo_bg_color; 60 extern int ul_fg_color, ul_bg_color; 61 extern int so_fg_color, so_bg_color; 62 extern int bl_fg_color, bl_bg_color; 63 #endif 64 65 66 #if LOGFILE 67 /* 68 * Handler for -o option. 69 */ 70 public void 71 opt_o(type, s) 72 int type; 73 char *s; 74 { 75 PARG parg; 76 77 if (secure) 78 { 79 error("log file support is not available", NULL_PARG); 80 return; 81 } 82 switch (type) 83 { 84 case INIT: 85 namelogfile = s; 86 break; 87 case TOGGLE: 88 if (ch_getflags() & CH_CANSEEK) 89 { 90 error("Input is not a pipe", NULL_PARG); 91 return; 92 } 93 if (logfile >= 0) 94 { 95 error("Log file is already in use", NULL_PARG); 96 return; 97 } 98 s = skipsp(s); 99 namelogfile = lglob(s); 100 use_logfile(namelogfile); 101 sync_logfile(); 102 break; 103 case QUERY: 104 if (logfile < 0) 105 error("No log file", NULL_PARG); 106 else 107 { 108 parg.p_string = unquote_file(namelogfile); 109 error("Log file \"%s\"", &parg); 110 free(parg.p_string); 111 } 112 break; 113 } 114 } 115 116 /* 117 * Handler for -O option. 118 */ 119 public void 120 opt__O(type, s) 121 int type; 122 char *s; 123 { 124 force_logfile = TRUE; 125 opt_o(type, s); 126 } 127 #endif 128 129 /* 130 * Handlers for -l option. 131 */ 132 public void 133 opt_l(type, s) 134 int type; 135 char *s; 136 { 137 int err; 138 int n; 139 char *t; 140 141 switch (type) 142 { 143 case INIT: 144 t = s; 145 n = getnum(&t, 'l', &err); 146 if (err || n <= 0) 147 { 148 error("Line number is required after -l", NULL_PARG); 149 return; 150 } 151 plusoption = TRUE; 152 ungetsc(s); 153 break; 154 } 155 } 156 157 #if USERFILE 158 public void 159 opt_k(type, s) 160 int type; 161 char *s; 162 { 163 PARG parg; 164 165 switch (type) 166 { 167 case INIT: 168 if (lesskey(s, 0)) 169 { 170 parg.p_string = unquote_file(s); 171 error("Cannot use lesskey file \"%s\"", &parg); 172 free(parg.p_string); 173 } 174 break; 175 } 176 } 177 #endif 178 179 #if TAGS 180 /* 181 * Handler for -t option. 182 */ 183 public void 184 opt_t(type, s) 185 int type; 186 char *s; 187 { 188 IFILE save_ifile; 189 POSITION pos; 190 191 switch (type) 192 { 193 case INIT: 194 tagoption = s; 195 /* Do the rest in main() */ 196 break; 197 case TOGGLE: 198 if (secure) 199 { 200 error("tags support is not available", NULL_PARG); 201 break; 202 } 203 findtag(skipsp(s)); 204 save_ifile = save_curr_ifile(); 205 if (edit_tagfile()) 206 break; 207 if ((pos = tagsearch()) == NULL_POSITION) 208 { 209 reedit_ifile(save_ifile); 210 break; 211 } 212 unsave_ifile(save_ifile); 213 jump_loc(pos, jump_sline); 214 break; 215 } 216 } 217 218 /* 219 * Handler for -T option. 220 */ 221 public void 222 opt__T(type, s) 223 int type; 224 char *s; 225 { 226 PARG parg; 227 228 switch (type) 229 { 230 case INIT: 231 tags = s; 232 break; 233 case TOGGLE: 234 s = skipsp(s); 235 tags = lglob(s); 236 break; 237 case QUERY: 238 parg.p_string = unquote_file(tags); 239 error("Tags file \"%s\"", &parg); 240 free(parg.p_string); 241 break; 242 } 243 } 244 #endif 245 246 /* 247 * Handler for -p option. 248 */ 249 public void 250 opt_p(type, s) 251 int type; 252 register char *s; 253 { 254 switch (type) 255 { 256 case INIT: 257 /* 258 * Unget a search command for the specified string. 259 * {{ This won't work if the "/" command is 260 * changed or invalidated by a .lesskey file. }} 261 */ 262 plusoption = TRUE; 263 ungetsc(s); 264 ungetsc("/"); 265 break; 266 } 267 } 268 269 /* 270 * Handler for -P option. 271 */ 272 public void 273 opt__P(type, s) 274 int type; 275 register char *s; 276 { 277 register char **proto; 278 PARG parg; 279 280 switch (type) 281 { 282 case INIT: 283 case TOGGLE: 284 /* 285 * Figure out which prototype string should be changed. 286 */ 287 switch (*s) 288 { 289 case 's': proto = &prproto[PR_SHORT]; s++; break; 290 case 'm': proto = &prproto[PR_MEDIUM]; s++; break; 291 case 'M': proto = &prproto[PR_LONG]; s++; break; 292 case '=': proto = &eqproto; s++; break; 293 case 'h': proto = &hproto; s++; break; 294 default: proto = &prproto[PR_SHORT]; break; 295 } 296 free(*proto); 297 *proto = save(s); 298 break; 299 case QUERY: 300 parg.p_string = prproto[pr_type]; 301 error("%s", &parg); 302 break; 303 } 304 } 305 306 /* 307 * Handler for the -b option. 308 */ 309 /*ARGSUSED*/ 310 public void 311 opt_b(type, s) 312 int type; 313 char *s; 314 { 315 switch (type) 316 { 317 case TOGGLE: 318 case QUERY: 319 /* 320 * Allocate the new number of buffers. 321 */ 322 cbufs = ch_nbuf(cbufs); 323 break; 324 case INIT: 325 break; 326 } 327 } 328 329 /* 330 * Handler for the -i option. 331 */ 332 /*ARGSUSED*/ 333 public void 334 opt_i(type, s) 335 int type; 336 char *s; 337 { 338 switch (type) 339 { 340 case TOGGLE: 341 chg_caseless(); 342 break; 343 case QUERY: 344 case INIT: 345 break; 346 } 347 } 348 349 /* 350 * Handler for the -V option. 351 */ 352 /*ARGSUSED*/ 353 public void 354 opt__V(type, s) 355 int type; 356 char *s; 357 { 358 switch (type) 359 { 360 case TOGGLE: 361 case QUERY: 362 dispversion(); 363 break; 364 case INIT: 365 /* 366 * Force output to stdout per GNU standard for --version output. 367 */ 368 any_display = 1; 369 putstr("less "); 370 putstr(version); 371 putstr("\nCopyright (C) 2000 Mark Nudelman\n\n"); 372 putstr("less comes with NO WARRANTY, to the extent permitted by law.\n"); 373 putstr("For information about the terms of redistribution,\n"); 374 putstr("see the file named README in the less distribution.\n"); 375 quit(QUIT_OK); 376 break; 377 } 378 } 379 380 #if MSDOS_COMPILER 381 /* 382 * Parse an MSDOS color descriptor. 383 */ 384 static void 385 colordesc(s, fg_color, bg_color) 386 char *s; 387 int *fg_color; 388 int *bg_color; 389 { 390 int fg, bg; 391 int err; 392 393 fg = getnum(&s, 'D', &err); 394 if (err) 395 { 396 error("Missing fg color in -D", NULL_PARG); 397 return; 398 } 399 if (*s != '.') 400 bg = 0; 401 else 402 { 403 s++; 404 bg = getnum(&s, 'D', &err); 405 if (err) 406 { 407 error("Missing fg color in -D", NULL_PARG); 408 return; 409 } 410 } 411 if (*s != '\0') 412 error("Extra characters at end of -D option", NULL_PARG); 413 *fg_color = fg; 414 *bg_color = bg; 415 } 416 417 /* 418 * Handler for the -D option. 419 */ 420 /*ARGSUSED*/ 421 public void 422 opt_D(type, s) 423 int type; 424 char *s; 425 { 426 switch (type) 427 { 428 case INIT: 429 case TOGGLE: 430 switch (*s++) 431 { 432 case 'n': 433 colordesc(s, &nm_fg_color, &nm_bg_color); 434 break; 435 case 'd': 436 colordesc(s, &bo_fg_color, &bo_bg_color); 437 break; 438 case 'u': 439 colordesc(s, &ul_fg_color, &ul_bg_color); 440 break; 441 case 'k': 442 colordesc(s, &bl_fg_color, &bl_bg_color); 443 break; 444 case 's': 445 colordesc(s, &so_fg_color, &so_bg_color); 446 break; 447 default: 448 error("-D must be followed by n, d, u, k or s", NULL_PARG); 449 break; 450 } 451 if (type == TOGGLE) 452 { 453 so_enter(); 454 so_exit(); 455 } 456 break; 457 case QUERY: 458 break; 459 } 460 } 461 #endif 462 463 /* 464 * Handler for the -" option. 465 */ 466 public void 467 opt_quote(type, s) 468 int type; 469 register char *s; 470 { 471 char buf[3]; 472 PARG parg; 473 474 switch (type) 475 { 476 case INIT: 477 case TOGGLE: 478 if (s[1] != '\0' && s[2] != '\0') 479 { 480 error("-\" must be followed by 1 or 2 chars", NULL_PARG); 481 return; 482 } 483 openquote = s[0]; 484 if (s[1] == '\0') 485 closequote = openquote; 486 else 487 closequote = s[1]; 488 break; 489 case QUERY: 490 buf[0] = openquote; 491 buf[1] = closequote; 492 buf[2] = '\0'; 493 parg.p_string = buf; 494 error("quotes %s", &parg); 495 break; 496 } 497 } 498 499 /* 500 * "-?" means display a help message. 501 * If from the command line, exit immediately. 502 */ 503 /*ARGSUSED*/ 504 public void 505 opt_query(type, s) 506 int type; 507 char *s; 508 { 509 switch (type) 510 { 511 case QUERY: 512 case TOGGLE: 513 error("Use \"h\" for help", NULL_PARG); 514 break; 515 case INIT: 516 dohelp = 1; 517 } 518 } 519 520 /* 521 * Get the "screen window" size. 522 */ 523 public int 524 get_swindow() 525 { 526 if (swindow > 0) 527 return (swindow); 528 return (sc_height + swindow); 529 } 530 531