command.c revision 173685
160812Sps/* $FreeBSD: head/contrib/less/command.c 173685 2007-11-16 22:24:31Z delphij $ */ 260786Sps/* 3170259Sdelphij * Copyright (C) 1984-2007 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 25161478Sdelphijextern int erase_char, erase2_char, kill_char; 2660786Spsextern int sigs; 2760786Spsextern int quit_if_one_screen; 2860786Spsextern int squished; 2960786Spsextern int hit_eof; 3060786Spsextern int sc_width; 3160786Spsextern int sc_height; 3260786Spsextern int swindow; 3360786Spsextern int jump_sline; 3460786Spsextern int quitting; 3560786Spsextern int wscroll; 3660786Spsextern int top_scroll; 3760786Spsextern int ignore_eoi; 3860786Spsextern int secure; 3960786Spsextern int hshift; 4060786Spsextern int show_attn; 41170259Sdelphijextern int less_is_more; 4260786Spsextern char *every_first_cmd; 4360786Spsextern char *curr_altfilename; 4460786Spsextern char version[]; 4560786Spsextern struct scrpos initial_scrpos; 4660786Spsextern IFILE curr_ifile; 4760786Spsextern void constant *ml_search; 4860786Spsextern void constant *ml_examine; 4960786Sps#if SHELL_ESCAPE || PIPEC 5060786Spsextern void constant *ml_shell; 5160786Sps#endif 5260786Sps#if EDITOR 5360786Spsextern char *editor; 5460786Spsextern char *editproto; 5560786Sps#endif 5660786Spsextern int screen_trashed; /* The screen has been overwritten */ 5763131Spsextern int shift_count; 58170259Sdelphijextern int oldbot; 59170259Sdelphijextern int forw_prompt; 6060786Sps 6160786Spsstatic char ungot[UNGOT_SIZE]; 6260786Spsstatic char *ungotp = NULL; 6360786Sps#if SHELL_ESCAPE 6460786Spsstatic char *shellcmd = NULL; /* For holding last shell command for "!!" */ 6560786Sps#endif 6660786Spsstatic int mca; /* The multicharacter command (action) */ 6760786Spsstatic int search_type; /* The previous type of search */ 68128348Stjrstatic LINENUM number; /* The number typed by the user */ 69170259Sdelphijstatic long fraction; /* The fractional part of the number */ 7060786Spsstatic char optchar; 7160786Spsstatic int optflag; 7260786Spsstatic int optgetname; 7360786Spsstatic POSITION bottompos; 74161478Sdelphijstatic int save_hshift; 7560786Sps#if PIPEC 7660786Spsstatic char pipec; 7760786Sps#endif 7860786Sps 7960786Spsstatic void multi_search(); 8060786Sps 8160786Sps/* 82170259Sdelphij * Move the cursor to start of prompt line before executing a command. 8360786Sps * This looks nicer if the command takes a long time before 8460786Sps * updating the screen. 8560786Sps */ 8660786Sps static void 8760786Spscmd_exec() 8860786Sps{ 8960786Sps clear_attn(); 90170967Sdelphij clear_bot(); 9160786Sps flush(); 9260786Sps} 9360786Sps 9460786Sps/* 9560786Sps * Set up the display to start a new multi-character command. 9660786Sps */ 9760786Sps static void 9860786Spsstart_mca(action, prompt, mlist, cmdflags) 9960786Sps int action; 10060786Sps char *prompt; 10160786Sps void *mlist; 10260786Sps int cmdflags; 10360786Sps{ 10460786Sps mca = action; 105170259Sdelphij clear_bot(); 10660786Sps clear_cmd(); 10760786Sps cmd_putstr(prompt); 10860786Sps set_mlist(mlist, cmdflags); 10960786Sps} 11060786Sps 11160786Sps public int 11260786Spsin_mca() 11360786Sps{ 11460786Sps return (mca != 0 && mca != A_PREFIX); 11560786Sps} 11660786Sps 11760786Sps/* 11860786Sps * Set up the display to start a new search command. 11960786Sps */ 12060786Sps static void 12160786Spsmca_search() 12260786Sps{ 12360786Sps if (search_type & SRCH_FORW) 12460786Sps mca = A_F_SEARCH; 12560786Sps else 12660786Sps mca = A_B_SEARCH; 12760786Sps 128170259Sdelphij clear_bot(); 12960786Sps clear_cmd(); 13060786Sps 13160786Sps if (search_type & SRCH_NO_MATCH) 13260786Sps cmd_putstr("Non-match "); 13360786Sps if (search_type & SRCH_FIRST_FILE) 13460786Sps cmd_putstr("First-file "); 13560786Sps if (search_type & SRCH_PAST_EOF) 13660786Sps cmd_putstr("EOF-ignore "); 13760786Sps if (search_type & SRCH_NO_MOVE) 13860786Sps cmd_putstr("Keep-pos "); 13960786Sps if (search_type & SRCH_NO_REGEX) 14060786Sps cmd_putstr("Regex-off "); 14160786Sps 14260786Sps if (search_type & SRCH_FORW) 14360786Sps cmd_putstr("/"); 14460786Sps else 14560786Sps cmd_putstr("?"); 14660786Sps set_mlist(ml_search, 0); 14760786Sps} 14860786Sps 14960786Sps/* 15060786Sps * Set up the display to start a new toggle-option command. 15160786Sps */ 15260786Sps static void 15360786Spsmca_opt_toggle() 15460786Sps{ 15560786Sps int no_prompt; 15660786Sps int flag; 15760786Sps char *dash; 15860786Sps 15960786Sps no_prompt = (optflag & OPT_NO_PROMPT); 16060786Sps flag = (optflag & ~OPT_NO_PROMPT); 16160786Sps dash = (flag == OPT_NO_TOGGLE) ? "_" : "-"; 16260786Sps 16360786Sps mca = A_OPT_TOGGLE; 164170259Sdelphij clear_bot(); 16560786Sps clear_cmd(); 16660786Sps cmd_putstr(dash); 16760786Sps if (optgetname) 16860786Sps cmd_putstr(dash); 16960786Sps if (no_prompt) 17060786Sps cmd_putstr("(P)"); 17160786Sps switch (flag) 17260786Sps { 17360786Sps case OPT_UNSET: 17460786Sps cmd_putstr("+"); 17560786Sps break; 17660786Sps case OPT_SET: 17760786Sps cmd_putstr("!"); 17860786Sps break; 17960786Sps } 18060786Sps set_mlist(NULL, 0); 18160786Sps} 18260786Sps 18360786Sps/* 18460786Sps * Execute a multicharacter command. 18560786Sps */ 18660786Sps static void 18760786Spsexec_mca() 18860786Sps{ 18960786Sps register char *cbuf; 19060786Sps 19160786Sps cmd_exec(); 19260786Sps cbuf = get_cmdbuf(); 19360786Sps 19460786Sps switch (mca) 19560786Sps { 19660786Sps case A_F_SEARCH: 19760786Sps case A_B_SEARCH: 198128348Stjr multi_search(cbuf, (int) number); 19960786Sps break; 20060786Sps case A_FIRSTCMD: 20160786Sps /* 20260786Sps * Skip leading spaces or + signs in the string. 20360786Sps */ 20460786Sps while (*cbuf == '+' || *cbuf == ' ') 20560786Sps cbuf++; 20660786Sps if (every_first_cmd != NULL) 20760786Sps free(every_first_cmd); 20860786Sps if (*cbuf == '\0') 20960786Sps every_first_cmd = NULL; 21060786Sps else 21160786Sps every_first_cmd = save(cbuf); 21260786Sps break; 21360786Sps case A_OPT_TOGGLE: 21460786Sps toggle_option(optchar, cbuf, optflag); 21560786Sps optchar = '\0'; 21660786Sps break; 21760786Sps case A_F_BRACKET: 218128348Stjr match_brac(cbuf[0], cbuf[1], 1, (int) number); 21960786Sps break; 22060786Sps case A_B_BRACKET: 221128348Stjr match_brac(cbuf[1], cbuf[0], 0, (int) number); 22260786Sps break; 22360786Sps#if EXAMINE 22460786Sps case A_EXAMINE: 22560786Sps if (secure) 22660786Sps break; 22760786Sps edit_list(cbuf); 228128348Stjr#if TAGS 22989022Sps /* If tag structure is loaded then clean it up. */ 23089022Sps cleantags(); 231128348Stjr#endif 23260786Sps break; 23360786Sps#endif 23460786Sps#if SHELL_ESCAPE 23560786Sps case A_SHELL: 23660786Sps /* 23760786Sps * !! just uses whatever is in shellcmd. 23860786Sps * Otherwise, copy cmdbuf to shellcmd, 23960786Sps * expanding any special characters ("%" or "#"). 24060786Sps */ 24160786Sps if (*cbuf != '!') 24260786Sps { 24360786Sps if (shellcmd != NULL) 24460786Sps free(shellcmd); 24560786Sps shellcmd = fexpand(cbuf); 24660786Sps } 24760786Sps 24860786Sps if (secure) 24960786Sps break; 25060786Sps if (shellcmd == NULL) 25160786Sps lsystem("", "!done"); 25260786Sps else 25360786Sps lsystem(shellcmd, "!done"); 25460786Sps break; 25560786Sps#endif 25660786Sps#if PIPEC 25760786Sps case A_PIPE: 25860786Sps if (secure) 25960786Sps break; 26060786Sps (void) pipe_mark(pipec, cbuf); 26160786Sps error("|done", NULL_PARG); 26260786Sps break; 26360786Sps#endif 26460786Sps } 26560786Sps} 26660786Sps 26760786Sps/* 26860786Sps * Add a character to a multi-character command. 26960786Sps */ 27060786Sps static int 27160786Spsmca_char(c) 27260786Sps int c; 27360786Sps{ 27460786Sps char *p; 27560786Sps int flag; 27660786Sps char buf[3]; 27760786Sps PARG parg; 27860786Sps 27960786Sps switch (mca) 28060786Sps { 28160786Sps case 0: 28260786Sps /* 28360786Sps * Not in a multicharacter command. 28460786Sps */ 28560786Sps return (NO_MCA); 28660786Sps 28760786Sps case A_PREFIX: 28860786Sps /* 28960786Sps * In the prefix of a command. 29060786Sps * This not considered a multichar command 29160786Sps * (even tho it uses cmdbuf, etc.). 29260786Sps * It is handled in the commands() switch. 29360786Sps */ 29460786Sps return (NO_MCA); 29560786Sps 29660786Sps case A_DIGIT: 29760786Sps /* 29860786Sps * Entering digits of a number. 29960786Sps * Terminated by a non-digit. 30060786Sps */ 301170259Sdelphij if (!((c >= '0' && c <= '9') || c == '.') && 30289022Sps editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID) 30360786Sps { 30460786Sps /* 30560786Sps * Not part of the number. 30660786Sps * Treat as a normal command character. 30760786Sps */ 308170259Sdelphij number = cmd_int(&fraction); 30960786Sps mca = 0; 31060786Sps cmd_accept(); 31160786Sps return (NO_MCA); 31260786Sps } 31360786Sps break; 31460786Sps 31560786Sps case A_OPT_TOGGLE: 31660786Sps /* 31760786Sps * Special case for the TOGGLE_OPTION command. 31860786Sps * If the option letter which was entered is a 31960786Sps * single-char option, execute the command immediately, 32060786Sps * so user doesn't have to hit RETURN. 32160786Sps * If the first char is + or -, this indicates 32260786Sps * OPT_UNSET or OPT_SET respectively, instead of OPT_TOGGLE. 32360786Sps * "--" begins inputting a long option name. 32460786Sps */ 32560786Sps if (optchar == '\0' && len_cmdbuf() == 0) 32660786Sps { 32760786Sps flag = (optflag & ~OPT_NO_PROMPT); 32860786Sps if (flag == OPT_NO_TOGGLE) 32960786Sps { 33060786Sps switch (c) 33160786Sps { 33260786Sps case '_': 33360786Sps /* "__" = long option name. */ 33460786Sps optgetname = TRUE; 33560786Sps mca_opt_toggle(); 33660786Sps return (MCA_MORE); 33760786Sps } 33860786Sps } else 33960786Sps { 34060786Sps switch (c) 34160786Sps { 34260786Sps case '+': 34360786Sps /* "-+" = UNSET. */ 34460786Sps optflag = (flag == OPT_UNSET) ? 34560786Sps OPT_TOGGLE : OPT_UNSET; 34660786Sps mca_opt_toggle(); 34760786Sps return (MCA_MORE); 34860786Sps case '!': 34960786Sps /* "-!" = SET */ 35060786Sps optflag = (flag == OPT_SET) ? 35160786Sps OPT_TOGGLE : OPT_SET; 35260786Sps mca_opt_toggle(); 35360786Sps return (MCA_MORE); 35460786Sps case CONTROL('P'): 35560786Sps optflag ^= OPT_NO_PROMPT; 35660786Sps mca_opt_toggle(); 35760786Sps return (MCA_MORE); 35860786Sps case '-': 35960786Sps /* "--" = long option name. */ 36060786Sps optgetname = TRUE; 36160786Sps mca_opt_toggle(); 36260786Sps return (MCA_MORE); 36360786Sps } 36460786Sps } 36560786Sps } 36660786Sps if (optgetname) 36760786Sps { 36860786Sps /* 36960786Sps * We're getting a long option name. 37060786Sps * See if we've matched an option name yet. 37160786Sps * If so, display the complete name and stop 37260786Sps * accepting chars until user hits RETURN. 37360786Sps */ 374128348Stjr struct loption *o; 37560786Sps char *oname; 37660786Sps int lc; 37760786Sps 37860786Sps if (c == '\n' || c == '\r') 37960786Sps { 38060786Sps /* 38160786Sps * When the user hits RETURN, make sure 38260786Sps * we've matched an option name, then 38360786Sps * pretend he just entered the equivalent 38460786Sps * option letter. 38560786Sps */ 38660786Sps if (optchar == '\0') 38760786Sps { 38860786Sps parg.p_string = get_cmdbuf(); 38960786Sps error("There is no --%s option", &parg); 39060786Sps return (MCA_DONE); 39160786Sps } 39260786Sps optgetname = FALSE; 39360786Sps cmd_reset(); 39460786Sps c = optchar; 39560786Sps } else 39660786Sps { 39760786Sps if (optchar != '\0') 39860786Sps { 39960786Sps /* 40060786Sps * Already have a match for the name. 40160786Sps * Don't accept anything but erase/kill. 40260786Sps */ 403161478Sdelphij if (c == erase_char || 404161478Sdelphij c == erase2_char || 405161478Sdelphij c == kill_char) 40660786Sps return (MCA_DONE); 40760786Sps return (MCA_MORE); 40860786Sps } 40960786Sps /* 41060786Sps * Add char to cmd buffer and try to match 41160786Sps * the option name. 41260786Sps */ 41360786Sps if (cmd_char(c) == CC_QUIT) 41460786Sps return (MCA_DONE); 41560786Sps p = get_cmdbuf(); 416161478Sdelphij lc = ASCII_IS_LOWER(p[0]); 41760786Sps o = findopt_name(&p, &oname, NULL); 41860786Sps if (o != NULL) 41960786Sps { 42060786Sps /* 42160786Sps * Got a match. 42260786Sps * Remember the option letter and 42360786Sps * display the full option name. 42460786Sps */ 42560786Sps optchar = o->oletter; 426161478Sdelphij if (!lc && ASCII_IS_LOWER(optchar)) 427161478Sdelphij optchar = ASCII_TO_UPPER(optchar); 42860786Sps cmd_reset(); 42960786Sps mca_opt_toggle(); 43060786Sps for (p = oname; *p != '\0'; p++) 43160786Sps { 43260786Sps c = *p; 433161478Sdelphij if (!lc && ASCII_IS_LOWER(c)) 434161478Sdelphij c = ASCII_TO_UPPER(c); 43560786Sps if (cmd_char(c) != CC_OK) 43660786Sps return (MCA_DONE); 43760786Sps } 43860786Sps } 43960786Sps return (MCA_MORE); 44060786Sps } 44160786Sps } else 44260786Sps { 443161478Sdelphij if (c == erase_char || c == erase2_char || c == kill_char) 44460786Sps break; 44560786Sps if (optchar != '\0') 44660786Sps /* We already have the option letter. */ 44760786Sps break; 44860786Sps } 44960786Sps 45060786Sps optchar = c; 45160786Sps if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE || 45260786Sps single_char_option(c)) 45360786Sps { 45460786Sps toggle_option(c, "", optflag); 45560786Sps return (MCA_DONE); 45660786Sps } 45760786Sps /* 45860786Sps * Display a prompt appropriate for the option letter. 45960786Sps */ 46060786Sps if ((p = opt_prompt(c)) == NULL) 46160786Sps { 46260786Sps buf[0] = '-'; 46360786Sps buf[1] = c; 46460786Sps buf[2] = '\0'; 46560786Sps p = buf; 46660786Sps } 46760786Sps start_mca(A_OPT_TOGGLE, p, (void*)NULL, 0); 46860786Sps return (MCA_MORE); 46960786Sps 47060786Sps case A_F_SEARCH: 47160786Sps case A_B_SEARCH: 47260786Sps /* 47360786Sps * Special case for search commands. 47460786Sps * Certain characters as the first char of 47560786Sps * the pattern have special meaning: 47660786Sps * ! Toggle the NO_MATCH flag 47760786Sps * * Toggle the PAST_EOF flag 47860786Sps * @ Toggle the FIRST_FILE flag 47960786Sps */ 48060786Sps if (len_cmdbuf() > 0) 48160786Sps /* 48260786Sps * Only works for the first char of the pattern. 48360786Sps */ 48460786Sps break; 48560786Sps 48660786Sps flag = 0; 48760786Sps switch (c) 48860786Sps { 48960812Sps case '*': 490170259Sdelphij if (less_is_more) 49160812Sps break; 49260786Sps case CONTROL('E'): /* ignore END of file */ 49360786Sps flag = SRCH_PAST_EOF; 49460786Sps break; 49560812Sps case '@': 496170259Sdelphij if (less_is_more) 49760812Sps break; 49860786Sps case CONTROL('F'): /* FIRST file */ 49960786Sps flag = SRCH_FIRST_FILE; 50060786Sps break; 50160786Sps case CONTROL('K'): /* KEEP position */ 50260786Sps flag = SRCH_NO_MOVE; 50360786Sps break; 50460786Sps case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */ 50560786Sps flag = SRCH_NO_REGEX; 50660786Sps break; 50760786Sps case CONTROL('N'): /* NOT match */ 50860786Sps case '!': 50960786Sps flag = SRCH_NO_MATCH; 51060786Sps break; 51160786Sps } 51260786Sps if (flag != 0) 51360786Sps { 51460786Sps search_type ^= flag; 51560786Sps mca_search(); 51660786Sps return (MCA_MORE); 51760786Sps } 51860786Sps break; 51960786Sps } 52060786Sps 52160786Sps /* 52260786Sps * Any other multicharacter command 52360786Sps * is terminated by a newline. 52460786Sps */ 52560786Sps if (c == '\n' || c == '\r') 52660786Sps { 52760786Sps /* 52860786Sps * Execute the command. 52960786Sps */ 53060786Sps exec_mca(); 53160786Sps return (MCA_DONE); 53260786Sps } 53360786Sps 53460786Sps /* 53560786Sps * Append the char to the command buffer. 53660786Sps */ 53760786Sps if (cmd_char(c) == CC_QUIT) 53860786Sps /* 53960786Sps * Abort the multi-char command. 54060786Sps */ 54160786Sps return (MCA_DONE); 54260786Sps 54360786Sps if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2) 54460786Sps { 54560786Sps /* 54660786Sps * Special case for the bracket-matching commands. 54760786Sps * Execute the command after getting exactly two 54860786Sps * characters from the user. 54960786Sps */ 55060786Sps exec_mca(); 55160786Sps return (MCA_DONE); 55260786Sps } 55360786Sps 55460786Sps /* 55560786Sps * Need another character. 55660786Sps */ 55760786Sps return (MCA_MORE); 55860786Sps} 55960786Sps 56060786Sps/* 561173685Sdelphij * Discard any buffered file data. 562173685Sdelphij */ 563173685Sdelphij static void 564173685Sdelphijclear_buffers() 565173685Sdelphij{ 566173685Sdelphij if (!(ch_getflags() & CH_CANSEEK)) 567173685Sdelphij return; 568173685Sdelphij ch_flush(); 569173685Sdelphij clr_linenum(); 570173685Sdelphij#if HILITE_SEARCH 571173685Sdelphij clr_hilite(); 572173685Sdelphij#endif 573173685Sdelphij} 574173685Sdelphij 575173685Sdelphij/* 57660786Sps * Make sure the screen is displayed. 57760786Sps */ 57860786Sps static void 57960786Spsmake_display() 58060786Sps{ 58160786Sps /* 58260786Sps * If nothing is displayed yet, display starting from initial_scrpos. 58360786Sps */ 58460786Sps if (empty_screen()) 58560786Sps { 58660786Sps if (initial_scrpos.pos == NULL_POSITION) 58760786Sps /* 58860786Sps * {{ Maybe this should be: 58960786Sps * jump_loc(ch_zero(), jump_sline); 59060786Sps * but this behavior seems rather unexpected 59160786Sps * on the first screen. }} 59260786Sps */ 59360786Sps jump_loc(ch_zero(), 1); 59460786Sps else 59560786Sps jump_loc(initial_scrpos.pos, initial_scrpos.ln); 59660786Sps } else if (screen_trashed) 59760786Sps { 598173685Sdelphij int save_top_scroll = top_scroll; 599173685Sdelphij int save_ignore_eoi = ignore_eoi; 60060786Sps top_scroll = 1; 601173685Sdelphij ignore_eoi = 0; 602173685Sdelphij if (screen_trashed == 2) 603173685Sdelphij { 604173685Sdelphij /* Special case used by ignore_eoi: re-open the input file 605173685Sdelphij * and jump to the end of the file. */ 606173685Sdelphij reopen_curr_ifile(); 607173685Sdelphij jump_forw(); 608173685Sdelphij } 60960786Sps repaint(); 61060786Sps top_scroll = save_top_scroll; 611173685Sdelphij ignore_eoi = save_ignore_eoi; 61260786Sps } 61360786Sps} 61460786Sps 61560786Sps/* 61660786Sps * Display the appropriate prompt. 61760786Sps */ 61860786Sps static void 61960786Spsprompt() 62060786Sps{ 62160786Sps register char *p; 62260786Sps 62360786Sps if (ungotp != NULL && ungotp > ungot) 62460786Sps { 62560786Sps /* 62660786Sps * No prompt necessary if commands are from 62760786Sps * ungotten chars rather than from the user. 62860786Sps */ 62960786Sps return; 63060786Sps } 63160786Sps 63260786Sps /* 63360786Sps * Make sure the screen is displayed. 63460786Sps */ 63560786Sps make_display(); 63660786Sps bottompos = position(BOTTOM_PLUS_ONE); 63760786Sps 63860786Sps /* 639161478Sdelphij * If we've hit EOF on the last file, and the -E flag is set 640161478Sdelphij * (or -F is set and this is the first prompt), then quit. 641161478Sdelphij * {{ Relying on "first prompt" to detect a single-screen file 642161478Sdelphij * fails if +G is used, for example. }} 64360786Sps */ 644170259Sdelphij if ((get_quit_at_eof() == OPT_ONPLUS || quit_if_one_screen) && 64560786Sps hit_eof && !(ch_getflags() & CH_HELPFILE) && 64660786Sps next_ifile(curr_ifile) == NULL_IFILE) 64760786Sps quit(QUIT_OK); 64860786Sps quit_if_one_screen = FALSE; 64960786Sps#if 0 /* This doesn't work well because some "te"s clear the screen. */ 65060786Sps /* 65160786Sps * If the -e flag is set and we've hit EOF on the last file, 65260786Sps * and the file is squished (shorter than the screen), quit. 65360786Sps */ 654170259Sdelphij if (get_quit_at_eof() && squished && 65560786Sps next_ifile(curr_ifile) == NULL_IFILE) 65660786Sps quit(QUIT_OK); 65760786Sps#endif 65860786Sps 65989022Sps#if MSDOS_COMPILER==WIN32C 66089022Sps /* 66189022Sps * In Win32, display the file name in the window title. 66289022Sps */ 66389022Sps if (!(ch_getflags() & CH_HELPFILE)) 66489022Sps SetConsoleTitle(pr_expand("Less?f - %f.", 0)); 66589022Sps#endif 66660786Sps /* 66760786Sps * Select the proper prompt and display it. 66860786Sps */ 669170259Sdelphij /* 670170259Sdelphij * If the previous action was a forward movement, 671170259Sdelphij * don't clear the bottom line of the display; 672170259Sdelphij * just print the prompt since the forward movement guarantees 673170259Sdelphij * that we're in the right position to display the prompt. 674170259Sdelphij * Clearing the line could cause a problem: for example, if the last 675170259Sdelphij * line displayed ended at the right screen edge without a newline, 676170259Sdelphij * then clearing would clear the last displayed line rather than 677170259Sdelphij * the prompt line. 678170259Sdelphij */ 679170259Sdelphij if (!forw_prompt) 680170259Sdelphij clear_bot(); 68160786Sps clear_cmd(); 682170259Sdelphij forw_prompt = 0; 68360786Sps p = pr_string(); 684161478Sdelphij if (p == NULL || *p == '\0') 68560786Sps putchr(':'); 68660786Sps else 68760786Sps { 688161478Sdelphij at_enter(AT_STANDOUT); 68960786Sps putstr(p); 690161478Sdelphij at_exit(); 69160786Sps } 692170259Sdelphij clear_eol(); 69360786Sps} 69460786Sps 69560786Sps/* 69660786Sps * Display the less version message. 69760786Sps */ 69860786Sps public void 69960786Spsdispversion() 70060786Sps{ 70160786Sps PARG parg; 70260786Sps 70360786Sps parg.p_string = version; 70460786Sps error("less %s", &parg); 70560786Sps} 70660786Sps 70760786Sps/* 70860786Sps * Get command character. 70960786Sps * The character normally comes from the keyboard, 71060786Sps * but may come from ungotten characters 71160786Sps * (characters previously given to ungetcc or ungetsc). 71260786Sps */ 71360786Sps public int 71460786Spsgetcc() 71560786Sps{ 71660786Sps if (ungotp == NULL) 71760786Sps /* 71860786Sps * Normal case: no ungotten chars, so get one from the user. 71960786Sps */ 72060786Sps return (getchr()); 72160786Sps 72260786Sps if (ungotp > ungot) 72360786Sps /* 72460786Sps * Return the next ungotten char. 72560786Sps */ 72660786Sps return (*--ungotp); 72760786Sps 72860786Sps /* 72960786Sps * We have just run out of ungotten chars. 73060786Sps */ 73160786Sps ungotp = NULL; 73260786Sps if (len_cmdbuf() == 0 || !empty_screen()) 73360786Sps return (getchr()); 73460786Sps /* 73560786Sps * Command is incomplete, so try to complete it. 73660786Sps */ 73760786Sps switch (mca) 73860786Sps { 73960786Sps case A_DIGIT: 74060786Sps /* 74160786Sps * We have a number but no command. Treat as #g. 74260786Sps */ 74360786Sps return ('g'); 74460786Sps 74560786Sps case A_F_SEARCH: 74660786Sps case A_B_SEARCH: 74760786Sps /* 74860786Sps * We have "/string" but no newline. Add the \n. 74960786Sps */ 75060786Sps return ('\n'); 75160786Sps 75260786Sps default: 75360786Sps /* 75460786Sps * Some other incomplete command. Let user complete it. 75560786Sps */ 75660786Sps return (getchr()); 75760786Sps } 75860786Sps} 75960786Sps 76060786Sps/* 76160786Sps * "Unget" a command character. 76260786Sps * The next getcc() will return this character. 76360786Sps */ 76460786Sps public void 76560786Spsungetcc(c) 76660786Sps int c; 76760786Sps{ 76860786Sps if (ungotp == NULL) 76960786Sps ungotp = ungot; 77060786Sps if (ungotp >= ungot + sizeof(ungot)) 77160786Sps { 77260786Sps error("ungetcc overflow", NULL_PARG); 77360786Sps quit(QUIT_ERROR); 77460786Sps } 77560786Sps *ungotp++ = c; 77660786Sps} 77760786Sps 77860786Sps/* 77960786Sps * Unget a whole string of command characters. 78060786Sps * The next sequence of getcc()'s will return this string. 78160786Sps */ 78260786Sps public void 78360786Spsungetsc(s) 78460786Sps char *s; 78560786Sps{ 78660786Sps register char *p; 78760786Sps 78860786Sps for (p = s + strlen(s) - 1; p >= s; p--) 78960786Sps ungetcc(*p); 79060786Sps} 79160786Sps 79260786Sps/* 79360786Sps * Search for a pattern, possibly in multiple files. 79460786Sps * If SRCH_FIRST_FILE is set, begin searching at the first file. 79560786Sps * If SRCH_PAST_EOF is set, continue the search thru multiple files. 79660786Sps */ 79760786Sps static void 79860786Spsmulti_search(pattern, n) 79960786Sps char *pattern; 80060786Sps int n; 80160786Sps{ 80260786Sps register int nomore; 80360786Sps IFILE save_ifile; 80460786Sps int changed_file; 80560786Sps 80660786Sps changed_file = 0; 80760786Sps save_ifile = save_curr_ifile(); 80860786Sps 80960786Sps if (search_type & SRCH_FIRST_FILE) 81060786Sps { 81160786Sps /* 81260786Sps * Start at the first (or last) file 81360786Sps * in the command line list. 81460786Sps */ 81560786Sps if (search_type & SRCH_FORW) 81660786Sps nomore = edit_first(); 81760786Sps else 81860786Sps nomore = edit_last(); 81960786Sps if (nomore) 82060786Sps { 82160786Sps unsave_ifile(save_ifile); 82260786Sps return; 82360786Sps } 82460786Sps changed_file = 1; 82560786Sps search_type &= ~SRCH_FIRST_FILE; 82660786Sps } 82760786Sps 82860786Sps for (;;) 82960786Sps { 83060786Sps n = search(search_type, pattern, n); 83160786Sps /* 83260786Sps * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared 83360786Sps * after being used once. This allows "n" to work after 83460786Sps * using a /@@ search. 83560786Sps */ 83660786Sps search_type &= ~SRCH_NO_MOVE; 83760786Sps if (n == 0) 83860786Sps { 83960786Sps /* 84060786Sps * Found it. 84160786Sps */ 84260786Sps unsave_ifile(save_ifile); 84360786Sps return; 84460786Sps } 84560786Sps 84660786Sps if (n < 0) 84760786Sps /* 84860786Sps * Some kind of error in the search. 84960786Sps * Error message has been printed by search(). 85060786Sps */ 85160786Sps break; 85260786Sps 85360786Sps if ((search_type & SRCH_PAST_EOF) == 0) 85460786Sps /* 85560786Sps * We didn't find a match, but we're 85660786Sps * supposed to search only one file. 85760786Sps */ 85860786Sps break; 85960786Sps /* 86060786Sps * Move on to the next file. 86160786Sps */ 86260786Sps if (search_type & SRCH_FORW) 86360786Sps nomore = edit_next(1); 86460786Sps else 86560786Sps nomore = edit_prev(1); 86660786Sps if (nomore) 86760786Sps break; 86860786Sps changed_file = 1; 86960786Sps } 87060786Sps 87160786Sps /* 87260786Sps * Didn't find it. 87360786Sps * Print an error message if we haven't already. 87460786Sps */ 87560786Sps if (n > 0) 87660786Sps error("Pattern not found", NULL_PARG); 87760786Sps 87860786Sps if (changed_file) 87960786Sps { 88060786Sps /* 88160786Sps * Restore the file we were originally viewing. 88260786Sps */ 88360786Sps reedit_ifile(save_ifile); 884161478Sdelphij } else 885161478Sdelphij { 886161478Sdelphij unsave_ifile(save_ifile); 88760786Sps } 88860786Sps} 88960786Sps 89060786Sps/* 89160786Sps * Main command processor. 89260786Sps * Accept and execute commands until a quit command. 89360786Sps */ 89460786Sps public void 89560786Spscommands() 89660786Sps{ 89760786Sps register int c; 89860786Sps register int action; 89960786Sps register char *cbuf; 90060786Sps int newaction; 90160786Sps int save_search_type; 90260786Sps char *extra; 90360786Sps char tbuf[2]; 90460786Sps PARG parg; 90560786Sps IFILE old_ifile; 90660786Sps IFILE new_ifile; 90789022Sps char *tagfile; 90860786Sps 90960786Sps search_type = SRCH_FORW; 91060786Sps wscroll = (sc_height + 1) / 2; 91160786Sps newaction = A_NOACTION; 91260786Sps 91360786Sps for (;;) 91460786Sps { 91560786Sps mca = 0; 91660786Sps cmd_accept(); 91760786Sps number = 0; 91860786Sps optchar = '\0'; 91960786Sps 92060786Sps /* 92160786Sps * See if any signals need processing. 92260786Sps */ 92360786Sps if (sigs) 92460786Sps { 92560786Sps psignals(); 92660786Sps if (quitting) 92760786Sps quit(QUIT_SAVED_STATUS); 92860786Sps } 92960786Sps 93060786Sps /* 93160786Sps * See if window size changed, for systems that don't 93260786Sps * generate SIGWINCH. 93360786Sps */ 93460786Sps check_winch(); 93560786Sps 93660786Sps /* 93760786Sps * Display prompt and accept a character. 93860786Sps */ 93960786Sps cmd_reset(); 94060786Sps prompt(); 94160786Sps if (sigs) 94260786Sps continue; 94360786Sps if (newaction == A_NOACTION) 94460786Sps c = getcc(); 94560786Sps 94660786Sps again: 94760786Sps if (sigs) 94860786Sps continue; 94960786Sps 95060786Sps if (newaction != A_NOACTION) 95160786Sps { 95260786Sps action = newaction; 95360786Sps newaction = A_NOACTION; 95460786Sps } else 95560786Sps { 95660786Sps /* 95760786Sps * If we are in a multicharacter command, call mca_char. 95860786Sps * Otherwise we call fcmd_decode to determine the 95960786Sps * action to be performed. 96060786Sps */ 96160786Sps if (mca) 96260786Sps switch (mca_char(c)) 96360786Sps { 96460786Sps case MCA_MORE: 96560786Sps /* 96660786Sps * Need another character. 96760786Sps */ 96860786Sps c = getcc(); 96960786Sps goto again; 97060786Sps case MCA_DONE: 97160786Sps /* 97260786Sps * Command has been handled by mca_char. 97360786Sps * Start clean with a prompt. 97460786Sps */ 97560786Sps continue; 97660786Sps case NO_MCA: 97760786Sps /* 97860786Sps * Not a multi-char command 97960786Sps * (at least, not anymore). 98060786Sps */ 98160786Sps break; 98260786Sps } 98360786Sps 98460786Sps /* 98560786Sps * Decode the command character and decide what to do. 98660786Sps */ 98760786Sps if (mca) 98860786Sps { 98960786Sps /* 99060786Sps * We're in a multichar command. 99160786Sps * Add the character to the command buffer 99260786Sps * and display it on the screen. 99360786Sps * If the user backspaces past the start 99460786Sps * of the line, abort the command. 99560786Sps */ 99660786Sps if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0) 99760786Sps continue; 99860786Sps cbuf = get_cmdbuf(); 99960786Sps } else 100060786Sps { 100160786Sps /* 100260786Sps * Don't use cmd_char if we're starting fresh 100360786Sps * at the beginning of a command, because we 100460786Sps * don't want to echo the command until we know 100560786Sps * it is a multichar command. We also don't 100660786Sps * want erase_char/kill_char to be treated 100760786Sps * as line editing characters. 100860786Sps */ 100960786Sps tbuf[0] = c; 101060786Sps tbuf[1] = '\0'; 101160786Sps cbuf = tbuf; 101260786Sps } 101360786Sps extra = NULL; 101460786Sps action = fcmd_decode(cbuf, &extra); 101560786Sps /* 101660786Sps * If an "extra" string was returned, 101760786Sps * process it as a string of command characters. 101860786Sps */ 101960786Sps if (extra != NULL) 102060786Sps ungetsc(extra); 102160786Sps } 102260786Sps /* 102360786Sps * Clear the cmdbuf string. 102460786Sps * (But not if we're in the prefix of a command, 102560786Sps * because the partial command string is kept there.) 102660786Sps */ 102760786Sps if (action != A_PREFIX) 102860786Sps cmd_reset(); 102960786Sps 103060786Sps switch (action) 103160786Sps { 103260786Sps case A_DIGIT: 103360786Sps /* 103460786Sps * First digit of a number. 103560786Sps */ 103660786Sps start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE); 103760786Sps goto again; 103860786Sps 103960786Sps case A_F_WINDOW: 104060786Sps /* 104160786Sps * Forward one window (and set the window size). 104260786Sps */ 104360786Sps if (number > 0) 1044128348Stjr swindow = (int) number; 104560786Sps /* FALLTHRU */ 104660786Sps case A_F_SCREEN: 104760786Sps /* 104860786Sps * Forward one screen. 104960786Sps */ 105060786Sps if (number <= 0) 105160786Sps number = get_swindow(); 105260786Sps cmd_exec(); 105360786Sps if (show_attn) 105460786Sps set_attnpos(bottompos); 1055128348Stjr forward((int) number, 0, 1); 105660786Sps break; 105760786Sps 105860786Sps case A_B_WINDOW: 105960786Sps /* 106060786Sps * Backward one window (and set the window size). 106160786Sps */ 106260786Sps if (number > 0) 1063128348Stjr swindow = (int) number; 106460786Sps /* FALLTHRU */ 106560786Sps case A_B_SCREEN: 106660786Sps /* 106760786Sps * Backward one screen. 106860786Sps */ 106960786Sps if (number <= 0) 107060786Sps number = get_swindow(); 107160786Sps cmd_exec(); 1072128348Stjr backward((int) number, 0, 1); 107360786Sps break; 107460786Sps 107560786Sps case A_F_LINE: 107660786Sps /* 107760786Sps * Forward N (default 1) line. 107860786Sps */ 107960786Sps if (number <= 0) 108060786Sps number = 1; 108160786Sps cmd_exec(); 108260786Sps if (show_attn == OPT_ONPLUS && number > 1) 108360786Sps set_attnpos(bottompos); 1084128348Stjr forward((int) number, 0, 0); 108560786Sps break; 108660786Sps 108760786Sps case A_B_LINE: 108860786Sps /* 108960786Sps * Backward N (default 1) line. 109060786Sps */ 109160786Sps if (number <= 0) 109260786Sps number = 1; 109360786Sps cmd_exec(); 1094128348Stjr backward((int) number, 0, 0); 109560786Sps break; 109660786Sps 109760786Sps case A_FF_LINE: 109860786Sps /* 109960786Sps * Force forward N (default 1) line. 110060786Sps */ 110160786Sps if (number <= 0) 110260786Sps number = 1; 110360786Sps cmd_exec(); 110460786Sps if (show_attn == OPT_ONPLUS && number > 1) 110560786Sps set_attnpos(bottompos); 1106128348Stjr forward((int) number, 1, 0); 110760786Sps break; 110860786Sps 110960786Sps case A_BF_LINE: 111060786Sps /* 111160786Sps * Force backward N (default 1) line. 111260786Sps */ 111360786Sps if (number <= 0) 111460786Sps number = 1; 111560786Sps cmd_exec(); 1116128348Stjr backward((int) number, 1, 0); 111760786Sps break; 111860786Sps 111960786Sps case A_FF_SCREEN: 112060786Sps /* 112160786Sps * Force forward one screen. 112260786Sps */ 112360786Sps if (number <= 0) 112460786Sps number = get_swindow(); 112560786Sps cmd_exec(); 112660786Sps if (show_attn == OPT_ONPLUS) 112760786Sps set_attnpos(bottompos); 1128128348Stjr forward((int) number, 1, 0); 112960786Sps break; 113060786Sps 113160786Sps case A_F_FOREVER: 113260786Sps /* 113360786Sps * Forward forever, ignoring EOF. 113460786Sps */ 113560786Sps if (ch_getflags() & CH_HELPFILE) 113660786Sps break; 113760786Sps cmd_exec(); 113860786Sps jump_forw(); 113960786Sps ignore_eoi = 1; 114060786Sps hit_eof = 0; 114160786Sps while (!sigs) 1142173685Sdelphij { 1143173685Sdelphij make_display(); 114460786Sps forward(1, 0, 0); 1145173685Sdelphij } 114660786Sps ignore_eoi = 0; 114760786Sps /* 114860786Sps * This gets us back in "F mode" after processing 114960786Sps * a non-abort signal (e.g. window-change). 115060786Sps */ 115160786Sps if (sigs && !ABORT_SIGS()) 115260786Sps newaction = A_F_FOREVER; 115360786Sps break; 115460786Sps 115560786Sps case A_F_SCROLL: 115660786Sps /* 115760786Sps * Forward N lines 115860786Sps * (default same as last 'd' or 'u' command). 115960786Sps */ 116060786Sps if (number > 0) 1161128348Stjr wscroll = (int) number; 116260786Sps cmd_exec(); 116360786Sps if (show_attn == OPT_ONPLUS) 116460786Sps set_attnpos(bottompos); 116560786Sps forward(wscroll, 0, 0); 116660786Sps break; 116760786Sps 116860786Sps case A_B_SCROLL: 116960786Sps /* 117060786Sps * Forward N lines 117160786Sps * (default same as last 'd' or 'u' command). 117260786Sps */ 117360786Sps if (number > 0) 1174128348Stjr wscroll = (int) number; 117560786Sps cmd_exec(); 117660786Sps backward(wscroll, 0, 0); 117760786Sps break; 117860786Sps 117960786Sps case A_FREPAINT: 118060786Sps /* 118160786Sps * Flush buffers, then repaint screen. 118260786Sps * Don't flush the buffers on a pipe! 118360786Sps */ 1184173685Sdelphij clear_buffers(); 118560786Sps /* FALLTHRU */ 118660786Sps case A_REPAINT: 118760786Sps /* 118860786Sps * Repaint screen. 118960786Sps */ 119060786Sps cmd_exec(); 119160786Sps repaint(); 119260786Sps break; 119360786Sps 119460786Sps case A_GOLINE: 119560786Sps /* 119660786Sps * Go to line N, default beginning of file. 119760786Sps */ 119860786Sps if (number <= 0) 119960786Sps number = 1; 120060786Sps cmd_exec(); 120160786Sps jump_back(number); 120260786Sps break; 120360786Sps 120460786Sps case A_PERCENT: 120560786Sps /* 120660786Sps * Go to a specified percentage into the file. 120760786Sps */ 120860786Sps if (number < 0) 1209170259Sdelphij { 121060786Sps number = 0; 1211170259Sdelphij fraction = 0; 1212170259Sdelphij } 121360786Sps if (number > 100) 1214170259Sdelphij { 121560786Sps number = 100; 1216170259Sdelphij fraction = 0; 1217170259Sdelphij } 121860786Sps cmd_exec(); 1219170259Sdelphij jump_percent((int) number, fraction); 122060786Sps break; 122160786Sps 122260786Sps case A_GOEND: 122360786Sps /* 122460786Sps * Go to line N, default end of file. 122560786Sps */ 122660786Sps cmd_exec(); 122760786Sps if (number <= 0) 122860786Sps jump_forw(); 122960786Sps else 123060786Sps jump_back(number); 123160786Sps break; 123260786Sps 123360786Sps case A_GOPOS: 123460786Sps /* 123560786Sps * Go to a specified byte position in the file. 123660786Sps */ 123760786Sps cmd_exec(); 123860786Sps if (number < 0) 123960786Sps number = 0; 1240128348Stjr jump_line_loc((POSITION) number, jump_sline); 124160786Sps break; 124260786Sps 124360786Sps case A_STAT: 124460786Sps /* 124560786Sps * Print file name, etc. 124660786Sps */ 124760786Sps if (ch_getflags() & CH_HELPFILE) 124860786Sps break; 124960786Sps cmd_exec(); 125060786Sps parg.p_string = eq_message(); 125160786Sps error("%s", &parg); 125260786Sps break; 125360786Sps 125460786Sps case A_VERSION: 125560786Sps /* 125660786Sps * Print version number, without the "@(#)". 125760786Sps */ 125860786Sps cmd_exec(); 125960786Sps dispversion(); 126060786Sps break; 126160786Sps 126260786Sps case A_QUIT: 126360786Sps /* 126460786Sps * Exit. 126560786Sps */ 126660786Sps if (curr_ifile != NULL_IFILE && 126760786Sps ch_getflags() & CH_HELPFILE) 126860786Sps { 126960786Sps /* 127060786Sps * Quit while viewing the help file 127160786Sps * just means return to viewing the 127260786Sps * previous file. 127360786Sps */ 1274161478Sdelphij hshift = save_hshift; 127560786Sps if (edit_prev(1) == 0) 127660786Sps break; 127760786Sps } 127860786Sps if (extra != NULL) 127960786Sps quit(*extra); 128060786Sps quit(QUIT_OK); 128160786Sps break; 128260786Sps 128360786Sps/* 128460786Sps * Define abbreviation for a commonly used sequence below. 128560786Sps */ 1286173685Sdelphij#define DO_SEARCH() \ 1287173685Sdelphij if (number <= 0) number = 1; \ 128860786Sps mca_search(); \ 128960786Sps cmd_exec(); \ 1290128348Stjr multi_search((char *)NULL, (int) number); 129160786Sps 129260786Sps 129360786Sps case A_F_SEARCH: 129460786Sps /* 129560786Sps * Search forward for a pattern. 129660786Sps * Get the first char of the pattern. 129760786Sps */ 129860786Sps search_type = SRCH_FORW; 129960786Sps if (number <= 0) 130060786Sps number = 1; 130160786Sps mca_search(); 130260786Sps c = getcc(); 130360786Sps goto again; 130460786Sps 130560786Sps case A_B_SEARCH: 130660786Sps /* 130760786Sps * Search backward for a pattern. 130860786Sps * Get the first char of the pattern. 130960786Sps */ 131060786Sps search_type = SRCH_BACK; 131160786Sps if (number <= 0) 131260786Sps number = 1; 131360786Sps mca_search(); 131460786Sps c = getcc(); 131560786Sps goto again; 131660786Sps 131760786Sps case A_AGAIN_SEARCH: 131860786Sps /* 131960786Sps * Repeat previous search. 132060786Sps */ 132160786Sps DO_SEARCH(); 132260786Sps break; 132360786Sps 132460786Sps case A_T_AGAIN_SEARCH: 132560786Sps /* 132660786Sps * Repeat previous search, multiple files. 132760786Sps */ 132860786Sps search_type |= SRCH_PAST_EOF; 132960786Sps DO_SEARCH(); 133060786Sps break; 133160786Sps 133260786Sps case A_REVERSE_SEARCH: 133360786Sps /* 133460786Sps * Repeat previous search, in reverse direction. 133560786Sps */ 133660786Sps save_search_type = search_type; 133760786Sps search_type = SRCH_REVERSE(search_type); 133860786Sps DO_SEARCH(); 133960786Sps search_type = save_search_type; 134060786Sps break; 134160786Sps 134260786Sps case A_T_REVERSE_SEARCH: 134360786Sps /* 134460786Sps * Repeat previous search, 134560786Sps * multiple files in reverse direction. 134660786Sps */ 134760786Sps save_search_type = search_type; 134860786Sps search_type = SRCH_REVERSE(search_type); 134960786Sps search_type |= SRCH_PAST_EOF; 135060786Sps DO_SEARCH(); 135160786Sps search_type = save_search_type; 135260786Sps break; 135360786Sps 135460786Sps case A_UNDO_SEARCH: 135560786Sps undo_search(); 135660786Sps break; 135760786Sps 135860786Sps case A_HELP: 135960786Sps /* 136060786Sps * Help. 136160786Sps */ 136260786Sps if (ch_getflags() & CH_HELPFILE) 136360786Sps break; 136460786Sps cmd_exec(); 1365161478Sdelphij save_hshift = hshift; 1366161478Sdelphij hshift = 0; 136760786Sps (void) edit(FAKE_HELPFILE); 136860786Sps break; 136960786Sps 137060786Sps case A_EXAMINE: 137160786Sps#if EXAMINE 137260786Sps /* 137360786Sps * Edit a new file. Get the filename. 137460786Sps */ 137560786Sps if (secure) 137660786Sps { 137760786Sps error("Command not available", NULL_PARG); 137860786Sps break; 137960786Sps } 138060786Sps start_mca(A_EXAMINE, "Examine: ", ml_examine, 0); 138160786Sps c = getcc(); 138260786Sps goto again; 138360786Sps#else 138460786Sps error("Command not available", NULL_PARG); 138560786Sps break; 138660786Sps#endif 138760786Sps 138860786Sps case A_VISUAL: 138960786Sps /* 139060786Sps * Invoke an editor on the input file. 139160786Sps */ 139260786Sps#if EDITOR 139360786Sps if (secure) 139460786Sps { 139560786Sps error("Command not available", NULL_PARG); 139660786Sps break; 139760786Sps } 139860786Sps if (ch_getflags() & CH_HELPFILE) 139960786Sps break; 140060786Sps if (strcmp(get_filename(curr_ifile), "-") == 0) 140160786Sps { 140260786Sps error("Cannot edit standard input", NULL_PARG); 140360786Sps break; 140460786Sps } 140560786Sps if (curr_altfilename != NULL) 140660786Sps { 1407161478Sdelphij error("WARNING: This file was viewed via LESSOPEN", 140860786Sps NULL_PARG); 140960786Sps } 141060786Sps start_mca(A_SHELL, "!", ml_shell, 0); 141160786Sps /* 141260786Sps * Expand the editor prototype string 141360786Sps * and pass it to the system to execute. 141460786Sps * (Make sure the screen is displayed so the 141560786Sps * expansion of "+%lm" works.) 141660786Sps */ 141760786Sps make_display(); 141860786Sps cmd_exec(); 141960786Sps lsystem(pr_expand(editproto, 0), (char*)NULL); 142060786Sps break; 142160786Sps#else 142260786Sps error("Command not available", NULL_PARG); 142360786Sps break; 142460786Sps#endif 142560786Sps 142660786Sps case A_NEXT_FILE: 142760786Sps /* 142860786Sps * Examine next file. 142960786Sps */ 1430128348Stjr#if TAGS 143189022Sps if (ntags()) 143289022Sps { 143389022Sps error("No next file", NULL_PARG); 143489022Sps break; 143589022Sps } 1436128348Stjr#endif 143760786Sps if (number <= 0) 143860786Sps number = 1; 1439128348Stjr if (edit_next((int) number)) 144060786Sps { 1441170259Sdelphij if (get_quit_at_eof() && hit_eof && 144260786Sps !(ch_getflags() & CH_HELPFILE)) 144360786Sps quit(QUIT_OK); 144460786Sps parg.p_string = (number > 1) ? "(N-th) " : ""; 144560786Sps error("No %snext file", &parg); 144660786Sps } 144760786Sps break; 144860786Sps 144960786Sps case A_PREV_FILE: 145060786Sps /* 145160786Sps * Examine previous file. 145260786Sps */ 1453128348Stjr#if TAGS 145489022Sps if (ntags()) 145589022Sps { 145689022Sps error("No previous file", NULL_PARG); 145789022Sps break; 145889022Sps } 1459128348Stjr#endif 146060786Sps if (number <= 0) 146160786Sps number = 1; 1462128348Stjr if (edit_prev((int) number)) 146360786Sps { 146460786Sps parg.p_string = (number > 1) ? "(N-th) " : ""; 146560786Sps error("No %sprevious file", &parg); 146660786Sps } 146760786Sps break; 146860786Sps 146989022Sps case A_NEXT_TAG: 1470128348Stjr#if TAGS 147189022Sps if (number <= 0) 147289022Sps number = 1; 1473128348Stjr tagfile = nexttag((int) number); 147489022Sps if (tagfile == NULL) 147589022Sps { 147689022Sps error("No next tag", NULL_PARG); 147789022Sps break; 147889022Sps } 147989022Sps if (edit(tagfile) == 0) 148089022Sps { 148189022Sps POSITION pos = tagsearch(); 148289022Sps if (pos != NULL_POSITION) 148389022Sps jump_loc(pos, jump_sline); 148489022Sps } 1485128348Stjr#else 1486128348Stjr error("Command not available", NULL_PARG); 1487128348Stjr#endif 148889022Sps break; 148989022Sps 149089022Sps case A_PREV_TAG: 1491128348Stjr#if TAGS 149289022Sps if (number <= 0) 149389022Sps number = 1; 1494128348Stjr tagfile = prevtag((int) number); 149589022Sps if (tagfile == NULL) 149689022Sps { 149789022Sps error("No previous tag", NULL_PARG); 149889022Sps break; 149989022Sps } 150089022Sps if (edit(tagfile) == 0) 150189022Sps { 150289022Sps POSITION pos = tagsearch(); 150389022Sps if (pos != NULL_POSITION) 150489022Sps jump_loc(pos, jump_sline); 150589022Sps } 1506128348Stjr#else 1507128348Stjr error("Command not available", NULL_PARG); 1508128348Stjr#endif 150989022Sps break; 151089022Sps 151160786Sps case A_INDEX_FILE: 151260786Sps /* 151360786Sps * Examine a particular file. 151460786Sps */ 151560786Sps if (number <= 0) 151660786Sps number = 1; 1517128348Stjr if (edit_index((int) number)) 151860786Sps error("No such file", NULL_PARG); 151960786Sps break; 152060786Sps 152160786Sps case A_REMOVE_FILE: 152260786Sps if (ch_getflags() & CH_HELPFILE) 152360786Sps break; 152460786Sps old_ifile = curr_ifile; 152560786Sps new_ifile = getoff_ifile(curr_ifile); 152660786Sps if (new_ifile == NULL_IFILE) 152760786Sps { 152860786Sps bell(); 152960786Sps break; 153060786Sps } 153160786Sps if (edit_ifile(new_ifile) != 0) 153260786Sps { 153360786Sps reedit_ifile(old_ifile); 153460786Sps break; 153560786Sps } 153660786Sps del_ifile(old_ifile); 153760786Sps break; 153860786Sps 153960786Sps case A_OPT_TOGGLE: 154060786Sps optflag = OPT_TOGGLE; 154160786Sps optgetname = FALSE; 154260786Sps mca_opt_toggle(); 154360786Sps c = getcc(); 154460786Sps goto again; 154560786Sps 154660786Sps case A_DISP_OPTION: 154760786Sps /* 154860786Sps * Report a flag setting. 154960786Sps */ 155060786Sps optflag = OPT_NO_TOGGLE; 155160786Sps optgetname = FALSE; 155260786Sps mca_opt_toggle(); 155360786Sps c = getcc(); 155460786Sps goto again; 155560786Sps 155660786Sps case A_FIRSTCMD: 155760786Sps /* 155860786Sps * Set an initial command for new files. 155960786Sps */ 156060786Sps start_mca(A_FIRSTCMD, "+", (void*)NULL, 0); 156160786Sps c = getcc(); 156260786Sps goto again; 156360786Sps 156460786Sps case A_SHELL: 156560786Sps /* 156660786Sps * Shell escape. 156760786Sps */ 156860786Sps#if SHELL_ESCAPE 156960786Sps if (secure) 157060786Sps { 157160786Sps error("Command not available", NULL_PARG); 157260786Sps break; 157360786Sps } 157460786Sps start_mca(A_SHELL, "!", ml_shell, 0); 157560786Sps c = getcc(); 157660786Sps goto again; 157760786Sps#else 157860786Sps error("Command not available", NULL_PARG); 157960786Sps break; 158060786Sps#endif 158160786Sps 158260786Sps case A_SETMARK: 158360786Sps /* 158460786Sps * Set a mark. 158560786Sps */ 158660786Sps if (ch_getflags() & CH_HELPFILE) 158760786Sps break; 158860786Sps start_mca(A_SETMARK, "mark: ", (void*)NULL, 0); 158960786Sps c = getcc(); 1590161478Sdelphij if (c == erase_char || c == erase2_char || 1591161478Sdelphij c == kill_char || c == '\n' || c == '\r') 159260786Sps break; 159360786Sps setmark(c); 159460786Sps break; 159560786Sps 159660786Sps case A_GOMARK: 159760786Sps /* 159860786Sps * Go to a mark. 159960786Sps */ 160060786Sps start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0); 160160786Sps c = getcc(); 1602161478Sdelphij if (c == erase_char || c == erase2_char || 1603161478Sdelphij c == kill_char || c == '\n' || c == '\r') 160460786Sps break; 160560786Sps gomark(c); 160660786Sps break; 160760786Sps 160860786Sps case A_PIPE: 160960786Sps#if PIPEC 161060786Sps if (secure) 161160786Sps { 161260786Sps error("Command not available", NULL_PARG); 161360786Sps break; 161460786Sps } 161560786Sps start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); 161660786Sps c = getcc(); 1617161478Sdelphij if (c == erase_char || c == erase2_char || c == kill_char) 161860786Sps break; 161960786Sps if (c == '\n' || c == '\r') 162060786Sps c = '.'; 162160786Sps if (badmark(c)) 162260786Sps break; 162360786Sps pipec = c; 162460786Sps start_mca(A_PIPE, "!", ml_shell, 0); 162560786Sps c = getcc(); 162660786Sps goto again; 162760786Sps#else 162860786Sps error("Command not available", NULL_PARG); 162960786Sps break; 163060786Sps#endif 163160786Sps 163260786Sps case A_B_BRACKET: 163360786Sps case A_F_BRACKET: 163460786Sps start_mca(action, "Brackets: ", (void*)NULL, 0); 163560786Sps c = getcc(); 163660786Sps goto again; 163760786Sps 163860786Sps case A_LSHIFT: 163989022Sps if (number > 0) 164089022Sps shift_count = number; 164189022Sps else 164263131Sps number = (shift_count > 0) ? 164363131Sps shift_count : sc_width / 2; 164460786Sps if (number > hshift) 164560786Sps number = hshift; 164660786Sps hshift -= number; 164760786Sps screen_trashed = 1; 164860786Sps break; 164960786Sps 165060786Sps case A_RSHIFT: 165189022Sps if (number > 0) 165289022Sps shift_count = number; 165389022Sps else 165463131Sps number = (shift_count > 0) ? 165563131Sps shift_count : sc_width / 2; 165660786Sps hshift += number; 165760786Sps screen_trashed = 1; 165860786Sps break; 165960786Sps 166060786Sps case A_PREFIX: 166160786Sps /* 166260786Sps * The command is incomplete (more chars are needed). 166360786Sps * Display the current char, so the user knows 166460786Sps * what's going on, and get another character. 166560786Sps */ 166660786Sps if (mca != A_PREFIX) 166760786Sps { 166860786Sps cmd_reset(); 166960786Sps start_mca(A_PREFIX, " ", (void*)NULL, 167060786Sps CF_QUIT_ON_ERASE); 167160786Sps (void) cmd_char(c); 167260786Sps } 167360786Sps c = getcc(); 167460786Sps goto again; 167560786Sps 167660786Sps case A_NOACTION: 167760786Sps break; 167860786Sps 167960786Sps default: 168060786Sps bell(); 168160786Sps break; 168260786Sps } 168360786Sps } 168460786Sps} 1685