1 /* $OpenBSD: optfunc.c,v 1.2 2001/01/29 01:58:03 niklas Exp $ */ 2 3 /* 4 * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice in the documentation and/or other materials provided with 14 * the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 22 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 30 /* 31 * Handling functions for command line options. 32 * 33 * Most options are handled by the generic code in option.c. 34 * But all string options, and a few non-string options, require 35 * special handling specific to the particular option. 36 * This special processing is done by the "handling functions" in this file. 37 * 38 * Each handling function is passed a "type" and, if it is a string 39 * option, the string which should be "assigned" to the option. 40 * The type may be one of: 41 * INIT The option is being initialized from the command line. 42 * TOGGLE The option is being changed from within the program. 43 * QUERY The setting of the option is merely being queried. 44 */ 45 46 #include "less.h" 47 #include "option.h" 48 49 extern int nbufs; 50 extern int cbufs; 51 extern int pr_type; 52 extern int nohelp; 53 extern int plusoption; 54 extern int swindow; 55 extern int sc_height; 56 extern int any_display; 57 extern char *prproto[]; 58 extern char *eqproto; 59 extern IFILE curr_ifile; 60 #if LOGFILE 61 extern char *namelogfile; 62 extern int force_logfile; 63 extern int logfile; 64 #endif 65 #if TAGS 66 public char *tagoption = NULL; 67 extern char *tagfile; 68 extern char *tags; 69 extern int jump_sline; 70 #endif 71 #if MSOFTC 72 extern int nm_fg_color, nm_bg_color; 73 extern int bo_fg_color, bo_bg_color; 74 extern int ul_fg_color, ul_bg_color; 75 extern int so_fg_color, so_bg_color; 76 extern int bl_fg_color, bl_bg_color; 77 #endif 78 79 80 #if LOGFILE 81 /* 82 * Handler for -o option. 83 */ 84 public void 85 opt_o(type, s) 86 int type; 87 char *s; 88 { 89 PARG parg; 90 91 switch (type) 92 { 93 case INIT: 94 namelogfile = s; 95 break; 96 case TOGGLE: 97 if (ch_getflags() & CH_CANSEEK) 98 { 99 error("Input is not a pipe", NULL_PARG); 100 return; 101 } 102 if (logfile >= 0) 103 { 104 error("Log file is already in use", NULL_PARG); 105 return; 106 } 107 s = skipsp(s); 108 namelogfile = glob(s); 109 use_logfile(namelogfile); 110 sync_logfile(); 111 break; 112 case QUERY: 113 if (logfile < 0) 114 error("No log file", NULL_PARG); 115 else 116 { 117 parg.p_string = namelogfile; 118 error("Log file \"%s\"", &parg); 119 } 120 break; 121 } 122 } 123 124 /* 125 * Handler for -O option. 126 */ 127 public void 128 opt__O(type, s) 129 int type; 130 char *s; 131 { 132 force_logfile = TRUE; 133 opt_o(type, s); 134 } 135 #endif 136 137 /* 138 * Handlers for -l option. 139 */ 140 public void 141 opt_l(type, s) 142 int type; 143 char *s; 144 { 145 int err; 146 int n; 147 char *t; 148 149 switch (type) 150 { 151 case INIT: 152 t = s; 153 n = getnum(&t, 'l', &err); 154 if (err || n <= 0) 155 { 156 error("Line number is required after -l", NULL_PARG); 157 return; 158 } 159 plusoption = TRUE; 160 ungetsc(s); 161 break; 162 } 163 } 164 165 #if USERFILE 166 public void 167 opt_k(type, s) 168 int type; 169 char *s; 170 { 171 PARG parg; 172 173 switch (type) 174 { 175 case INIT: 176 if (lesskey(s)) 177 { 178 parg.p_string = s; 179 error("Cannot use lesskey file \"%s\"", &parg); 180 } 181 break; 182 } 183 } 184 #endif 185 186 #if TAGS 187 /* 188 * Handler for -t option. 189 */ 190 public void 191 opt_t(type, s) 192 int type; 193 char *s; 194 { 195 IFILE save_ifile; 196 POSITION pos; 197 198 switch (type) 199 { 200 case INIT: 201 tagoption = s; 202 /* Do the rest in main() */ 203 break; 204 case TOGGLE: 205 findtag(skipsp(s)); 206 if (tagfile == NULL) 207 break; 208 save_ifile = curr_ifile; 209 if (edit(tagfile)) 210 break; 211 if ((pos = tagsearch()) == NULL_POSITION) 212 { 213 if (edit_ifile(save_ifile)) 214 quit(QUIT_ERROR); 215 break; 216 } 217 jump_loc(pos, jump_sline); 218 break; 219 } 220 } 221 222 /* 223 * Handler for -T option. 224 */ 225 public void 226 opt__T(type, s) 227 int type; 228 char *s; 229 { 230 PARG parg; 231 232 switch (type) 233 { 234 case INIT: 235 tags = s; 236 break; 237 case TOGGLE: 238 s = skipsp(s); 239 tags = glob(s); 240 break; 241 case QUERY: 242 parg.p_string = tags; 243 error("Tags file \"%s\"", &parg); 244 break; 245 } 246 } 247 #endif 248 249 /* 250 * Handler for -p option. 251 */ 252 public void 253 opt_p(type, s) 254 int type; 255 register char *s; 256 { 257 switch (type) 258 { 259 case INIT: 260 /* 261 * Unget a search command for the specified string. 262 * {{ This won't work if the "/" command is 263 * changed or invalidated by a .lesskey file. }} 264 */ 265 plusoption = TRUE; 266 ungetsc(s); 267 ungetsc("/"); 268 break; 269 } 270 } 271 272 /* 273 * Handler for -P option. 274 */ 275 public void 276 opt__P(type, s) 277 int type; 278 register char *s; 279 { 280 register char **proto; 281 PARG parg; 282 283 switch (type) 284 { 285 case INIT: 286 case TOGGLE: 287 /* 288 * Figure out which prototype string should be changed. 289 */ 290 switch (*s) 291 { 292 case 'm': proto = &prproto[PR_MEDIUM]; s++; break; 293 case 'M': proto = &prproto[PR_LONG]; s++; break; 294 case '=': proto = &eqproto; s++; break; 295 default: proto = &prproto[PR_SHORT]; break; 296 } 297 free(*proto); 298 *proto = save(s); 299 break; 300 case QUERY: 301 parg.p_string = prproto[pr_type]; 302 error("%s", &parg); 303 break; 304 } 305 } 306 307 /* 308 * Handler for the -b option. 309 */ 310 /*ARGSUSED*/ 311 public void 312 opt_b(type, s) 313 int type; 314 char *s; 315 { 316 switch (type) 317 { 318 case TOGGLE: 319 case QUERY: 320 /* 321 * Allocate the new number of buffers. 322 */ 323 cbufs = ch_nbuf(cbufs); 324 break; 325 case INIT: 326 break; 327 } 328 } 329 330 /* 331 * Handler for the -i option. 332 */ 333 /*ARGSUSED*/ 334 public void 335 opt_i(type, s) 336 int type; 337 char *s; 338 { 339 switch (type) 340 { 341 case TOGGLE: 342 chg_caseless(); 343 break; 344 case QUERY: 345 case INIT: 346 break; 347 } 348 } 349 350 /* 351 * Handler for the -V option. 352 */ 353 /*ARGSUSED*/ 354 public void 355 opt__V(type, s) 356 int type; 357 char *s; 358 { 359 switch (type) 360 { 361 case TOGGLE: 362 case QUERY: 363 case INIT: 364 dispversion(); 365 if (type == INIT) 366 quit(QUIT_OK); 367 break; 368 } 369 } 370 371 #if MSOFTC 372 /* 373 * 374 */ 375 static void 376 colordesc(s, fg_color, bg_color) 377 char *s; 378 int *fg_color; 379 int *bg_color; 380 { 381 int fg, bg; 382 int err; 383 384 fg = getnum(&s, 'D', &err); 385 if (err) 386 { 387 error("Missing fg color in -D", NULL_PARG); 388 return; 389 } 390 if (*s != '.') 391 bg = 0; 392 else 393 { 394 s++; 395 bg = getnum(&s, 'D', &err); 396 if (err) 397 { 398 error("Missing fg color in -D", NULL_PARG); 399 return; 400 } 401 } 402 *fg_color = fg; 403 *bg_color = bg; 404 } 405 406 /* 407 * Handler for the -D option. 408 */ 409 /*ARGSUSED*/ 410 public void 411 opt_D(type, s) 412 int type; 413 char *s; 414 { 415 switch (type) 416 { 417 case INIT: 418 case TOGGLE: 419 switch (*s++) 420 { 421 case 'n': 422 colordesc(s, &nm_fg_color, &nm_bg_color); 423 break; 424 case 'd': 425 colordesc(s, &bo_fg_color, &bo_bg_color); 426 break; 427 case 'u': 428 colordesc(s, &ul_fg_color, &ul_bg_color); 429 break; 430 case 'k': 431 colordesc(s, &bl_fg_color, &bl_bg_color); 432 break; 433 case 's': 434 colordesc(s, &so_fg_color, &so_bg_color); 435 break; 436 default: 437 error("-D must be followed by n, d, u, k or s", NULL_PARG); 438 break; 439 } 440 if (type == TOGGLE) 441 { 442 so_enter(); 443 so_exit(); 444 } 445 break; 446 case QUERY: 447 break; 448 } 449 } 450 #endif 451 452 /* 453 * "-?" means display a help message. 454 * If from the command line, exit immediately. 455 */ 456 /*ARGSUSED*/ 457 public void 458 opt_query(type, s) 459 int type; 460 char *s; 461 { 462 if (nohelp) 463 return; 464 switch (type) 465 { 466 case QUERY: 467 case TOGGLE: 468 error("Use \"h\" for help", NULL_PARG); 469 break; 470 case INIT: 471 /* 472 * This is "less -?". 473 * It rather ungracefully grabs control, 474 * does the initializations normally done in main, 475 * shows the help file and exits. 476 */ 477 raw_mode(1); 478 get_term(); 479 open_getchr(); 480 init(); 481 any_display = TRUE; 482 help(1); 483 quit(QUIT_OK); 484 /*NOTREACHED*/ 485 } 486 } 487 488 /* 489 * Get the "screen window" size. 490 */ 491 public int 492 get_swindow() 493 { 494 if (swindow > 0) 495 return (swindow); 496 return (sc_height + swindow); 497 } 498 499