optfunc.c revision 170256
160786Sps/* 2170256Sdelphij * Copyright (C) 1984-2007 Mark Nudelman 360786Sps * 460786Sps * You may distribute under the terms of either the GNU General Public 560786Sps * License or the Less License, as specified in the README file. 660786Sps * 760786Sps * For more information about less, or for information on how to 860786Sps * contact the author, see the README file. 960786Sps */ 1060786Sps 1160786Sps 1260786Sps/* 1360786Sps * Handling functions for command line options. 1460786Sps * 1560786Sps * Most options are handled by the generic code in option.c. 1660786Sps * But all string options, and a few non-string options, require 1760786Sps * special handling specific to the particular option. 1860786Sps * This special processing is done by the "handling functions" in this file. 1960786Sps * 2060786Sps * Each handling function is passed a "type" and, if it is a string 2160786Sps * option, the string which should be "assigned" to the option. 2260786Sps * The type may be one of: 2360786Sps * INIT The option is being initialized from the command line. 2460786Sps * TOGGLE The option is being changed from within the program. 2560786Sps * QUERY The setting of the option is merely being queried. 2660786Sps */ 2760786Sps 2860786Sps#include "less.h" 2960786Sps#include "option.h" 3060786Sps 3160786Spsextern int nbufs; 32128345Stjrextern int bufspace; 3360786Spsextern int pr_type; 3460786Spsextern int plusoption; 3560786Spsextern int swindow; 3660786Spsextern int sc_height; 3760786Spsextern int secure; 3860786Spsextern int dohelp; 3960786Spsextern int any_display; 4060786Spsextern char openquote; 4160786Spsextern char closequote; 4260786Spsextern char *prproto[]; 4360786Spsextern char *eqproto; 4460786Spsextern char *hproto; 4589019Spsextern char *wproto; 4660786Spsextern IFILE curr_ifile; 4760786Spsextern char version[]; 4860786Sps#if LOGFILE 4960786Spsextern char *namelogfile; 5060786Spsextern int force_logfile; 5160786Spsextern int logfile; 5260786Sps#endif 5360786Sps#if TAGS 5460786Spspublic char *tagoption = NULL; 5560786Spsextern char *tags; 5660786Spsextern int jump_sline; 57170256Sdelphijextern int jump_sline_fraction; 58170256Sdelphijextern int less_is_more; 5960786Sps#endif 6060786Sps#if MSDOS_COMPILER 6160786Spsextern int nm_fg_color, nm_bg_color; 6260786Spsextern int bo_fg_color, bo_bg_color; 6360786Spsextern int ul_fg_color, ul_bg_color; 6460786Spsextern int so_fg_color, so_bg_color; 6560786Spsextern int bl_fg_color, bl_bg_color; 6660786Sps#endif 6760786Sps 6860786Sps 6960786Sps#if LOGFILE 7060786Sps/* 7160786Sps * Handler for -o option. 7260786Sps */ 7360786Sps public void 7460786Spsopt_o(type, s) 7560786Sps int type; 7660786Sps char *s; 7760786Sps{ 7860786Sps PARG parg; 7960786Sps 8060786Sps if (secure) 8160786Sps { 8260786Sps error("log file support is not available", NULL_PARG); 8360786Sps return; 8460786Sps } 8560786Sps switch (type) 8660786Sps { 8760786Sps case INIT: 8860786Sps namelogfile = s; 8960786Sps break; 9060786Sps case TOGGLE: 9160786Sps if (ch_getflags() & CH_CANSEEK) 9260786Sps { 9360786Sps error("Input is not a pipe", NULL_PARG); 9460786Sps return; 9560786Sps } 9660786Sps if (logfile >= 0) 9760786Sps { 9860786Sps error("Log file is already in use", NULL_PARG); 9960786Sps return; 10060786Sps } 10160786Sps s = skipsp(s); 10260786Sps namelogfile = lglob(s); 10360786Sps use_logfile(namelogfile); 10460786Sps sync_logfile(); 10560786Sps break; 10660786Sps case QUERY: 10760786Sps if (logfile < 0) 10860786Sps error("No log file", NULL_PARG); 10960786Sps else 11060786Sps { 111128345Stjr parg.p_string = namelogfile; 11260786Sps error("Log file \"%s\"", &parg); 11360786Sps } 11460786Sps break; 11560786Sps } 11660786Sps} 11760786Sps 11860786Sps/* 11960786Sps * Handler for -O option. 12060786Sps */ 12160786Sps public void 12260786Spsopt__O(type, s) 12360786Sps int type; 12460786Sps char *s; 12560786Sps{ 12660786Sps force_logfile = TRUE; 12760786Sps opt_o(type, s); 12860786Sps} 12960786Sps#endif 13060786Sps 13160786Sps/* 13260786Sps * Handlers for -l option. 13360786Sps */ 13460786Sps public void 13560786Spsopt_l(type, s) 13660786Sps int type; 13760786Sps char *s; 13860786Sps{ 13960786Sps int err; 14060786Sps int n; 14160786Sps char *t; 14260786Sps 14360786Sps switch (type) 14460786Sps { 14560786Sps case INIT: 14660786Sps t = s; 147128345Stjr n = getnum(&t, "l", &err); 14860786Sps if (err || n <= 0) 14960786Sps { 15060786Sps error("Line number is required after -l", NULL_PARG); 15160786Sps return; 15260786Sps } 15360786Sps plusoption = TRUE; 15460786Sps ungetsc(s); 15560786Sps break; 15660786Sps } 15760786Sps} 15860786Sps 159170256Sdelphij/* 160170256Sdelphij * Handlers for -j option. 161170256Sdelphij */ 162170256Sdelphij public void 163170256Sdelphijopt_j(type, s) 164170256Sdelphij int type; 165170256Sdelphij char *s; 166170256Sdelphij{ 167170256Sdelphij PARG parg; 168170256Sdelphij char buf[16]; 169170256Sdelphij int len; 170170256Sdelphij int err; 171170256Sdelphij 172170256Sdelphij switch (type) 173170256Sdelphij { 174170256Sdelphij case INIT: 175170256Sdelphij case TOGGLE: 176170256Sdelphij if (*s == '.') 177170256Sdelphij { 178170256Sdelphij s++; 179170256Sdelphij jump_sline_fraction = getfraction(&s, "j", &err); 180170256Sdelphij if (err) 181170256Sdelphij error("Invalid line fraction", NULL_PARG); 182170256Sdelphij else 183170256Sdelphij calc_jump_sline(); 184170256Sdelphij } else 185170256Sdelphij { 186170256Sdelphij int sline = getnum(&s, "j", &err); 187170256Sdelphij if (err) 188170256Sdelphij error("Invalid line number", NULL_PARG); 189170256Sdelphij else 190170256Sdelphij { 191170256Sdelphij jump_sline = sline; 192170256Sdelphij jump_sline_fraction = -1; 193170256Sdelphij } 194170256Sdelphij } 195170256Sdelphij break; 196170256Sdelphij case QUERY: 197170256Sdelphij if (jump_sline_fraction < 0) 198170256Sdelphij { 199170256Sdelphij parg.p_int = jump_sline; 200170256Sdelphij error("Position target at screen line %d", &parg); 201170256Sdelphij } else 202170256Sdelphij { 203170256Sdelphij 204170256Sdelphij sprintf(buf, ".%06d", jump_sline_fraction); 205170256Sdelphij len = strlen(buf); 206170256Sdelphij while (len > 2 && buf[len-1] == '0') 207170256Sdelphij len--; 208170256Sdelphij buf[len] = '\0'; 209170256Sdelphij parg.p_string = buf; 210170256Sdelphij error("Position target at screen position %s", &parg); 211170256Sdelphij } 212170256Sdelphij break; 213170256Sdelphij } 214170256Sdelphij} 215170256Sdelphij 216170256Sdelphij public void 217170256Sdelphijcalc_jump_sline() 218170256Sdelphij{ 219170256Sdelphij if (jump_sline_fraction < 0) 220170256Sdelphij return; 221170256Sdelphij jump_sline = sc_height * jump_sline_fraction / NUM_FRAC_DENOM; 222170256Sdelphij} 223170256Sdelphij 22460786Sps#if USERFILE 22560786Sps public void 22660786Spsopt_k(type, s) 22760786Sps int type; 22860786Sps char *s; 22960786Sps{ 23060786Sps PARG parg; 23160786Sps 23260786Sps switch (type) 23360786Sps { 23460786Sps case INIT: 23560786Sps if (lesskey(s, 0)) 23660786Sps { 237128345Stjr parg.p_string = s; 23860786Sps error("Cannot use lesskey file \"%s\"", &parg); 23960786Sps } 24060786Sps break; 24160786Sps } 24260786Sps} 24360786Sps#endif 24460786Sps 24560786Sps#if TAGS 24660786Sps/* 24760786Sps * Handler for -t option. 24860786Sps */ 24960786Sps public void 25060786Spsopt_t(type, s) 25160786Sps int type; 25260786Sps char *s; 25360786Sps{ 25460786Sps IFILE save_ifile; 25560786Sps POSITION pos; 25660786Sps 25760786Sps switch (type) 25860786Sps { 25960786Sps case INIT: 26060786Sps tagoption = s; 26160786Sps /* Do the rest in main() */ 26260786Sps break; 26360786Sps case TOGGLE: 26460786Sps if (secure) 26560786Sps { 26660786Sps error("tags support is not available", NULL_PARG); 26760786Sps break; 26860786Sps } 26960786Sps findtag(skipsp(s)); 27060786Sps save_ifile = save_curr_ifile(); 271161475Sdelphij /* 272161475Sdelphij * Try to open the file containing the tag 273161475Sdelphij * and search for the tag in that file. 274161475Sdelphij */ 275161475Sdelphij if (edit_tagfile() || (pos = tagsearch()) == NULL_POSITION) 27660786Sps { 277161475Sdelphij /* Failed: reopen the old file. */ 27860786Sps reedit_ifile(save_ifile); 27960786Sps break; 28060786Sps } 28160786Sps unsave_ifile(save_ifile); 28260786Sps jump_loc(pos, jump_sline); 28360786Sps break; 28460786Sps } 28560786Sps} 28660786Sps 28760786Sps/* 28860786Sps * Handler for -T option. 28960786Sps */ 29060786Sps public void 29160786Spsopt__T(type, s) 29260786Sps int type; 29360786Sps char *s; 29460786Sps{ 29560786Sps PARG parg; 29660786Sps 29760786Sps switch (type) 29860786Sps { 29960786Sps case INIT: 30060786Sps tags = s; 30160786Sps break; 30260786Sps case TOGGLE: 30360786Sps s = skipsp(s); 30460786Sps tags = lglob(s); 30560786Sps break; 30660786Sps case QUERY: 307128345Stjr parg.p_string = tags; 30860786Sps error("Tags file \"%s\"", &parg); 30960786Sps break; 31060786Sps } 31160786Sps} 31260786Sps#endif 31360786Sps 31460786Sps/* 31560786Sps * Handler for -p option. 31660786Sps */ 31760786Sps public void 31860786Spsopt_p(type, s) 31960786Sps int type; 32060786Sps register char *s; 32160786Sps{ 32260786Sps switch (type) 32360786Sps { 32460786Sps case INIT: 32560786Sps /* 32660786Sps * Unget a search command for the specified string. 32760786Sps * {{ This won't work if the "/" command is 32860786Sps * changed or invalidated by a .lesskey file. }} 32960786Sps */ 33060786Sps plusoption = TRUE; 33160786Sps ungetsc(s); 332161475Sdelphij /* 333161475Sdelphij * In "more" mode, the -p argument is a command, 334161475Sdelphij * not a search string, so we don't need a slash. 335161475Sdelphij */ 336170256Sdelphij if (!less_is_more) 337161475Sdelphij ungetsc("/"); 33860786Sps break; 33960786Sps } 34060786Sps} 34160786Sps 34260786Sps/* 34360786Sps * Handler for -P option. 34460786Sps */ 34560786Sps public void 34660786Spsopt__P(type, s) 34760786Sps int type; 34860786Sps register char *s; 34960786Sps{ 35060786Sps register char **proto; 35160786Sps PARG parg; 35260786Sps 35360786Sps switch (type) 35460786Sps { 35560786Sps case INIT: 35660786Sps case TOGGLE: 35760786Sps /* 35860786Sps * Figure out which prototype string should be changed. 35960786Sps */ 36060786Sps switch (*s) 36160786Sps { 36260786Sps case 's': proto = &prproto[PR_SHORT]; s++; break; 36360786Sps case 'm': proto = &prproto[PR_MEDIUM]; s++; break; 36460786Sps case 'M': proto = &prproto[PR_LONG]; s++; break; 36560786Sps case '=': proto = &eqproto; s++; break; 36660786Sps case 'h': proto = &hproto; s++; break; 36789019Sps case 'w': proto = &wproto; s++; break; 36860786Sps default: proto = &prproto[PR_SHORT]; break; 36960786Sps } 37060786Sps free(*proto); 37160786Sps *proto = save(s); 37260786Sps break; 37360786Sps case QUERY: 37460786Sps parg.p_string = prproto[pr_type]; 37560786Sps error("%s", &parg); 37660786Sps break; 37760786Sps } 37860786Sps} 37960786Sps 38060786Sps/* 38160786Sps * Handler for the -b option. 38260786Sps */ 38360786Sps /*ARGSUSED*/ 38460786Sps public void 38560786Spsopt_b(type, s) 38660786Sps int type; 38760786Sps char *s; 38860786Sps{ 38960786Sps switch (type) 39060786Sps { 391128345Stjr case INIT: 39260786Sps case TOGGLE: 39360786Sps /* 394128345Stjr * Set the new number of buffers. 39560786Sps */ 396128345Stjr ch_setbufspace(bufspace); 39760786Sps break; 398128345Stjr case QUERY: 39960786Sps break; 40060786Sps } 40160786Sps} 40260786Sps 40360786Sps/* 40460786Sps * Handler for the -i option. 40560786Sps */ 40660786Sps /*ARGSUSED*/ 40760786Sps public void 40860786Spsopt_i(type, s) 40960786Sps int type; 41060786Sps char *s; 41160786Sps{ 41260786Sps switch (type) 41360786Sps { 41460786Sps case TOGGLE: 41560786Sps chg_caseless(); 41660786Sps break; 41760786Sps case QUERY: 41860786Sps case INIT: 41960786Sps break; 42060786Sps } 42160786Sps} 42260786Sps 42360786Sps/* 42460786Sps * Handler for the -V option. 42560786Sps */ 42660786Sps /*ARGSUSED*/ 42760786Sps public void 42860786Spsopt__V(type, s) 42960786Sps int type; 43060786Sps char *s; 43160786Sps{ 43260786Sps switch (type) 43360786Sps { 43460786Sps case TOGGLE: 43560786Sps case QUERY: 43660786Sps dispversion(); 43760786Sps break; 43860786Sps case INIT: 43960786Sps /* 44060786Sps * Force output to stdout per GNU standard for --version output. 44160786Sps */ 44260786Sps any_display = 1; 44360786Sps putstr("less "); 44460786Sps putstr(version); 445161475Sdelphij putstr("\nCopyright (C) 1984-2005 Mark Nudelman\n\n"); 44660786Sps putstr("less comes with NO WARRANTY, to the extent permitted by law.\n"); 44760786Sps putstr("For information about the terms of redistribution,\n"); 44860786Sps putstr("see the file named README in the less distribution.\n"); 44989019Sps putstr("Homepage: http://www.greenwoodsoftware.com/less\n"); 45060786Sps quit(QUIT_OK); 45160786Sps break; 45260786Sps } 45360786Sps} 45460786Sps 45560786Sps#if MSDOS_COMPILER 45660786Sps/* 45760786Sps * Parse an MSDOS color descriptor. 45860786Sps */ 45960786Sps static void 46060786Spscolordesc(s, fg_color, bg_color) 46160786Sps char *s; 46260786Sps int *fg_color; 46360786Sps int *bg_color; 46460786Sps{ 46560786Sps int fg, bg; 46660786Sps int err; 46760786Sps 468128345Stjr fg = getnum(&s, "D", &err); 46960786Sps if (err) 47060786Sps { 47160786Sps error("Missing fg color in -D", NULL_PARG); 47260786Sps return; 47360786Sps } 47460786Sps if (*s != '.') 47560786Sps bg = 0; 47660786Sps else 47760786Sps { 47860786Sps s++; 479128345Stjr bg = getnum(&s, "D", &err); 48060786Sps if (err) 48160786Sps { 48260786Sps error("Missing fg color in -D", NULL_PARG); 48360786Sps return; 48460786Sps } 48560786Sps } 48660786Sps if (*s != '\0') 48760786Sps error("Extra characters at end of -D option", NULL_PARG); 48860786Sps *fg_color = fg; 48960786Sps *bg_color = bg; 49060786Sps} 49160786Sps 49260786Sps/* 49360786Sps * Handler for the -D option. 49460786Sps */ 49560786Sps /*ARGSUSED*/ 49660786Sps public void 49760786Spsopt_D(type, s) 49860786Sps int type; 49960786Sps char *s; 50060786Sps{ 50160786Sps switch (type) 50260786Sps { 50360786Sps case INIT: 50460786Sps case TOGGLE: 50560786Sps switch (*s++) 50660786Sps { 50760786Sps case 'n': 50860786Sps colordesc(s, &nm_fg_color, &nm_bg_color); 50960786Sps break; 51060786Sps case 'd': 51160786Sps colordesc(s, &bo_fg_color, &bo_bg_color); 51260786Sps break; 51360786Sps case 'u': 51460786Sps colordesc(s, &ul_fg_color, &ul_bg_color); 51560786Sps break; 51660786Sps case 'k': 51760786Sps colordesc(s, &bl_fg_color, &bl_bg_color); 51860786Sps break; 51960786Sps case 's': 52060786Sps colordesc(s, &so_fg_color, &so_bg_color); 52160786Sps break; 52260786Sps default: 52360786Sps error("-D must be followed by n, d, u, k or s", NULL_PARG); 52460786Sps break; 52560786Sps } 52660786Sps if (type == TOGGLE) 52760786Sps { 528161475Sdelphij at_enter(AT_STANDOUT); 529161475Sdelphij at_exit(); 53060786Sps } 53160786Sps break; 53260786Sps case QUERY: 53360786Sps break; 53460786Sps } 53560786Sps} 53660786Sps#endif 53760786Sps 53860786Sps/* 53989019Sps * Handler for the -x option. 54089019Sps */ 54189019Sps public void 54289019Spsopt_x(type, s) 54389019Sps int type; 54489019Sps register char *s; 54589019Sps{ 54689019Sps extern int tabstops[]; 54789019Sps extern int ntabstops; 54889019Sps extern int tabdefault; 54989019Sps char msg[60+(4*TABSTOP_MAX)]; 55089019Sps int i; 55189019Sps PARG p; 55289019Sps 55389019Sps switch (type) 55489019Sps { 55589019Sps case INIT: 55689019Sps case TOGGLE: 55789019Sps /* Start at 1 because tabstops[0] is always zero. */ 55889019Sps for (i = 1; i < TABSTOP_MAX; ) 55989019Sps { 56089019Sps int n = 0; 561128345Stjr s = skipsp(s); 56289019Sps while (*s >= '0' && *s <= '9') 56389019Sps n = (10 * n) + (*s++ - '0'); 56489019Sps if (n > tabstops[i-1]) 56589019Sps tabstops[i++] = n; 566128345Stjr s = skipsp(s); 56789019Sps if (*s++ != ',') 56889019Sps break; 56989019Sps } 57089019Sps if (i < 2) 57189019Sps return; 57289019Sps ntabstops = i; 57389019Sps tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2]; 57489019Sps break; 57589019Sps case QUERY: 57689019Sps strcpy(msg, "Tab stops "); 57789019Sps if (ntabstops > 2) 57889019Sps { 57989019Sps for (i = 1; i < ntabstops; i++) 58089019Sps { 58189019Sps if (i > 1) 58289019Sps strcat(msg, ","); 58389019Sps sprintf(msg+strlen(msg), "%d", tabstops[i]); 58489019Sps } 58589019Sps sprintf(msg+strlen(msg), " and then "); 58689019Sps } 58789019Sps sprintf(msg+strlen(msg), "every %d spaces", 58889019Sps tabdefault); 58989019Sps p.p_string = msg; 59089019Sps error("%s", &p); 59189019Sps break; 59289019Sps } 59389019Sps} 59489019Sps 59589019Sps 59689019Sps/* 59760786Sps * Handler for the -" option. 59860786Sps */ 59960786Sps public void 60060786Spsopt_quote(type, s) 60160786Sps int type; 60260786Sps register char *s; 60360786Sps{ 60460786Sps char buf[3]; 60560786Sps PARG parg; 60660786Sps 60760786Sps switch (type) 60860786Sps { 60960786Sps case INIT: 61060786Sps case TOGGLE: 611128345Stjr if (s[0] == '\0') 612128345Stjr { 613128345Stjr openquote = closequote = '\0'; 614128345Stjr break; 615128345Stjr } 61660786Sps if (s[1] != '\0' && s[2] != '\0') 61760786Sps { 61860786Sps error("-\" must be followed by 1 or 2 chars", NULL_PARG); 61960786Sps return; 62060786Sps } 62160786Sps openquote = s[0]; 62260786Sps if (s[1] == '\0') 62360786Sps closequote = openquote; 62460786Sps else 62560786Sps closequote = s[1]; 62660786Sps break; 62760786Sps case QUERY: 62860786Sps buf[0] = openquote; 62960786Sps buf[1] = closequote; 63060786Sps buf[2] = '\0'; 63160786Sps parg.p_string = buf; 63260786Sps error("quotes %s", &parg); 63360786Sps break; 63460786Sps } 63560786Sps} 63660786Sps 63760786Sps/* 63860786Sps * "-?" means display a help message. 63960786Sps * If from the command line, exit immediately. 64060786Sps */ 64160786Sps /*ARGSUSED*/ 64260786Sps public void 64360786Spsopt_query(type, s) 64460786Sps int type; 64560786Sps char *s; 64660786Sps{ 64760786Sps switch (type) 64860786Sps { 64960786Sps case QUERY: 65060786Sps case TOGGLE: 65160786Sps error("Use \"h\" for help", NULL_PARG); 65260786Sps break; 65360786Sps case INIT: 65460786Sps dohelp = 1; 65560786Sps } 65660786Sps} 65760786Sps 65860786Sps/* 65960786Sps * Get the "screen window" size. 66060786Sps */ 66160786Sps public int 66260786Spsget_swindow() 66360786Sps{ 66460786Sps if (swindow > 0) 66560786Sps return (swindow); 66660786Sps return (sc_height + swindow); 66760786Sps} 66860786Sps 669