optfunc.c revision 89019
160786Sps/* 260786Sps * Copyright (C) 1984-2000 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; 3260786Spsextern int cbufs; 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; 5760786Sps#endif 5860786Sps#if MSDOS_COMPILER 5960786Spsextern int nm_fg_color, nm_bg_color; 6060786Spsextern int bo_fg_color, bo_bg_color; 6160786Spsextern int ul_fg_color, ul_bg_color; 6260786Spsextern int so_fg_color, so_bg_color; 6360786Spsextern int bl_fg_color, bl_bg_color; 6460786Sps#endif 6560786Sps 6660786Sps 6760786Sps#if LOGFILE 6860786Sps/* 6960786Sps * Handler for -o option. 7060786Sps */ 7160786Sps public void 7260786Spsopt_o(type, s) 7360786Sps int type; 7460786Sps char *s; 7560786Sps{ 7660786Sps PARG parg; 7760786Sps 7860786Sps if (secure) 7960786Sps { 8060786Sps error("log file support is not available", NULL_PARG); 8160786Sps return; 8260786Sps } 8360786Sps switch (type) 8460786Sps { 8560786Sps case INIT: 8660786Sps namelogfile = s; 8760786Sps break; 8860786Sps case TOGGLE: 8960786Sps if (ch_getflags() & CH_CANSEEK) 9060786Sps { 9160786Sps error("Input is not a pipe", NULL_PARG); 9260786Sps return; 9360786Sps } 9460786Sps if (logfile >= 0) 9560786Sps { 9660786Sps error("Log file is already in use", NULL_PARG); 9760786Sps return; 9860786Sps } 9960786Sps s = skipsp(s); 10060786Sps namelogfile = lglob(s); 10160786Sps use_logfile(namelogfile); 10260786Sps sync_logfile(); 10360786Sps break; 10460786Sps case QUERY: 10560786Sps if (logfile < 0) 10660786Sps error("No log file", NULL_PARG); 10760786Sps else 10860786Sps { 10960786Sps parg.p_string = unquote_file(namelogfile); 11060786Sps error("Log file \"%s\"", &parg); 11160786Sps free(parg.p_string); 11260786Sps } 11360786Sps break; 11460786Sps } 11560786Sps} 11660786Sps 11760786Sps/* 11860786Sps * Handler for -O option. 11960786Sps */ 12060786Sps public void 12160786Spsopt__O(type, s) 12260786Sps int type; 12360786Sps char *s; 12460786Sps{ 12560786Sps force_logfile = TRUE; 12660786Sps opt_o(type, s); 12760786Sps} 12860786Sps#endif 12960786Sps 13060786Sps/* 13160786Sps * Handlers for -l option. 13260786Sps */ 13360786Sps public void 13460786Spsopt_l(type, s) 13560786Sps int type; 13660786Sps char *s; 13760786Sps{ 13860786Sps int err; 13960786Sps int n; 14060786Sps char *t; 14160786Sps 14260786Sps switch (type) 14360786Sps { 14460786Sps case INIT: 14560786Sps t = s; 14660786Sps n = getnum(&t, 'l', &err); 14760786Sps if (err || n <= 0) 14860786Sps { 14960786Sps error("Line number is required after -l", NULL_PARG); 15060786Sps return; 15160786Sps } 15260786Sps plusoption = TRUE; 15360786Sps ungetsc(s); 15460786Sps break; 15560786Sps } 15660786Sps} 15760786Sps 15860786Sps#if USERFILE 15960786Sps public void 16060786Spsopt_k(type, s) 16160786Sps int type; 16260786Sps char *s; 16360786Sps{ 16460786Sps PARG parg; 16560786Sps 16660786Sps switch (type) 16760786Sps { 16860786Sps case INIT: 16960786Sps if (lesskey(s, 0)) 17060786Sps { 17160786Sps parg.p_string = unquote_file(s); 17260786Sps error("Cannot use lesskey file \"%s\"", &parg); 17360786Sps free(parg.p_string); 17460786Sps } 17560786Sps break; 17660786Sps } 17760786Sps} 17860786Sps#endif 17960786Sps 18060786Sps#if TAGS 18160786Sps/* 18260786Sps * Handler for -t option. 18360786Sps */ 18460786Sps public void 18560786Spsopt_t(type, s) 18660786Sps int type; 18760786Sps char *s; 18860786Sps{ 18960786Sps IFILE save_ifile; 19060786Sps POSITION pos; 19160786Sps 19260786Sps switch (type) 19360786Sps { 19460786Sps case INIT: 19560786Sps tagoption = s; 19660786Sps /* Do the rest in main() */ 19760786Sps break; 19860786Sps case TOGGLE: 19960786Sps if (secure) 20060786Sps { 20160786Sps error("tags support is not available", NULL_PARG); 20260786Sps break; 20360786Sps } 20460786Sps findtag(skipsp(s)); 20560786Sps save_ifile = save_curr_ifile(); 20660786Sps if (edit_tagfile()) 20760786Sps break; 20860786Sps if ((pos = tagsearch()) == NULL_POSITION) 20960786Sps { 21060786Sps reedit_ifile(save_ifile); 21160786Sps break; 21260786Sps } 21360786Sps unsave_ifile(save_ifile); 21460786Sps jump_loc(pos, jump_sline); 21560786Sps break; 21660786Sps } 21760786Sps} 21860786Sps 21960786Sps/* 22060786Sps * Handler for -T option. 22160786Sps */ 22260786Sps public void 22360786Spsopt__T(type, s) 22460786Sps int type; 22560786Sps char *s; 22660786Sps{ 22760786Sps PARG parg; 22860786Sps 22960786Sps switch (type) 23060786Sps { 23160786Sps case INIT: 23260786Sps tags = s; 23360786Sps break; 23460786Sps case TOGGLE: 23560786Sps s = skipsp(s); 23660786Sps tags = lglob(s); 23760786Sps break; 23860786Sps case QUERY: 23960786Sps parg.p_string = unquote_file(tags); 24060786Sps error("Tags file \"%s\"", &parg); 24160786Sps free(parg.p_string); 24260786Sps break; 24360786Sps } 24460786Sps} 24560786Sps#endif 24660786Sps 24760786Sps/* 24860786Sps * Handler for -p option. 24960786Sps */ 25060786Sps public void 25160786Spsopt_p(type, s) 25260786Sps int type; 25360786Sps register char *s; 25460786Sps{ 25560786Sps switch (type) 25660786Sps { 25760786Sps case INIT: 25860786Sps /* 25960786Sps * Unget a search command for the specified string. 26060786Sps * {{ This won't work if the "/" command is 26160786Sps * changed or invalidated by a .lesskey file. }} 26260786Sps */ 26360786Sps plusoption = TRUE; 26460786Sps ungetsc(s); 26560786Sps ungetsc("/"); 26660786Sps break; 26760786Sps } 26860786Sps} 26960786Sps 27060786Sps/* 27160786Sps * Handler for -P option. 27260786Sps */ 27360786Sps public void 27460786Spsopt__P(type, s) 27560786Sps int type; 27660786Sps register char *s; 27760786Sps{ 27860786Sps register char **proto; 27960786Sps PARG parg; 28060786Sps 28160786Sps switch (type) 28260786Sps { 28360786Sps case INIT: 28460786Sps case TOGGLE: 28560786Sps /* 28660786Sps * Figure out which prototype string should be changed. 28760786Sps */ 28860786Sps switch (*s) 28960786Sps { 29060786Sps case 's': proto = &prproto[PR_SHORT]; s++; break; 29160786Sps case 'm': proto = &prproto[PR_MEDIUM]; s++; break; 29260786Sps case 'M': proto = &prproto[PR_LONG]; s++; break; 29360786Sps case '=': proto = &eqproto; s++; break; 29460786Sps case 'h': proto = &hproto; s++; break; 29589019Sps case 'w': proto = &wproto; s++; break; 29660786Sps default: proto = &prproto[PR_SHORT]; break; 29760786Sps } 29860786Sps free(*proto); 29960786Sps *proto = save(s); 30060786Sps break; 30160786Sps case QUERY: 30260786Sps parg.p_string = prproto[pr_type]; 30360786Sps error("%s", &parg); 30460786Sps break; 30560786Sps } 30660786Sps} 30760786Sps 30860786Sps/* 30960786Sps * Handler for the -b option. 31060786Sps */ 31160786Sps /*ARGSUSED*/ 31260786Sps public void 31360786Spsopt_b(type, s) 31460786Sps int type; 31560786Sps char *s; 31660786Sps{ 31760786Sps switch (type) 31860786Sps { 31960786Sps case TOGGLE: 32060786Sps case QUERY: 32160786Sps /* 32260786Sps * Allocate the new number of buffers. 32360786Sps */ 32460786Sps cbufs = ch_nbuf(cbufs); 32560786Sps break; 32660786Sps case INIT: 32760786Sps break; 32860786Sps } 32960786Sps} 33060786Sps 33160786Sps/* 33260786Sps * Handler for the -i option. 33360786Sps */ 33460786Sps /*ARGSUSED*/ 33560786Sps public void 33660786Spsopt_i(type, s) 33760786Sps int type; 33860786Sps char *s; 33960786Sps{ 34060786Sps switch (type) 34160786Sps { 34260786Sps case TOGGLE: 34360786Sps chg_caseless(); 34460786Sps break; 34560786Sps case QUERY: 34660786Sps case INIT: 34760786Sps break; 34860786Sps } 34960786Sps} 35060786Sps 35160786Sps/* 35260786Sps * Handler for the -V option. 35360786Sps */ 35460786Sps /*ARGSUSED*/ 35560786Sps public void 35660786Spsopt__V(type, s) 35760786Sps int type; 35860786Sps char *s; 35960786Sps{ 36060786Sps switch (type) 36160786Sps { 36260786Sps case TOGGLE: 36360786Sps case QUERY: 36460786Sps dispversion(); 36560786Sps break; 36660786Sps case INIT: 36760786Sps /* 36860786Sps * Force output to stdout per GNU standard for --version output. 36960786Sps */ 37060786Sps any_display = 1; 37160786Sps putstr("less "); 37260786Sps putstr(version); 37389019Sps putstr("\nCopyright (C) 2001 Mark Nudelman\n\n"); 37460786Sps putstr("less comes with NO WARRANTY, to the extent permitted by law.\n"); 37560786Sps putstr("For information about the terms of redistribution,\n"); 37660786Sps putstr("see the file named README in the less distribution.\n"); 37789019Sps putstr("Homepage: http://www.greenwoodsoftware.com/less\n"); 37860786Sps quit(QUIT_OK); 37960786Sps break; 38060786Sps } 38160786Sps} 38260786Sps 38360786Sps#if MSDOS_COMPILER 38460786Sps/* 38560786Sps * Parse an MSDOS color descriptor. 38660786Sps */ 38760786Sps static void 38860786Spscolordesc(s, fg_color, bg_color) 38960786Sps char *s; 39060786Sps int *fg_color; 39160786Sps int *bg_color; 39260786Sps{ 39360786Sps int fg, bg; 39460786Sps int err; 39560786Sps 39660786Sps fg = getnum(&s, 'D', &err); 39760786Sps if (err) 39860786Sps { 39960786Sps error("Missing fg color in -D", NULL_PARG); 40060786Sps return; 40160786Sps } 40260786Sps if (*s != '.') 40360786Sps bg = 0; 40460786Sps else 40560786Sps { 40660786Sps s++; 40760786Sps bg = getnum(&s, 'D', &err); 40860786Sps if (err) 40960786Sps { 41060786Sps error("Missing fg color in -D", NULL_PARG); 41160786Sps return; 41260786Sps } 41360786Sps } 41460786Sps if (*s != '\0') 41560786Sps error("Extra characters at end of -D option", NULL_PARG); 41660786Sps *fg_color = fg; 41760786Sps *bg_color = bg; 41860786Sps} 41960786Sps 42060786Sps/* 42160786Sps * Handler for the -D option. 42260786Sps */ 42360786Sps /*ARGSUSED*/ 42460786Sps public void 42560786Spsopt_D(type, s) 42660786Sps int type; 42760786Sps char *s; 42860786Sps{ 42960786Sps switch (type) 43060786Sps { 43160786Sps case INIT: 43260786Sps case TOGGLE: 43360786Sps switch (*s++) 43460786Sps { 43560786Sps case 'n': 43660786Sps colordesc(s, &nm_fg_color, &nm_bg_color); 43760786Sps break; 43860786Sps case 'd': 43960786Sps colordesc(s, &bo_fg_color, &bo_bg_color); 44060786Sps break; 44160786Sps case 'u': 44260786Sps colordesc(s, &ul_fg_color, &ul_bg_color); 44360786Sps break; 44460786Sps case 'k': 44560786Sps colordesc(s, &bl_fg_color, &bl_bg_color); 44660786Sps break; 44760786Sps case 's': 44860786Sps colordesc(s, &so_fg_color, &so_bg_color); 44960786Sps break; 45060786Sps default: 45160786Sps error("-D must be followed by n, d, u, k or s", NULL_PARG); 45260786Sps break; 45360786Sps } 45460786Sps if (type == TOGGLE) 45560786Sps { 45660786Sps so_enter(); 45760786Sps so_exit(); 45860786Sps } 45960786Sps break; 46060786Sps case QUERY: 46160786Sps break; 46260786Sps } 46360786Sps} 46460786Sps#endif 46560786Sps 46660786Sps/* 46789019Sps * Handler for the -x option. 46889019Sps */ 46989019Sps public void 47089019Spsopt_x(type, s) 47189019Sps int type; 47289019Sps register char *s; 47389019Sps{ 47489019Sps extern int tabstops[]; 47589019Sps extern int ntabstops; 47689019Sps extern int tabdefault; 47789019Sps char msg[60+(4*TABSTOP_MAX)]; 47889019Sps int i; 47989019Sps PARG p; 48089019Sps 48189019Sps switch (type) 48289019Sps { 48389019Sps case INIT: 48489019Sps case TOGGLE: 48589019Sps /* Start at 1 because tabstops[0] is always zero. */ 48689019Sps for (i = 1; i < TABSTOP_MAX; ) 48789019Sps { 48889019Sps int n = 0; 48989019Sps while (*s >= '0' && *s <= '9') 49089019Sps n = (10 * n) + (*s++ - '0'); 49189019Sps if (n > tabstops[i-1]) 49289019Sps tabstops[i++] = n; 49389019Sps if (*s++ != ',') 49489019Sps break; 49589019Sps } 49689019Sps if (i < 2) 49789019Sps return; 49889019Sps ntabstops = i; 49989019Sps tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2]; 50089019Sps break; 50189019Sps case QUERY: 50289019Sps strcpy(msg, "Tab stops "); 50389019Sps if (ntabstops > 2) 50489019Sps { 50589019Sps for (i = 1; i < ntabstops; i++) 50689019Sps { 50789019Sps if (i > 1) 50889019Sps strcat(msg, ","); 50989019Sps sprintf(msg+strlen(msg), "%d", tabstops[i]); 51089019Sps } 51189019Sps sprintf(msg+strlen(msg), " and then "); 51289019Sps } 51389019Sps sprintf(msg+strlen(msg), "every %d spaces", 51489019Sps tabdefault); 51589019Sps p.p_string = msg; 51689019Sps error("%s", &p); 51789019Sps break; 51889019Sps } 51989019Sps} 52089019Sps 52189019Sps 52289019Sps/* 52360786Sps * Handler for the -" option. 52460786Sps */ 52560786Sps public void 52660786Spsopt_quote(type, s) 52760786Sps int type; 52860786Sps register char *s; 52960786Sps{ 53060786Sps char buf[3]; 53160786Sps PARG parg; 53260786Sps 53360786Sps switch (type) 53460786Sps { 53560786Sps case INIT: 53660786Sps case TOGGLE: 53760786Sps if (s[1] != '\0' && s[2] != '\0') 53860786Sps { 53960786Sps error("-\" must be followed by 1 or 2 chars", NULL_PARG); 54060786Sps return; 54160786Sps } 54260786Sps openquote = s[0]; 54360786Sps if (s[1] == '\0') 54460786Sps closequote = openquote; 54560786Sps else 54660786Sps closequote = s[1]; 54760786Sps break; 54860786Sps case QUERY: 54960786Sps buf[0] = openquote; 55060786Sps buf[1] = closequote; 55160786Sps buf[2] = '\0'; 55260786Sps parg.p_string = buf; 55360786Sps error("quotes %s", &parg); 55460786Sps break; 55560786Sps } 55660786Sps} 55760786Sps 55860786Sps/* 55960786Sps * "-?" means display a help message. 56060786Sps * If from the command line, exit immediately. 56160786Sps */ 56260786Sps /*ARGSUSED*/ 56360786Sps public void 56460786Spsopt_query(type, s) 56560786Sps int type; 56660786Sps char *s; 56760786Sps{ 56860786Sps switch (type) 56960786Sps { 57060786Sps case QUERY: 57160786Sps case TOGGLE: 57260786Sps error("Use \"h\" for help", NULL_PARG); 57360786Sps break; 57460786Sps case INIT: 57560786Sps dohelp = 1; 57660786Sps } 57760786Sps} 57860786Sps 57960786Sps/* 58060786Sps * Get the "screen window" size. 58160786Sps */ 58260786Sps public int 58360786Spsget_swindow() 58460786Sps{ 58560786Sps if (swindow > 0) 58660786Sps return (swindow); 58760786Sps return (sc_height + swindow); 58860786Sps} 58960786Sps 590