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