command.c revision 60786
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 * User-level command processor. 1460786Sps */ 1560786Sps 1660786Sps#include "less.h" 1760786Sps#include "position.h" 1860786Sps#include "option.h" 1960786Sps#include "cmd.h" 2060786Sps 2160786Spsextern int erase_char, kill_char; 2260786Spsextern int sigs; 2360786Spsextern int quit_at_eof; 2460786Spsextern int quit_if_one_screen; 2560786Spsextern int squished; 2660786Spsextern int hit_eof; 2760786Spsextern int sc_width; 2860786Spsextern int sc_height; 2960786Spsextern int swindow; 3060786Spsextern int jump_sline; 3160786Spsextern int quitting; 3260786Spsextern int wscroll; 3360786Spsextern int top_scroll; 3460786Spsextern int ignore_eoi; 3560786Spsextern int secure; 3660786Spsextern int hshift; 3760786Spsextern int show_attn; 3860786Spsextern char *every_first_cmd; 3960786Spsextern char *curr_altfilename; 4060786Spsextern char version[]; 4160786Spsextern struct scrpos initial_scrpos; 4260786Spsextern IFILE curr_ifile; 4360786Spsextern void constant *ml_search; 4460786Spsextern void constant *ml_examine; 4560786Sps#if SHELL_ESCAPE || PIPEC 4660786Spsextern void constant *ml_shell; 4760786Sps#endif 4860786Sps#if EDITOR 4960786Spsextern char *editor; 5060786Spsextern char *editproto; 5160786Sps#endif 5260786Spsextern int screen_trashed; /* The screen has been overwritten */ 5360786Sps 5460786Spsstatic char ungot[UNGOT_SIZE]; 5560786Spsstatic char *ungotp = NULL; 5660786Sps#if SHELL_ESCAPE 5760786Spsstatic char *shellcmd = NULL; /* For holding last shell command for "!!" */ 5860786Sps#endif 5960786Spsstatic int mca; /* The multicharacter command (action) */ 6060786Spsstatic int search_type; /* The previous type of search */ 6160786Spsstatic int number; /* The number typed by the user */ 6260786Spsstatic char optchar; 6360786Spsstatic int optflag; 6460786Spsstatic int optgetname; 6560786Spsstatic POSITION bottompos; 6660786Sps#if PIPEC 6760786Spsstatic char pipec; 6860786Sps#endif 6960786Sps 7060786Spsstatic void multi_search(); 7160786Sps 7260786Sps/* 7360786Sps * Move the cursor to lower left before executing a command. 7460786Sps * This looks nicer if the command takes a long time before 7560786Sps * updating the screen. 7660786Sps */ 7760786Sps static void 7860786Spscmd_exec() 7960786Sps{ 8060786Sps clear_attn(); 8160786Sps lower_left(); 8260786Sps flush(); 8360786Sps} 8460786Sps 8560786Sps/* 8660786Sps * Set up the display to start a new multi-character command. 8760786Sps */ 8860786Sps static void 8960786Spsstart_mca(action, prompt, mlist, cmdflags) 9060786Sps int action; 9160786Sps char *prompt; 9260786Sps void *mlist; 9360786Sps int cmdflags; 9460786Sps{ 9560786Sps mca = action; 9660786Sps clear_cmd(); 9760786Sps cmd_putstr(prompt); 9860786Sps set_mlist(mlist, cmdflags); 9960786Sps} 10060786Sps 10160786Sps public int 10260786Spsin_mca() 10360786Sps{ 10460786Sps return (mca != 0 && mca != A_PREFIX); 10560786Sps} 10660786Sps 10760786Sps/* 10860786Sps * Set up the display to start a new search command. 10960786Sps */ 11060786Sps static void 11160786Spsmca_search() 11260786Sps{ 11360786Sps if (search_type & SRCH_FORW) 11460786Sps mca = A_F_SEARCH; 11560786Sps else 11660786Sps mca = A_B_SEARCH; 11760786Sps 11860786Sps clear_cmd(); 11960786Sps 12060786Sps if (search_type & SRCH_NO_MATCH) 12160786Sps cmd_putstr("Non-match "); 12260786Sps if (search_type & SRCH_FIRST_FILE) 12360786Sps cmd_putstr("First-file "); 12460786Sps if (search_type & SRCH_PAST_EOF) 12560786Sps cmd_putstr("EOF-ignore "); 12660786Sps if (search_type & SRCH_NO_MOVE) 12760786Sps cmd_putstr("Keep-pos "); 12860786Sps if (search_type & SRCH_NO_REGEX) 12960786Sps cmd_putstr("Regex-off "); 13060786Sps 13160786Sps if (search_type & SRCH_FORW) 13260786Sps cmd_putstr("/"); 13360786Sps else 13460786Sps cmd_putstr("?"); 13560786Sps set_mlist(ml_search, 0); 13660786Sps} 13760786Sps 13860786Sps/* 13960786Sps * Set up the display to start a new toggle-option command. 14060786Sps */ 14160786Sps static void 14260786Spsmca_opt_toggle() 14360786Sps{ 14460786Sps int no_prompt; 14560786Sps int flag; 14660786Sps char *dash; 14760786Sps 14860786Sps no_prompt = (optflag & OPT_NO_PROMPT); 14960786Sps flag = (optflag & ~OPT_NO_PROMPT); 15060786Sps dash = (flag == OPT_NO_TOGGLE) ? "_" : "-"; 15160786Sps 15260786Sps mca = A_OPT_TOGGLE; 15360786Sps clear_cmd(); 15460786Sps cmd_putstr(dash); 15560786Sps if (optgetname) 15660786Sps cmd_putstr(dash); 15760786Sps if (no_prompt) 15860786Sps cmd_putstr("(P)"); 15960786Sps switch (flag) 16060786Sps { 16160786Sps case OPT_UNSET: 16260786Sps cmd_putstr("+"); 16360786Sps break; 16460786Sps case OPT_SET: 16560786Sps cmd_putstr("!"); 16660786Sps break; 16760786Sps } 16860786Sps set_mlist(NULL, 0); 16960786Sps} 17060786Sps 17160786Sps/* 17260786Sps * Execute a multicharacter command. 17360786Sps */ 17460786Sps static void 17560786Spsexec_mca() 17660786Sps{ 17760786Sps register char *cbuf; 17860786Sps 17960786Sps cmd_exec(); 18060786Sps cbuf = get_cmdbuf(); 18160786Sps 18260786Sps switch (mca) 18360786Sps { 18460786Sps case A_F_SEARCH: 18560786Sps case A_B_SEARCH: 18660786Sps multi_search(cbuf, number); 18760786Sps break; 18860786Sps case A_FIRSTCMD: 18960786Sps /* 19060786Sps * Skip leading spaces or + signs in the string. 19160786Sps */ 19260786Sps while (*cbuf == '+' || *cbuf == ' ') 19360786Sps cbuf++; 19460786Sps if (every_first_cmd != NULL) 19560786Sps free(every_first_cmd); 19660786Sps if (*cbuf == '\0') 19760786Sps every_first_cmd = NULL; 19860786Sps else 19960786Sps every_first_cmd = save(cbuf); 20060786Sps break; 20160786Sps case A_OPT_TOGGLE: 20260786Sps toggle_option(optchar, cbuf, optflag); 20360786Sps optchar = '\0'; 20460786Sps break; 20560786Sps case A_F_BRACKET: 20660786Sps match_brac(cbuf[0], cbuf[1], 1, number); 20760786Sps break; 20860786Sps case A_B_BRACKET: 20960786Sps match_brac(cbuf[1], cbuf[0], 0, number); 21060786Sps break; 21160786Sps#if EXAMINE 21260786Sps case A_EXAMINE: 21360786Sps if (secure) 21460786Sps break; 21560786Sps edit_list(cbuf); 21660786Sps break; 21760786Sps#endif 21860786Sps#if SHELL_ESCAPE 21960786Sps case A_SHELL: 22060786Sps /* 22160786Sps * !! just uses whatever is in shellcmd. 22260786Sps * Otherwise, copy cmdbuf to shellcmd, 22360786Sps * expanding any special characters ("%" or "#"). 22460786Sps */ 22560786Sps if (*cbuf != '!') 22660786Sps { 22760786Sps if (shellcmd != NULL) 22860786Sps free(shellcmd); 22960786Sps shellcmd = fexpand(cbuf); 23060786Sps } 23160786Sps 23260786Sps if (secure) 23360786Sps break; 23460786Sps if (shellcmd == NULL) 23560786Sps lsystem("", "!done"); 23660786Sps else 23760786Sps lsystem(shellcmd, "!done"); 23860786Sps break; 23960786Sps#endif 24060786Sps#if PIPEC 24160786Sps case A_PIPE: 24260786Sps if (secure) 24360786Sps break; 24460786Sps (void) pipe_mark(pipec, cbuf); 24560786Sps error("|done", NULL_PARG); 24660786Sps break; 24760786Sps#endif 24860786Sps } 24960786Sps} 25060786Sps 25160786Sps/* 25260786Sps * Add a character to a multi-character command. 25360786Sps */ 25460786Sps static int 25560786Spsmca_char(c) 25660786Sps int c; 25760786Sps{ 25860786Sps char *p; 25960786Sps int flag; 26060786Sps char buf[3]; 26160786Sps PARG parg; 26260786Sps 26360786Sps switch (mca) 26460786Sps { 26560786Sps case 0: 26660786Sps /* 26760786Sps * Not in a multicharacter command. 26860786Sps */ 26960786Sps return (NO_MCA); 27060786Sps 27160786Sps case A_PREFIX: 27260786Sps /* 27360786Sps * In the prefix of a command. 27460786Sps * This not considered a multichar command 27560786Sps * (even tho it uses cmdbuf, etc.). 27660786Sps * It is handled in the commands() switch. 27760786Sps */ 27860786Sps return (NO_MCA); 27960786Sps 28060786Sps case A_DIGIT: 28160786Sps /* 28260786Sps * Entering digits of a number. 28360786Sps * Terminated by a non-digit. 28460786Sps */ 28560786Sps if ((c < '0' || c > '9') && 28660786Sps editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE) == A_INVALID) 28760786Sps { 28860786Sps /* 28960786Sps * Not part of the number. 29060786Sps * Treat as a normal command character. 29160786Sps */ 29260786Sps number = cmd_int(); 29360786Sps mca = 0; 29460786Sps cmd_accept(); 29560786Sps return (NO_MCA); 29660786Sps } 29760786Sps break; 29860786Sps 29960786Sps case A_OPT_TOGGLE: 30060786Sps /* 30160786Sps * Special case for the TOGGLE_OPTION command. 30260786Sps * If the option letter which was entered is a 30360786Sps * single-char option, execute the command immediately, 30460786Sps * so user doesn't have to hit RETURN. 30560786Sps * If the first char is + or -, this indicates 30660786Sps * OPT_UNSET or OPT_SET respectively, instead of OPT_TOGGLE. 30760786Sps * "--" begins inputting a long option name. 30860786Sps */ 30960786Sps if (optchar == '\0' && len_cmdbuf() == 0) 31060786Sps { 31160786Sps flag = (optflag & ~OPT_NO_PROMPT); 31260786Sps if (flag == OPT_NO_TOGGLE) 31360786Sps { 31460786Sps switch (c) 31560786Sps { 31660786Sps case '_': 31760786Sps /* "__" = long option name. */ 31860786Sps optgetname = TRUE; 31960786Sps mca_opt_toggle(); 32060786Sps return (MCA_MORE); 32160786Sps } 32260786Sps } else 32360786Sps { 32460786Sps switch (c) 32560786Sps { 32660786Sps case '+': 32760786Sps /* "-+" = UNSET. */ 32860786Sps optflag = (flag == OPT_UNSET) ? 32960786Sps OPT_TOGGLE : OPT_UNSET; 33060786Sps mca_opt_toggle(); 33160786Sps return (MCA_MORE); 33260786Sps case '!': 33360786Sps /* "-!" = SET */ 33460786Sps optflag = (flag == OPT_SET) ? 33560786Sps OPT_TOGGLE : OPT_SET; 33660786Sps mca_opt_toggle(); 33760786Sps return (MCA_MORE); 33860786Sps case CONTROL('P'): 33960786Sps optflag ^= OPT_NO_PROMPT; 34060786Sps mca_opt_toggle(); 34160786Sps return (MCA_MORE); 34260786Sps case '-': 34360786Sps /* "--" = long option name. */ 34460786Sps optgetname = TRUE; 34560786Sps mca_opt_toggle(); 34660786Sps return (MCA_MORE); 34760786Sps } 34860786Sps } 34960786Sps } 35060786Sps if (optgetname) 35160786Sps { 35260786Sps /* 35360786Sps * We're getting a long option name. 35460786Sps * See if we've matched an option name yet. 35560786Sps * If so, display the complete name and stop 35660786Sps * accepting chars until user hits RETURN. 35760786Sps */ 35860786Sps struct option *o; 35960786Sps char *oname; 36060786Sps int lc; 36160786Sps 36260786Sps if (c == '\n' || c == '\r') 36360786Sps { 36460786Sps /* 36560786Sps * When the user hits RETURN, make sure 36660786Sps * we've matched an option name, then 36760786Sps * pretend he just entered the equivalent 36860786Sps * option letter. 36960786Sps */ 37060786Sps if (optchar == '\0') 37160786Sps { 37260786Sps parg.p_string = get_cmdbuf(); 37360786Sps error("There is no --%s option", &parg); 37460786Sps return (MCA_DONE); 37560786Sps } 37660786Sps optgetname = FALSE; 37760786Sps cmd_reset(); 37860786Sps c = optchar; 37960786Sps } else 38060786Sps { 38160786Sps if (optchar != '\0') 38260786Sps { 38360786Sps /* 38460786Sps * Already have a match for the name. 38560786Sps * Don't accept anything but erase/kill. 38660786Sps */ 38760786Sps if (c == erase_char || c == kill_char) 38860786Sps return (MCA_DONE); 38960786Sps return (MCA_MORE); 39060786Sps } 39160786Sps /* 39260786Sps * Add char to cmd buffer and try to match 39360786Sps * the option name. 39460786Sps */ 39560786Sps if (cmd_char(c) == CC_QUIT) 39660786Sps return (MCA_DONE); 39760786Sps p = get_cmdbuf(); 39860786Sps lc = islower(p[0]); 39960786Sps o = findopt_name(&p, &oname, NULL); 40060786Sps if (o != NULL) 40160786Sps { 40260786Sps /* 40360786Sps * Got a match. 40460786Sps * Remember the option letter and 40560786Sps * display the full option name. 40660786Sps */ 40760786Sps optchar = o->oletter; 40860786Sps if (!lc && islower(optchar)) 40960786Sps optchar = toupper(optchar); 41060786Sps cmd_reset(); 41160786Sps mca_opt_toggle(); 41260786Sps for (p = oname; *p != '\0'; p++) 41360786Sps { 41460786Sps c = *p; 41560786Sps if (!lc && islower(c)) 41660786Sps c = toupper(c); 41760786Sps if (cmd_char(c) != CC_OK) 41860786Sps return (MCA_DONE); 41960786Sps } 42060786Sps } 42160786Sps return (MCA_MORE); 42260786Sps } 42360786Sps } else 42460786Sps { 42560786Sps if (c == erase_char || c == kill_char) 42660786Sps break; 42760786Sps if (optchar != '\0') 42860786Sps /* We already have the option letter. */ 42960786Sps break; 43060786Sps } 43160786Sps 43260786Sps optchar = c; 43360786Sps if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE || 43460786Sps single_char_option(c)) 43560786Sps { 43660786Sps toggle_option(c, "", optflag); 43760786Sps return (MCA_DONE); 43860786Sps } 43960786Sps /* 44060786Sps * Display a prompt appropriate for the option letter. 44160786Sps */ 44260786Sps if ((p = opt_prompt(c)) == NULL) 44360786Sps { 44460786Sps buf[0] = '-'; 44560786Sps buf[1] = c; 44660786Sps buf[2] = '\0'; 44760786Sps p = buf; 44860786Sps } 44960786Sps start_mca(A_OPT_TOGGLE, p, (void*)NULL, 0); 45060786Sps return (MCA_MORE); 45160786Sps 45260786Sps case A_F_SEARCH: 45360786Sps case A_B_SEARCH: 45460786Sps /* 45560786Sps * Special case for search commands. 45660786Sps * Certain characters as the first char of 45760786Sps * the pattern have special meaning: 45860786Sps * ! Toggle the NO_MATCH flag 45960786Sps * * Toggle the PAST_EOF flag 46060786Sps * @ Toggle the FIRST_FILE flag 46160786Sps */ 46260786Sps if (len_cmdbuf() > 0) 46360786Sps /* 46460786Sps * Only works for the first char of the pattern. 46560786Sps */ 46660786Sps break; 46760786Sps 46860786Sps flag = 0; 46960786Sps switch (c) 47060786Sps { 47160786Sps case CONTROL('E'): /* ignore END of file */ 47260786Sps case '*': 47360786Sps flag = SRCH_PAST_EOF; 47460786Sps break; 47560786Sps case CONTROL('F'): /* FIRST file */ 47660786Sps case '@': 47760786Sps flag = SRCH_FIRST_FILE; 47860786Sps break; 47960786Sps case CONTROL('K'): /* KEEP position */ 48060786Sps flag = SRCH_NO_MOVE; 48160786Sps break; 48260786Sps case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */ 48360786Sps flag = SRCH_NO_REGEX; 48460786Sps break; 48560786Sps case CONTROL('N'): /* NOT match */ 48660786Sps case '!': 48760786Sps flag = SRCH_NO_MATCH; 48860786Sps break; 48960786Sps } 49060786Sps if (flag != 0) 49160786Sps { 49260786Sps search_type ^= flag; 49360786Sps mca_search(); 49460786Sps return (MCA_MORE); 49560786Sps } 49660786Sps break; 49760786Sps } 49860786Sps 49960786Sps /* 50060786Sps * Any other multicharacter command 50160786Sps * is terminated by a newline. 50260786Sps */ 50360786Sps if (c == '\n' || c == '\r') 50460786Sps { 50560786Sps /* 50660786Sps * Execute the command. 50760786Sps */ 50860786Sps exec_mca(); 50960786Sps return (MCA_DONE); 51060786Sps } 51160786Sps 51260786Sps /* 51360786Sps * Append the char to the command buffer. 51460786Sps */ 51560786Sps if (cmd_char(c) == CC_QUIT) 51660786Sps /* 51760786Sps * Abort the multi-char command. 51860786Sps */ 51960786Sps return (MCA_DONE); 52060786Sps 52160786Sps if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2) 52260786Sps { 52360786Sps /* 52460786Sps * Special case for the bracket-matching commands. 52560786Sps * Execute the command after getting exactly two 52660786Sps * characters from the user. 52760786Sps */ 52860786Sps exec_mca(); 52960786Sps return (MCA_DONE); 53060786Sps } 53160786Sps 53260786Sps /* 53360786Sps * Need another character. 53460786Sps */ 53560786Sps return (MCA_MORE); 53660786Sps} 53760786Sps 53860786Sps/* 53960786Sps * Make sure the screen is displayed. 54060786Sps */ 54160786Sps static void 54260786Spsmake_display() 54360786Sps{ 54460786Sps /* 54560786Sps * If nothing is displayed yet, display starting from initial_scrpos. 54660786Sps */ 54760786Sps if (empty_screen()) 54860786Sps { 54960786Sps if (initial_scrpos.pos == NULL_POSITION) 55060786Sps /* 55160786Sps * {{ Maybe this should be: 55260786Sps * jump_loc(ch_zero(), jump_sline); 55360786Sps * but this behavior seems rather unexpected 55460786Sps * on the first screen. }} 55560786Sps */ 55660786Sps jump_loc(ch_zero(), 1); 55760786Sps else 55860786Sps jump_loc(initial_scrpos.pos, initial_scrpos.ln); 55960786Sps } else if (screen_trashed) 56060786Sps { 56160786Sps int save_top_scroll; 56260786Sps save_top_scroll = top_scroll; 56360786Sps top_scroll = 1; 56460786Sps repaint(); 56560786Sps top_scroll = save_top_scroll; 56660786Sps } 56760786Sps} 56860786Sps 56960786Sps/* 57060786Sps * Display the appropriate prompt. 57160786Sps */ 57260786Sps static void 57360786Spsprompt() 57460786Sps{ 57560786Sps register char *p; 57660786Sps 57760786Sps if (ungotp != NULL && ungotp > ungot) 57860786Sps { 57960786Sps /* 58060786Sps * No prompt necessary if commands are from 58160786Sps * ungotten chars rather than from the user. 58260786Sps */ 58360786Sps return; 58460786Sps } 58560786Sps 58660786Sps /* 58760786Sps * Make sure the screen is displayed. 58860786Sps */ 58960786Sps make_display(); 59060786Sps bottompos = position(BOTTOM_PLUS_ONE); 59160786Sps 59260786Sps /* 59360786Sps * If the -E flag is set and we've hit EOF on the last file, quit. 59460786Sps */ 59560786Sps if ((quit_at_eof == OPT_ONPLUS || quit_if_one_screen) && 59660786Sps hit_eof && !(ch_getflags() & CH_HELPFILE) && 59760786Sps next_ifile(curr_ifile) == NULL_IFILE) 59860786Sps quit(QUIT_OK); 59960786Sps quit_if_one_screen = FALSE; 60060786Sps#if 0 /* This doesn't work well because some "te"s clear the screen. */ 60160786Sps /* 60260786Sps * If the -e flag is set and we've hit EOF on the last file, 60360786Sps * and the file is squished (shorter than the screen), quit. 60460786Sps */ 60560786Sps if (quit_at_eof && squished && 60660786Sps next_ifile(curr_ifile) == NULL_IFILE) 60760786Sps quit(QUIT_OK); 60860786Sps#endif 60960786Sps 61060786Sps /* 61160786Sps * Select the proper prompt and display it. 61260786Sps */ 61360786Sps clear_cmd(); 61460786Sps p = pr_string(); 61560786Sps if (p == NULL) 61660786Sps putchr(':'); 61760786Sps else 61860786Sps { 61960786Sps so_enter(); 62060786Sps putstr(p); 62160786Sps so_exit(); 62260786Sps } 62360786Sps} 62460786Sps 62560786Sps/* 62660786Sps * Display the less version message. 62760786Sps */ 62860786Sps public void 62960786Spsdispversion() 63060786Sps{ 63160786Sps PARG parg; 63260786Sps 63360786Sps parg.p_string = version; 63460786Sps error("less %s", &parg); 63560786Sps} 63660786Sps 63760786Sps/* 63860786Sps * Get command character. 63960786Sps * The character normally comes from the keyboard, 64060786Sps * but may come from ungotten characters 64160786Sps * (characters previously given to ungetcc or ungetsc). 64260786Sps */ 64360786Sps public int 64460786Spsgetcc() 64560786Sps{ 64660786Sps if (ungotp == NULL) 64760786Sps /* 64860786Sps * Normal case: no ungotten chars, so get one from the user. 64960786Sps */ 65060786Sps return (getchr()); 65160786Sps 65260786Sps if (ungotp > ungot) 65360786Sps /* 65460786Sps * Return the next ungotten char. 65560786Sps */ 65660786Sps return (*--ungotp); 65760786Sps 65860786Sps /* 65960786Sps * We have just run out of ungotten chars. 66060786Sps */ 66160786Sps ungotp = NULL; 66260786Sps if (len_cmdbuf() == 0 || !empty_screen()) 66360786Sps return (getchr()); 66460786Sps /* 66560786Sps * Command is incomplete, so try to complete it. 66660786Sps */ 66760786Sps switch (mca) 66860786Sps { 66960786Sps case A_DIGIT: 67060786Sps /* 67160786Sps * We have a number but no command. Treat as #g. 67260786Sps */ 67360786Sps return ('g'); 67460786Sps 67560786Sps case A_F_SEARCH: 67660786Sps case A_B_SEARCH: 67760786Sps /* 67860786Sps * We have "/string" but no newline. Add the \n. 67960786Sps */ 68060786Sps return ('\n'); 68160786Sps 68260786Sps default: 68360786Sps /* 68460786Sps * Some other incomplete command. Let user complete it. 68560786Sps */ 68660786Sps return (getchr()); 68760786Sps } 68860786Sps} 68960786Sps 69060786Sps/* 69160786Sps * "Unget" a command character. 69260786Sps * The next getcc() will return this character. 69360786Sps */ 69460786Sps public void 69560786Spsungetcc(c) 69660786Sps int c; 69760786Sps{ 69860786Sps if (ungotp == NULL) 69960786Sps ungotp = ungot; 70060786Sps if (ungotp >= ungot + sizeof(ungot)) 70160786Sps { 70260786Sps error("ungetcc overflow", NULL_PARG); 70360786Sps quit(QUIT_ERROR); 70460786Sps } 70560786Sps *ungotp++ = c; 70660786Sps} 70760786Sps 70860786Sps/* 70960786Sps * Unget a whole string of command characters. 71060786Sps * The next sequence of getcc()'s will return this string. 71160786Sps */ 71260786Sps public void 71360786Spsungetsc(s) 71460786Sps char *s; 71560786Sps{ 71660786Sps register char *p; 71760786Sps 71860786Sps for (p = s + strlen(s) - 1; p >= s; p--) 71960786Sps ungetcc(*p); 72060786Sps} 72160786Sps 72260786Sps/* 72360786Sps * Search for a pattern, possibly in multiple files. 72460786Sps * If SRCH_FIRST_FILE is set, begin searching at the first file. 72560786Sps * If SRCH_PAST_EOF is set, continue the search thru multiple files. 72660786Sps */ 72760786Sps static void 72860786Spsmulti_search(pattern, n) 72960786Sps char *pattern; 73060786Sps int n; 73160786Sps{ 73260786Sps register int nomore; 73360786Sps IFILE save_ifile; 73460786Sps int changed_file; 73560786Sps 73660786Sps changed_file = 0; 73760786Sps save_ifile = save_curr_ifile(); 73860786Sps 73960786Sps if (search_type & SRCH_FIRST_FILE) 74060786Sps { 74160786Sps /* 74260786Sps * Start at the first (or last) file 74360786Sps * in the command line list. 74460786Sps */ 74560786Sps if (search_type & SRCH_FORW) 74660786Sps nomore = edit_first(); 74760786Sps else 74860786Sps nomore = edit_last(); 74960786Sps if (nomore) 75060786Sps { 75160786Sps unsave_ifile(save_ifile); 75260786Sps return; 75360786Sps } 75460786Sps changed_file = 1; 75560786Sps search_type &= ~SRCH_FIRST_FILE; 75660786Sps } 75760786Sps 75860786Sps for (;;) 75960786Sps { 76060786Sps n = search(search_type, pattern, n); 76160786Sps /* 76260786Sps * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared 76360786Sps * after being used once. This allows "n" to work after 76460786Sps * using a /@@ search. 76560786Sps */ 76660786Sps search_type &= ~SRCH_NO_MOVE; 76760786Sps if (n == 0) 76860786Sps { 76960786Sps /* 77060786Sps * Found it. 77160786Sps */ 77260786Sps unsave_ifile(save_ifile); 77360786Sps return; 77460786Sps } 77560786Sps 77660786Sps if (n < 0) 77760786Sps /* 77860786Sps * Some kind of error in the search. 77960786Sps * Error message has been printed by search(). 78060786Sps */ 78160786Sps break; 78260786Sps 78360786Sps if ((search_type & SRCH_PAST_EOF) == 0) 78460786Sps /* 78560786Sps * We didn't find a match, but we're 78660786Sps * supposed to search only one file. 78760786Sps */ 78860786Sps break; 78960786Sps /* 79060786Sps * Move on to the next file. 79160786Sps */ 79260786Sps if (search_type & SRCH_FORW) 79360786Sps nomore = edit_next(1); 79460786Sps else 79560786Sps nomore = edit_prev(1); 79660786Sps if (nomore) 79760786Sps break; 79860786Sps changed_file = 1; 79960786Sps } 80060786Sps 80160786Sps /* 80260786Sps * Didn't find it. 80360786Sps * Print an error message if we haven't already. 80460786Sps */ 80560786Sps if (n > 0) 80660786Sps error("Pattern not found", NULL_PARG); 80760786Sps 80860786Sps if (changed_file) 80960786Sps { 81060786Sps /* 81160786Sps * Restore the file we were originally viewing. 81260786Sps */ 81360786Sps reedit_ifile(save_ifile); 81460786Sps } 81560786Sps} 81660786Sps 81760786Sps/* 81860786Sps * Main command processor. 81960786Sps * Accept and execute commands until a quit command. 82060786Sps */ 82160786Sps public void 82260786Spscommands() 82360786Sps{ 82460786Sps register int c; 82560786Sps register int action; 82660786Sps register char *cbuf; 82760786Sps int newaction; 82860786Sps int save_search_type; 82960786Sps char *extra; 83060786Sps char tbuf[2]; 83160786Sps PARG parg; 83260786Sps IFILE old_ifile; 83360786Sps IFILE new_ifile; 83460786Sps 83560786Sps search_type = SRCH_FORW; 83660786Sps wscroll = (sc_height + 1) / 2; 83760786Sps newaction = A_NOACTION; 83860786Sps 83960786Sps for (;;) 84060786Sps { 84160786Sps mca = 0; 84260786Sps cmd_accept(); 84360786Sps number = 0; 84460786Sps optchar = '\0'; 84560786Sps 84660786Sps /* 84760786Sps * See if any signals need processing. 84860786Sps */ 84960786Sps if (sigs) 85060786Sps { 85160786Sps psignals(); 85260786Sps if (quitting) 85360786Sps quit(QUIT_SAVED_STATUS); 85460786Sps } 85560786Sps 85660786Sps /* 85760786Sps * See if window size changed, for systems that don't 85860786Sps * generate SIGWINCH. 85960786Sps */ 86060786Sps check_winch(); 86160786Sps 86260786Sps /* 86360786Sps * Display prompt and accept a character. 86460786Sps */ 86560786Sps cmd_reset(); 86660786Sps prompt(); 86760786Sps if (sigs) 86860786Sps continue; 86960786Sps if (newaction == A_NOACTION) 87060786Sps c = getcc(); 87160786Sps 87260786Sps again: 87360786Sps if (sigs) 87460786Sps continue; 87560786Sps 87660786Sps if (newaction != A_NOACTION) 87760786Sps { 87860786Sps action = newaction; 87960786Sps newaction = A_NOACTION; 88060786Sps } else 88160786Sps { 88260786Sps /* 88360786Sps * If we are in a multicharacter command, call mca_char. 88460786Sps * Otherwise we call fcmd_decode to determine the 88560786Sps * action to be performed. 88660786Sps */ 88760786Sps if (mca) 88860786Sps switch (mca_char(c)) 88960786Sps { 89060786Sps case MCA_MORE: 89160786Sps /* 89260786Sps * Need another character. 89360786Sps */ 89460786Sps c = getcc(); 89560786Sps goto again; 89660786Sps case MCA_DONE: 89760786Sps /* 89860786Sps * Command has been handled by mca_char. 89960786Sps * Start clean with a prompt. 90060786Sps */ 90160786Sps continue; 90260786Sps case NO_MCA: 90360786Sps /* 90460786Sps * Not a multi-char command 90560786Sps * (at least, not anymore). 90660786Sps */ 90760786Sps break; 90860786Sps } 90960786Sps 91060786Sps /* 91160786Sps * Decode the command character and decide what to do. 91260786Sps */ 91360786Sps if (mca) 91460786Sps { 91560786Sps /* 91660786Sps * We're in a multichar command. 91760786Sps * Add the character to the command buffer 91860786Sps * and display it on the screen. 91960786Sps * If the user backspaces past the start 92060786Sps * of the line, abort the command. 92160786Sps */ 92260786Sps if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0) 92360786Sps continue; 92460786Sps cbuf = get_cmdbuf(); 92560786Sps } else 92660786Sps { 92760786Sps /* 92860786Sps * Don't use cmd_char if we're starting fresh 92960786Sps * at the beginning of a command, because we 93060786Sps * don't want to echo the command until we know 93160786Sps * it is a multichar command. We also don't 93260786Sps * want erase_char/kill_char to be treated 93360786Sps * as line editing characters. 93460786Sps */ 93560786Sps tbuf[0] = c; 93660786Sps tbuf[1] = '\0'; 93760786Sps cbuf = tbuf; 93860786Sps } 93960786Sps extra = NULL; 94060786Sps action = fcmd_decode(cbuf, &extra); 94160786Sps /* 94260786Sps * If an "extra" string was returned, 94360786Sps * process it as a string of command characters. 94460786Sps */ 94560786Sps if (extra != NULL) 94660786Sps ungetsc(extra); 94760786Sps } 94860786Sps /* 94960786Sps * Clear the cmdbuf string. 95060786Sps * (But not if we're in the prefix of a command, 95160786Sps * because the partial command string is kept there.) 95260786Sps */ 95360786Sps if (action != A_PREFIX) 95460786Sps cmd_reset(); 95560786Sps 95660786Sps switch (action) 95760786Sps { 95860786Sps case A_DIGIT: 95960786Sps /* 96060786Sps * First digit of a number. 96160786Sps */ 96260786Sps start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE); 96360786Sps goto again; 96460786Sps 96560786Sps case A_F_WINDOW: 96660786Sps /* 96760786Sps * Forward one window (and set the window size). 96860786Sps */ 96960786Sps if (number > 0) 97060786Sps swindow = number; 97160786Sps /* FALLTHRU */ 97260786Sps case A_F_SCREEN: 97360786Sps /* 97460786Sps * Forward one screen. 97560786Sps */ 97660786Sps if (number <= 0) 97760786Sps number = get_swindow(); 97860786Sps cmd_exec(); 97960786Sps if (show_attn) 98060786Sps set_attnpos(bottompos); 98160786Sps forward(number, 0, 1); 98260786Sps break; 98360786Sps 98460786Sps case A_B_WINDOW: 98560786Sps /* 98660786Sps * Backward one window (and set the window size). 98760786Sps */ 98860786Sps if (number > 0) 98960786Sps swindow = number; 99060786Sps /* FALLTHRU */ 99160786Sps case A_B_SCREEN: 99260786Sps /* 99360786Sps * Backward one screen. 99460786Sps */ 99560786Sps if (number <= 0) 99660786Sps number = get_swindow(); 99760786Sps cmd_exec(); 99860786Sps backward(number, 0, 1); 99960786Sps break; 100060786Sps 100160786Sps case A_F_LINE: 100260786Sps /* 100360786Sps * Forward N (default 1) line. 100460786Sps */ 100560786Sps if (number <= 0) 100660786Sps number = 1; 100760786Sps cmd_exec(); 100860786Sps if (show_attn == OPT_ONPLUS && number > 1) 100960786Sps set_attnpos(bottompos); 101060786Sps forward(number, 0, 0); 101160786Sps break; 101260786Sps 101360786Sps case A_B_LINE: 101460786Sps /* 101560786Sps * Backward N (default 1) line. 101660786Sps */ 101760786Sps if (number <= 0) 101860786Sps number = 1; 101960786Sps cmd_exec(); 102060786Sps backward(number, 0, 0); 102160786Sps break; 102260786Sps 102360786Sps case A_FF_LINE: 102460786Sps /* 102560786Sps * Force forward N (default 1) line. 102660786Sps */ 102760786Sps if (number <= 0) 102860786Sps number = 1; 102960786Sps cmd_exec(); 103060786Sps if (show_attn == OPT_ONPLUS && number > 1) 103160786Sps set_attnpos(bottompos); 103260786Sps forward(number, 1, 0); 103360786Sps break; 103460786Sps 103560786Sps case A_BF_LINE: 103660786Sps /* 103760786Sps * Force backward N (default 1) line. 103860786Sps */ 103960786Sps if (number <= 0) 104060786Sps number = 1; 104160786Sps cmd_exec(); 104260786Sps backward(number, 1, 0); 104360786Sps break; 104460786Sps 104560786Sps case A_FF_SCREEN: 104660786Sps /* 104760786Sps * Force forward one screen. 104860786Sps */ 104960786Sps if (number <= 0) 105060786Sps number = get_swindow(); 105160786Sps cmd_exec(); 105260786Sps if (show_attn == OPT_ONPLUS) 105360786Sps set_attnpos(bottompos); 105460786Sps forward(number, 1, 0); 105560786Sps break; 105660786Sps 105760786Sps case A_F_FOREVER: 105860786Sps /* 105960786Sps * Forward forever, ignoring EOF. 106060786Sps */ 106160786Sps if (ch_getflags() & CH_HELPFILE) 106260786Sps break; 106360786Sps cmd_exec(); 106460786Sps jump_forw(); 106560786Sps ignore_eoi = 1; 106660786Sps hit_eof = 0; 106760786Sps while (!sigs) 106860786Sps forward(1, 0, 0); 106960786Sps ignore_eoi = 0; 107060786Sps /* 107160786Sps * This gets us back in "F mode" after processing 107260786Sps * a non-abort signal (e.g. window-change). 107360786Sps */ 107460786Sps if (sigs && !ABORT_SIGS()) 107560786Sps newaction = A_F_FOREVER; 107660786Sps break; 107760786Sps 107860786Sps case A_F_SCROLL: 107960786Sps /* 108060786Sps * Forward N lines 108160786Sps * (default same as last 'd' or 'u' command). 108260786Sps */ 108360786Sps if (number > 0) 108460786Sps wscroll = number; 108560786Sps cmd_exec(); 108660786Sps if (show_attn == OPT_ONPLUS) 108760786Sps set_attnpos(bottompos); 108860786Sps forward(wscroll, 0, 0); 108960786Sps break; 109060786Sps 109160786Sps case A_B_SCROLL: 109260786Sps /* 109360786Sps * Forward N lines 109460786Sps * (default same as last 'd' or 'u' command). 109560786Sps */ 109660786Sps if (number > 0) 109760786Sps wscroll = number; 109860786Sps cmd_exec(); 109960786Sps backward(wscroll, 0, 0); 110060786Sps break; 110160786Sps 110260786Sps case A_FREPAINT: 110360786Sps /* 110460786Sps * Flush buffers, then repaint screen. 110560786Sps * Don't flush the buffers on a pipe! 110660786Sps */ 110760786Sps if (ch_getflags() & CH_CANSEEK) 110860786Sps { 110960786Sps ch_flush(); 111060786Sps clr_linenum(); 111160786Sps#if HILITE_SEARCH 111260786Sps clr_hilite(); 111360786Sps#endif 111460786Sps } 111560786Sps /* FALLTHRU */ 111660786Sps case A_REPAINT: 111760786Sps /* 111860786Sps * Repaint screen. 111960786Sps */ 112060786Sps cmd_exec(); 112160786Sps repaint(); 112260786Sps break; 112360786Sps 112460786Sps case A_GOLINE: 112560786Sps /* 112660786Sps * Go to line N, default beginning of file. 112760786Sps */ 112860786Sps if (number <= 0) 112960786Sps number = 1; 113060786Sps cmd_exec(); 113160786Sps jump_back(number); 113260786Sps break; 113360786Sps 113460786Sps case A_PERCENT: 113560786Sps /* 113660786Sps * Go to a specified percentage into the file. 113760786Sps */ 113860786Sps if (number < 0) 113960786Sps number = 0; 114060786Sps if (number > 100) 114160786Sps number = 100; 114260786Sps cmd_exec(); 114360786Sps jump_percent(number); 114460786Sps break; 114560786Sps 114660786Sps case A_GOEND: 114760786Sps /* 114860786Sps * Go to line N, default end of file. 114960786Sps */ 115060786Sps cmd_exec(); 115160786Sps if (number <= 0) 115260786Sps jump_forw(); 115360786Sps else 115460786Sps jump_back(number); 115560786Sps break; 115660786Sps 115760786Sps case A_GOPOS: 115860786Sps /* 115960786Sps * Go to a specified byte position in the file. 116060786Sps */ 116160786Sps cmd_exec(); 116260786Sps if (number < 0) 116360786Sps number = 0; 116460786Sps jump_line_loc((POSITION)number, jump_sline); 116560786Sps break; 116660786Sps 116760786Sps case A_STAT: 116860786Sps /* 116960786Sps * Print file name, etc. 117060786Sps */ 117160786Sps if (ch_getflags() & CH_HELPFILE) 117260786Sps break; 117360786Sps cmd_exec(); 117460786Sps parg.p_string = eq_message(); 117560786Sps error("%s", &parg); 117660786Sps break; 117760786Sps 117860786Sps case A_VERSION: 117960786Sps /* 118060786Sps * Print version number, without the "@(#)". 118160786Sps */ 118260786Sps cmd_exec(); 118360786Sps dispversion(); 118460786Sps break; 118560786Sps 118660786Sps case A_QUIT: 118760786Sps /* 118860786Sps * Exit. 118960786Sps */ 119060786Sps if (curr_ifile != NULL_IFILE && 119160786Sps ch_getflags() & CH_HELPFILE) 119260786Sps { 119360786Sps /* 119460786Sps * Quit while viewing the help file 119560786Sps * just means return to viewing the 119660786Sps * previous file. 119760786Sps */ 119860786Sps if (edit_prev(1) == 0) 119960786Sps break; 120060786Sps } 120160786Sps if (extra != NULL) 120260786Sps quit(*extra); 120360786Sps quit(QUIT_OK); 120460786Sps break; 120560786Sps 120660786Sps/* 120760786Sps * Define abbreviation for a commonly used sequence below. 120860786Sps */ 120960786Sps#define DO_SEARCH() if (number <= 0) number = 1; \ 121060786Sps mca_search(); \ 121160786Sps cmd_exec(); \ 121260786Sps multi_search((char *)NULL, number); 121360786Sps 121460786Sps 121560786Sps case A_F_SEARCH: 121660786Sps /* 121760786Sps * Search forward for a pattern. 121860786Sps * Get the first char of the pattern. 121960786Sps */ 122060786Sps search_type = SRCH_FORW; 122160786Sps if (number <= 0) 122260786Sps number = 1; 122360786Sps mca_search(); 122460786Sps c = getcc(); 122560786Sps goto again; 122660786Sps 122760786Sps case A_B_SEARCH: 122860786Sps /* 122960786Sps * Search backward for a pattern. 123060786Sps * Get the first char of the pattern. 123160786Sps */ 123260786Sps search_type = SRCH_BACK; 123360786Sps if (number <= 0) 123460786Sps number = 1; 123560786Sps mca_search(); 123660786Sps c = getcc(); 123760786Sps goto again; 123860786Sps 123960786Sps case A_AGAIN_SEARCH: 124060786Sps /* 124160786Sps * Repeat previous search. 124260786Sps */ 124360786Sps DO_SEARCH(); 124460786Sps break; 124560786Sps 124660786Sps case A_T_AGAIN_SEARCH: 124760786Sps /* 124860786Sps * Repeat previous search, multiple files. 124960786Sps */ 125060786Sps search_type |= SRCH_PAST_EOF; 125160786Sps DO_SEARCH(); 125260786Sps break; 125360786Sps 125460786Sps case A_REVERSE_SEARCH: 125560786Sps /* 125660786Sps * Repeat previous search, in reverse direction. 125760786Sps */ 125860786Sps save_search_type = search_type; 125960786Sps search_type = SRCH_REVERSE(search_type); 126060786Sps DO_SEARCH(); 126160786Sps search_type = save_search_type; 126260786Sps break; 126360786Sps 126460786Sps case A_T_REVERSE_SEARCH: 126560786Sps /* 126660786Sps * Repeat previous search, 126760786Sps * multiple files in reverse direction. 126860786Sps */ 126960786Sps save_search_type = search_type; 127060786Sps search_type = SRCH_REVERSE(search_type); 127160786Sps search_type |= SRCH_PAST_EOF; 127260786Sps DO_SEARCH(); 127360786Sps search_type = save_search_type; 127460786Sps break; 127560786Sps 127660786Sps case A_UNDO_SEARCH: 127760786Sps undo_search(); 127860786Sps break; 127960786Sps 128060786Sps case A_HELP: 128160786Sps /* 128260786Sps * Help. 128360786Sps */ 128460786Sps if (ch_getflags() & CH_HELPFILE) 128560786Sps break; 128660786Sps cmd_exec(); 128760786Sps (void) edit(FAKE_HELPFILE); 128860786Sps break; 128960786Sps 129060786Sps case A_EXAMINE: 129160786Sps#if EXAMINE 129260786Sps /* 129360786Sps * Edit a new file. Get the filename. 129460786Sps */ 129560786Sps if (secure) 129660786Sps { 129760786Sps error("Command not available", NULL_PARG); 129860786Sps break; 129960786Sps } 130060786Sps start_mca(A_EXAMINE, "Examine: ", ml_examine, 0); 130160786Sps c = getcc(); 130260786Sps goto again; 130360786Sps#else 130460786Sps error("Command not available", NULL_PARG); 130560786Sps break; 130660786Sps#endif 130760786Sps 130860786Sps case A_VISUAL: 130960786Sps /* 131060786Sps * Invoke an editor on the input file. 131160786Sps */ 131260786Sps#if EDITOR 131360786Sps if (secure) 131460786Sps { 131560786Sps error("Command not available", NULL_PARG); 131660786Sps break; 131760786Sps } 131860786Sps if (ch_getflags() & CH_HELPFILE) 131960786Sps break; 132060786Sps if (strcmp(get_filename(curr_ifile), "-") == 0) 132160786Sps { 132260786Sps error("Cannot edit standard input", NULL_PARG); 132360786Sps break; 132460786Sps } 132560786Sps if (curr_altfilename != NULL) 132660786Sps { 132760786Sps error("Cannot edit file processed with LESSOPEN", 132860786Sps NULL_PARG); 132960786Sps break; 133060786Sps } 133160786Sps start_mca(A_SHELL, "!", ml_shell, 0); 133260786Sps /* 133360786Sps * Expand the editor prototype string 133460786Sps * and pass it to the system to execute. 133560786Sps * (Make sure the screen is displayed so the 133660786Sps * expansion of "+%lm" works.) 133760786Sps */ 133860786Sps make_display(); 133960786Sps cmd_exec(); 134060786Sps lsystem(pr_expand(editproto, 0), (char*)NULL); 134160786Sps break; 134260786Sps#else 134360786Sps error("Command not available", NULL_PARG); 134460786Sps break; 134560786Sps#endif 134660786Sps 134760786Sps case A_NEXT_FILE: 134860786Sps /* 134960786Sps * Examine next file. 135060786Sps */ 135160786Sps if (number <= 0) 135260786Sps number = 1; 135360786Sps if (edit_next(number)) 135460786Sps { 135560786Sps if (quit_at_eof && hit_eof && 135660786Sps !(ch_getflags() & CH_HELPFILE)) 135760786Sps quit(QUIT_OK); 135860786Sps parg.p_string = (number > 1) ? "(N-th) " : ""; 135960786Sps error("No %snext file", &parg); 136060786Sps } 136160786Sps break; 136260786Sps 136360786Sps case A_PREV_FILE: 136460786Sps /* 136560786Sps * Examine previous file. 136660786Sps */ 136760786Sps if (number <= 0) 136860786Sps number = 1; 136960786Sps if (edit_prev(number)) 137060786Sps { 137160786Sps parg.p_string = (number > 1) ? "(N-th) " : ""; 137260786Sps error("No %sprevious file", &parg); 137360786Sps } 137460786Sps break; 137560786Sps 137660786Sps case A_INDEX_FILE: 137760786Sps /* 137860786Sps * Examine a particular file. 137960786Sps */ 138060786Sps if (number <= 0) 138160786Sps number = 1; 138260786Sps if (edit_index(number)) 138360786Sps error("No such file", NULL_PARG); 138460786Sps break; 138560786Sps 138660786Sps case A_REMOVE_FILE: 138760786Sps if (ch_getflags() & CH_HELPFILE) 138860786Sps break; 138960786Sps old_ifile = curr_ifile; 139060786Sps new_ifile = getoff_ifile(curr_ifile); 139160786Sps if (new_ifile == NULL_IFILE) 139260786Sps { 139360786Sps bell(); 139460786Sps break; 139560786Sps } 139660786Sps if (edit_ifile(new_ifile) != 0) 139760786Sps { 139860786Sps reedit_ifile(old_ifile); 139960786Sps break; 140060786Sps } 140160786Sps del_ifile(old_ifile); 140260786Sps break; 140360786Sps 140460786Sps case A_OPT_TOGGLE: 140560786Sps optflag = OPT_TOGGLE; 140660786Sps optgetname = FALSE; 140760786Sps mca_opt_toggle(); 140860786Sps c = getcc(); 140960786Sps goto again; 141060786Sps 141160786Sps case A_DISP_OPTION: 141260786Sps /* 141360786Sps * Report a flag setting. 141460786Sps */ 141560786Sps optflag = OPT_NO_TOGGLE; 141660786Sps optgetname = FALSE; 141760786Sps mca_opt_toggle(); 141860786Sps c = getcc(); 141960786Sps goto again; 142060786Sps 142160786Sps case A_FIRSTCMD: 142260786Sps /* 142360786Sps * Set an initial command for new files. 142460786Sps */ 142560786Sps start_mca(A_FIRSTCMD, "+", (void*)NULL, 0); 142660786Sps c = getcc(); 142760786Sps goto again; 142860786Sps 142960786Sps case A_SHELL: 143060786Sps /* 143160786Sps * Shell escape. 143260786Sps */ 143360786Sps#if SHELL_ESCAPE 143460786Sps if (secure) 143560786Sps { 143660786Sps error("Command not available", NULL_PARG); 143760786Sps break; 143860786Sps } 143960786Sps start_mca(A_SHELL, "!", ml_shell, 0); 144060786Sps c = getcc(); 144160786Sps goto again; 144260786Sps#else 144360786Sps error("Command not available", NULL_PARG); 144460786Sps break; 144560786Sps#endif 144660786Sps 144760786Sps case A_SETMARK: 144860786Sps /* 144960786Sps * Set a mark. 145060786Sps */ 145160786Sps if (ch_getflags() & CH_HELPFILE) 145260786Sps break; 145360786Sps start_mca(A_SETMARK, "mark: ", (void*)NULL, 0); 145460786Sps c = getcc(); 145560786Sps if (c == erase_char || c == kill_char || 145660786Sps c == '\n' || c == '\r') 145760786Sps break; 145860786Sps setmark(c); 145960786Sps break; 146060786Sps 146160786Sps case A_GOMARK: 146260786Sps /* 146360786Sps * Go to a mark. 146460786Sps */ 146560786Sps start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0); 146660786Sps c = getcc(); 146760786Sps if (c == erase_char || c == kill_char || 146860786Sps c == '\n' || c == '\r') 146960786Sps break; 147060786Sps gomark(c); 147160786Sps break; 147260786Sps 147360786Sps case A_PIPE: 147460786Sps#if PIPEC 147560786Sps if (secure) 147660786Sps { 147760786Sps error("Command not available", NULL_PARG); 147860786Sps break; 147960786Sps } 148060786Sps start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); 148160786Sps c = getcc(); 148260786Sps if (c == erase_char || c == kill_char) 148360786Sps break; 148460786Sps if (c == '\n' || c == '\r') 148560786Sps c = '.'; 148660786Sps if (badmark(c)) 148760786Sps break; 148860786Sps pipec = c; 148960786Sps start_mca(A_PIPE, "!", ml_shell, 0); 149060786Sps c = getcc(); 149160786Sps goto again; 149260786Sps#else 149360786Sps error("Command not available", NULL_PARG); 149460786Sps break; 149560786Sps#endif 149660786Sps 149760786Sps case A_B_BRACKET: 149860786Sps case A_F_BRACKET: 149960786Sps start_mca(action, "Brackets: ", (void*)NULL, 0); 150060786Sps c = getcc(); 150160786Sps goto again; 150260786Sps 150360786Sps case A_LSHIFT: 150460786Sps if (number <= 0) 150560786Sps number = 8; 150660786Sps if (number > hshift) 150760786Sps number = hshift; 150860786Sps hshift -= number; 150960786Sps screen_trashed = 1; 151060786Sps break; 151160786Sps 151260786Sps case A_RSHIFT: 151360786Sps if (number <= 0) 151460786Sps number = 8; 151560786Sps hshift += number; 151660786Sps screen_trashed = 1; 151760786Sps break; 151860786Sps 151960786Sps case A_PREFIX: 152060786Sps /* 152160786Sps * The command is incomplete (more chars are needed). 152260786Sps * Display the current char, so the user knows 152360786Sps * what's going on, and get another character. 152460786Sps */ 152560786Sps if (mca != A_PREFIX) 152660786Sps { 152760786Sps cmd_reset(); 152860786Sps start_mca(A_PREFIX, " ", (void*)NULL, 152960786Sps CF_QUIT_ON_ERASE); 153060786Sps (void) cmd_char(c); 153160786Sps } 153260786Sps c = getcc(); 153360786Sps goto again; 153460786Sps 153560786Sps case A_NOACTION: 153660786Sps break; 153760786Sps 153860786Sps default: 153960786Sps bell(); 154060786Sps break; 154160786Sps } 154260786Sps } 154360786Sps} 1544