1a8f92a7cSPaul Saab /* $FreeBSD$ */ 2a5f0fb15SPaul Saab /* 3*d713e089SXin LI * Copyright (C) 1984-2023 Mark Nudelman 4a5f0fb15SPaul Saab * 5a5f0fb15SPaul Saab * You may distribute under the terms of either the GNU General Public 6a5f0fb15SPaul Saab * License or the Less License, as specified in the README file. 7a5f0fb15SPaul Saab * 896e55cc7SXin LI * For more information, see the README file. 9a5f0fb15SPaul Saab */ 10a5f0fb15SPaul Saab 11a5f0fb15SPaul Saab 12a5f0fb15SPaul Saab /* 13a5f0fb15SPaul Saab * User-level command processor. 14a5f0fb15SPaul Saab */ 15a5f0fb15SPaul Saab 16a5f0fb15SPaul Saab #include "less.h" 178fd4165cSPaul Saab #if MSDOS_COMPILER==WIN32C 188fd4165cSPaul Saab #include <windows.h> 198fd4165cSPaul Saab #endif 20a5f0fb15SPaul Saab #include "position.h" 21a5f0fb15SPaul Saab #include "option.h" 22a5f0fb15SPaul Saab #include "cmd.h" 23a5f0fb15SPaul Saab 2489dd99dcSXin LI extern int erase_char, erase2_char, kill_char; 25a5f0fb15SPaul Saab extern int sigs; 26a5f0fb15SPaul Saab extern int quit_if_one_screen; 27*d713e089SXin LI extern int one_screen; 28a5f0fb15SPaul Saab extern int squished; 29a5f0fb15SPaul Saab extern int sc_width; 30a5f0fb15SPaul Saab extern int sc_height; 31b2ea2440SXin LI extern char *kent; 32a5f0fb15SPaul Saab extern int swindow; 33a5f0fb15SPaul Saab extern int jump_sline; 34a5f0fb15SPaul Saab extern int quitting; 35a5f0fb15SPaul Saab extern int wscroll; 36a5f0fb15SPaul Saab extern int top_scroll; 37a5f0fb15SPaul Saab extern int ignore_eoi; 38a5f0fb15SPaul Saab extern int secure; 39a5f0fb15SPaul Saab extern int hshift; 40a15691bfSXin LI extern int bs_mode; 41*d713e089SXin LI extern int proc_backspace; 42a5f0fb15SPaul Saab extern int show_attn; 43720c436cSXin LI extern int less_is_more; 44b2ea2440SXin LI extern int status_col; 4596e55cc7SXin LI extern POSITION highest_hilite; 46b2ea2440SXin LI extern POSITION start_attnpos; 47b2ea2440SXin LI extern POSITION end_attnpos; 48a5f0fb15SPaul Saab extern char *every_first_cmd; 49a5f0fb15SPaul Saab extern char version[]; 50a5f0fb15SPaul Saab extern struct scrpos initial_scrpos; 51a5f0fb15SPaul Saab extern IFILE curr_ifile; 52f6b74a7dSXin LI extern void *ml_search; 53f6b74a7dSXin LI extern void *ml_examine; 54b7780dbeSXin LI extern int wheel_lines; 5595270f73SXin LI extern int header_lines; 5695270f73SXin LI extern int def_search_type; 5795270f73SXin LI extern int updown_match; 58a5f0fb15SPaul Saab #if SHELL_ESCAPE || PIPEC 59f6b74a7dSXin LI extern void *ml_shell; 60a5f0fb15SPaul Saab #endif 61a5f0fb15SPaul Saab #if EDITOR 62a5f0fb15SPaul Saab extern char *editor; 63a5f0fb15SPaul Saab extern char *editproto; 64a5f0fb15SPaul Saab #endif 65a5f0fb15SPaul Saab extern int screen_trashed; /* The screen has been overwritten */ 6615596da4SPaul Saab extern int shift_count; 67720c436cSXin LI extern int oldbot; 68720c436cSXin LI extern int forw_prompt; 692235c7feSXin LI extern int incr_search; 70*d713e089SXin LI extern int full_screen; 71b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 72b7780dbeSXin LI extern int utf_mode; 73b7780dbeSXin LI #endif 74a5f0fb15SPaul Saab 75a5f0fb15SPaul Saab #if SHELL_ESCAPE 76a5f0fb15SPaul Saab static char *shellcmd = NULL; /* For holding last shell command for "!!" */ 77a5f0fb15SPaul Saab #endif 78a5f0fb15SPaul Saab static int mca; /* The multicharacter command (action) */ 79a5f0fb15SPaul Saab static int search_type; /* The previous type of search */ 80*d713e089SXin LI static int last_search_type; /* Type of last executed search */ 811ede1615STim J. Robbins static LINENUM number; /* The number typed by the user */ 82720c436cSXin LI static long fraction; /* The fractional part of the number */ 8333096f16SXin LI static struct loption *curropt; 8433096f16SXin LI static int opt_lower; 85a5f0fb15SPaul Saab static int optflag; 86a5f0fb15SPaul Saab static int optgetname; 87a5f0fb15SPaul Saab static POSITION bottompos; 8889dd99dcSXin LI static int save_hshift; 89a15691bfSXin LI static int save_bs_mode; 90*d713e089SXin LI static int save_proc_backspace; 91a5f0fb15SPaul Saab #if PIPEC 92a5f0fb15SPaul Saab static char pipec; 93a5f0fb15SPaul Saab #endif 94a5f0fb15SPaul Saab 95b2ea2440SXin LI /* Stack of ungotten chars (via ungetcc) */ 9633096f16SXin LI struct ungot { 9733096f16SXin LI struct ungot *ug_next; 98b2ea2440SXin LI LWCHAR ug_char; 9933096f16SXin LI }; 10033096f16SXin LI static struct ungot* ungot = NULL; 10133096f16SXin LI 102*d713e089SXin LI static void multi_search (char *pattern, int n, int silent); 103a5f0fb15SPaul Saab 104a5f0fb15SPaul Saab /* 105720c436cSXin LI * Move the cursor to start of prompt line before executing a command. 106a5f0fb15SPaul Saab * This looks nicer if the command takes a long time before 107a5f0fb15SPaul Saab * updating the screen. 108a5f0fb15SPaul Saab */ 109*d713e089SXin LI static void cmd_exec(void) 110a5f0fb15SPaul Saab { 111a5f0fb15SPaul Saab clear_attn(); 112aa22b8b6SXin LI clear_bot(); 113a5f0fb15SPaul Saab flush(); 114a5f0fb15SPaul Saab } 115a5f0fb15SPaul Saab 116a5f0fb15SPaul Saab /* 117b7780dbeSXin LI * Indicate we are reading a multi-character command. 118b7780dbeSXin LI */ 119*d713e089SXin LI static void set_mca(int action) 120b7780dbeSXin LI { 121b7780dbeSXin LI mca = action; 122b7780dbeSXin LI clear_bot(); 123b7780dbeSXin LI clear_cmd(); 124b7780dbeSXin LI } 125b7780dbeSXin LI 126b7780dbeSXin LI /* 127b7780dbeSXin LI * Indicate we are not reading a multi-character command. 128b7780dbeSXin LI */ 129*d713e089SXin LI static void clear_mca(void) 130b7780dbeSXin LI { 131b7780dbeSXin LI if (mca == 0) 132b7780dbeSXin LI return; 133b7780dbeSXin LI mca = 0; 134b7780dbeSXin LI } 135b7780dbeSXin LI 136b7780dbeSXin LI /* 137a5f0fb15SPaul Saab * Set up the display to start a new multi-character command. 138a5f0fb15SPaul Saab */ 139*d713e089SXin LI static void start_mca(int action, constant char *prompt, void *mlist, int cmdflags) 140a5f0fb15SPaul Saab { 141b7780dbeSXin LI set_mca(action); 142a5f0fb15SPaul Saab cmd_putstr(prompt); 143a5f0fb15SPaul Saab set_mlist(mlist, cmdflags); 144a5f0fb15SPaul Saab } 145a5f0fb15SPaul Saab 146*d713e089SXin LI public int in_mca(void) 147a5f0fb15SPaul Saab { 148a5f0fb15SPaul Saab return (mca != 0 && mca != A_PREFIX); 149a5f0fb15SPaul Saab } 150a5f0fb15SPaul Saab 151a5f0fb15SPaul Saab /* 152a5f0fb15SPaul Saab * Set up the display to start a new search command. 153a5f0fb15SPaul Saab */ 154*d713e089SXin LI static void mca_search1(void) 155a5f0fb15SPaul Saab { 156*d713e089SXin LI int i; 157*d713e089SXin LI 1587374caaaSXin LI #if HILITE_SEARCH 1597374caaaSXin LI if (search_type & SRCH_FILTER) 160b7780dbeSXin LI set_mca(A_FILTER); 1617374caaaSXin LI else 1627374caaaSXin LI #endif 163a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 164b7780dbeSXin LI set_mca(A_F_SEARCH); 165a5f0fb15SPaul Saab else 166b7780dbeSXin LI set_mca(A_B_SEARCH); 167a5f0fb15SPaul Saab 168a5f0fb15SPaul Saab if (search_type & SRCH_NO_MATCH) 169a5f0fb15SPaul Saab cmd_putstr("Non-match "); 170a5f0fb15SPaul Saab if (search_type & SRCH_FIRST_FILE) 171a5f0fb15SPaul Saab cmd_putstr("First-file "); 172a5f0fb15SPaul Saab if (search_type & SRCH_PAST_EOF) 173a5f0fb15SPaul Saab cmd_putstr("EOF-ignore "); 174a5f0fb15SPaul Saab if (search_type & SRCH_NO_MOVE) 175a5f0fb15SPaul Saab cmd_putstr("Keep-pos "); 176a5f0fb15SPaul Saab if (search_type & SRCH_NO_REGEX) 177a5f0fb15SPaul Saab cmd_putstr("Regex-off "); 1782235c7feSXin LI if (search_type & SRCH_WRAP) 1792235c7feSXin LI cmd_putstr("Wrap "); 180*d713e089SXin LI for (i = 1; i <= NUM_SEARCH_COLORS; i++) 181*d713e089SXin LI { 182*d713e089SXin LI if (search_type & SRCH_SUBSEARCH(i)) 183*d713e089SXin LI { 184*d713e089SXin LI char buf[8]; 185*d713e089SXin LI SNPRINTF1(buf, sizeof(buf), "Sub-%d ", i); 186*d713e089SXin LI cmd_putstr(buf); 187*d713e089SXin LI } 188*d713e089SXin LI } 189a5f0fb15SPaul Saab 1907374caaaSXin LI #if HILITE_SEARCH 1917374caaaSXin LI if (search_type & SRCH_FILTER) 1927374caaaSXin LI cmd_putstr("&/"); 1937374caaaSXin LI else 1947374caaaSXin LI #endif 195a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 196a5f0fb15SPaul Saab cmd_putstr("/"); 197a5f0fb15SPaul Saab else 198a5f0fb15SPaul Saab cmd_putstr("?"); 199a15691bfSXin LI forw_prompt = 0; 20095270f73SXin LI } 20195270f73SXin LI 202*d713e089SXin LI static void mca_search(void) 20395270f73SXin LI { 20495270f73SXin LI mca_search1(); 205a5f0fb15SPaul Saab set_mlist(ml_search, 0); 206a5f0fb15SPaul Saab } 207a5f0fb15SPaul Saab 208a5f0fb15SPaul Saab /* 209a5f0fb15SPaul Saab * Set up the display to start a new toggle-option command. 210a5f0fb15SPaul Saab */ 211*d713e089SXin LI static void mca_opt_toggle(void) 212a5f0fb15SPaul Saab { 213a5f0fb15SPaul Saab int no_prompt; 214a5f0fb15SPaul Saab int flag; 215a5f0fb15SPaul Saab char *dash; 216a5f0fb15SPaul Saab 217a5f0fb15SPaul Saab no_prompt = (optflag & OPT_NO_PROMPT); 218a5f0fb15SPaul Saab flag = (optflag & ~OPT_NO_PROMPT); 219a5f0fb15SPaul Saab dash = (flag == OPT_NO_TOGGLE) ? "_" : "-"; 220a5f0fb15SPaul Saab 221b7780dbeSXin LI set_mca(A_OPT_TOGGLE); 222a5f0fb15SPaul Saab cmd_putstr(dash); 223a5f0fb15SPaul Saab if (optgetname) 224a5f0fb15SPaul Saab cmd_putstr(dash); 225a5f0fb15SPaul Saab if (no_prompt) 226a5f0fb15SPaul Saab cmd_putstr("(P)"); 227a5f0fb15SPaul Saab switch (flag) 228a5f0fb15SPaul Saab { 229a5f0fb15SPaul Saab case OPT_UNSET: 230a5f0fb15SPaul Saab cmd_putstr("+"); 231a5f0fb15SPaul Saab break; 232a5f0fb15SPaul Saab case OPT_SET: 233a5f0fb15SPaul Saab cmd_putstr("!"); 234a5f0fb15SPaul Saab break; 235a5f0fb15SPaul Saab } 236a15691bfSXin LI forw_prompt = 0; 237a5f0fb15SPaul Saab set_mlist(NULL, 0); 238a5f0fb15SPaul Saab } 239a5f0fb15SPaul Saab 240a5f0fb15SPaul Saab /* 241a5f0fb15SPaul Saab * Execute a multicharacter command. 242a5f0fb15SPaul Saab */ 243*d713e089SXin LI static void exec_mca(void) 244a5f0fb15SPaul Saab { 2451ea31627SRobert Watson char *cbuf; 246a5f0fb15SPaul Saab 247a5f0fb15SPaul Saab cmd_exec(); 248a5f0fb15SPaul Saab cbuf = get_cmdbuf(); 24995270f73SXin LI if (cbuf == NULL) 25095270f73SXin LI return; 251a5f0fb15SPaul Saab 252a5f0fb15SPaul Saab switch (mca) 253a5f0fb15SPaul Saab { 254a5f0fb15SPaul Saab case A_F_SEARCH: 255a5f0fb15SPaul Saab case A_B_SEARCH: 256a15691bfSXin LI multi_search(cbuf, (int) number, 0); 257a5f0fb15SPaul Saab break; 2587374caaaSXin LI #if HILITE_SEARCH 2597374caaaSXin LI case A_FILTER: 2607374caaaSXin LI search_type ^= SRCH_NO_MATCH; 2617374caaaSXin LI set_filter_pattern(cbuf, search_type); 2627374caaaSXin LI break; 2637374caaaSXin LI #endif 264a5f0fb15SPaul Saab case A_FIRSTCMD: 265a5f0fb15SPaul Saab /* 266a5f0fb15SPaul Saab * Skip leading spaces or + signs in the string. 267a5f0fb15SPaul Saab */ 268a5f0fb15SPaul Saab while (*cbuf == '+' || *cbuf == ' ') 269a5f0fb15SPaul Saab cbuf++; 270a5f0fb15SPaul Saab if (every_first_cmd != NULL) 271a5f0fb15SPaul Saab free(every_first_cmd); 272a5f0fb15SPaul Saab if (*cbuf == '\0') 273a5f0fb15SPaul Saab every_first_cmd = NULL; 274a5f0fb15SPaul Saab else 275a5f0fb15SPaul Saab every_first_cmd = save(cbuf); 276a5f0fb15SPaul Saab break; 277a5f0fb15SPaul Saab case A_OPT_TOGGLE: 27833096f16SXin LI toggle_option(curropt, opt_lower, cbuf, optflag); 27933096f16SXin LI curropt = NULL; 280a5f0fb15SPaul Saab break; 281a5f0fb15SPaul Saab case A_F_BRACKET: 2821ede1615STim J. Robbins match_brac(cbuf[0], cbuf[1], 1, (int) number); 283a5f0fb15SPaul Saab break; 284a5f0fb15SPaul Saab case A_B_BRACKET: 2851ede1615STim J. Robbins match_brac(cbuf[1], cbuf[0], 0, (int) number); 286a5f0fb15SPaul Saab break; 287a5f0fb15SPaul Saab #if EXAMINE 288a5f0fb15SPaul Saab case A_EXAMINE: 289a5f0fb15SPaul Saab if (secure) 290a5f0fb15SPaul Saab break; 291a5f0fb15SPaul Saab edit_list(cbuf); 2921ede1615STim J. Robbins #if TAGS 2938fd4165cSPaul Saab /* If tag structure is loaded then clean it up. */ 2948fd4165cSPaul Saab cleantags(); 2951ede1615STim J. Robbins #endif 296a5f0fb15SPaul Saab break; 297a5f0fb15SPaul Saab #endif 298a5f0fb15SPaul Saab #if SHELL_ESCAPE 299a5f0fb15SPaul Saab case A_SHELL: 300a5f0fb15SPaul Saab /* 301a5f0fb15SPaul Saab * !! just uses whatever is in shellcmd. 302a5f0fb15SPaul Saab * Otherwise, copy cmdbuf to shellcmd, 303a5f0fb15SPaul Saab * expanding any special characters ("%" or "#"). 304a5f0fb15SPaul Saab */ 305a5f0fb15SPaul Saab if (*cbuf != '!') 306a5f0fb15SPaul Saab { 307a5f0fb15SPaul Saab if (shellcmd != NULL) 308a5f0fb15SPaul Saab free(shellcmd); 309a5f0fb15SPaul Saab shellcmd = fexpand(cbuf); 310a5f0fb15SPaul Saab } 311a5f0fb15SPaul Saab 312a5f0fb15SPaul Saab if (secure) 313a5f0fb15SPaul Saab break; 314a5f0fb15SPaul Saab if (shellcmd == NULL) 315a5f0fb15SPaul Saab lsystem("", "!done"); 316a5f0fb15SPaul Saab else 317a5f0fb15SPaul Saab lsystem(shellcmd, "!done"); 318a5f0fb15SPaul Saab break; 319*d713e089SXin LI case A_PSHELL: 320*d713e089SXin LI if (secure) 321*d713e089SXin LI break; 322*d713e089SXin LI lsystem(pr_expand(cbuf), "#done"); 323*d713e089SXin LI break; 324a5f0fb15SPaul Saab #endif 325a5f0fb15SPaul Saab #if PIPEC 326a5f0fb15SPaul Saab case A_PIPE: 327a5f0fb15SPaul Saab if (secure) 328a5f0fb15SPaul Saab break; 329a5f0fb15SPaul Saab (void) pipe_mark(pipec, cbuf); 330a5f0fb15SPaul Saab error("|done", NULL_PARG); 331a5f0fb15SPaul Saab break; 332a5f0fb15SPaul Saab #endif 333a5f0fb15SPaul Saab } 334a5f0fb15SPaul Saab } 335a5f0fb15SPaul Saab 336a5f0fb15SPaul Saab /* 33733096f16SXin LI * Is a character an erase or kill char? 338a5f0fb15SPaul Saab */ 339*d713e089SXin LI static int is_erase_char(int c) 340a5f0fb15SPaul Saab { 34133096f16SXin LI return (c == erase_char || c == erase2_char || c == kill_char); 342a5f0fb15SPaul Saab } 343a5f0fb15SPaul Saab 344a5f0fb15SPaul Saab /* 345b2ea2440SXin LI * Is a character a carriage return or newline? 346b2ea2440SXin LI */ 347*d713e089SXin LI static int is_newline_char(int c) 348b2ea2440SXin LI { 349b2ea2440SXin LI return (c == '\n' || c == '\r'); 350b2ea2440SXin LI } 351b2ea2440SXin LI 352b2ea2440SXin LI /* 35333096f16SXin LI * Handle the first char of an option (after the initial dash). 354a5f0fb15SPaul Saab */ 355*d713e089SXin LI static int mca_opt_first_char(int c) 356a5f0fb15SPaul Saab { 35795270f73SXin LI int no_prompt = (optflag & OPT_NO_PROMPT); 35833096f16SXin LI int flag = (optflag & ~OPT_NO_PROMPT); 359a5f0fb15SPaul Saab if (flag == OPT_NO_TOGGLE) 360a5f0fb15SPaul Saab { 361a5f0fb15SPaul Saab switch (c) 362a5f0fb15SPaul Saab { 363a5f0fb15SPaul Saab case '_': 364a5f0fb15SPaul Saab /* "__" = long option name. */ 365a5f0fb15SPaul Saab optgetname = TRUE; 366a5f0fb15SPaul Saab mca_opt_toggle(); 367a5f0fb15SPaul Saab return (MCA_MORE); 368a5f0fb15SPaul Saab } 369a5f0fb15SPaul Saab } else 370a5f0fb15SPaul Saab { 371a5f0fb15SPaul Saab switch (c) 372a5f0fb15SPaul Saab { 373a5f0fb15SPaul Saab case '+': 374a5f0fb15SPaul Saab /* "-+" = UNSET. */ 37595270f73SXin LI optflag = no_prompt | ((flag == OPT_UNSET) ? 37695270f73SXin LI OPT_TOGGLE : OPT_UNSET); 377a5f0fb15SPaul Saab mca_opt_toggle(); 378a5f0fb15SPaul Saab return (MCA_MORE); 379a5f0fb15SPaul Saab case '!': 380a5f0fb15SPaul Saab /* "-!" = SET */ 38195270f73SXin LI optflag = no_prompt | ((flag == OPT_SET) ? 38295270f73SXin LI OPT_TOGGLE : OPT_SET); 383a5f0fb15SPaul Saab mca_opt_toggle(); 384a5f0fb15SPaul Saab return (MCA_MORE); 385a5f0fb15SPaul Saab case CONTROL('P'): 386a5f0fb15SPaul Saab optflag ^= OPT_NO_PROMPT; 387a5f0fb15SPaul Saab mca_opt_toggle(); 388a5f0fb15SPaul Saab return (MCA_MORE); 389a5f0fb15SPaul Saab case '-': 390a5f0fb15SPaul Saab /* "--" = long option name. */ 391a5f0fb15SPaul Saab optgetname = TRUE; 392a5f0fb15SPaul Saab mca_opt_toggle(); 393a5f0fb15SPaul Saab return (MCA_MORE); 394a5f0fb15SPaul Saab } 395a5f0fb15SPaul Saab } 39633096f16SXin LI /* Char was not handled here. */ 39733096f16SXin LI return (NO_MCA); 398a5f0fb15SPaul Saab } 39933096f16SXin LI 400a5f0fb15SPaul Saab /* 40133096f16SXin LI * Add a char to a long option name. 40233096f16SXin LI * See if we've got a match for an option name yet. 403a5f0fb15SPaul Saab * If so, display the complete name and stop 404a5f0fb15SPaul Saab * accepting chars until user hits RETURN. 405a5f0fb15SPaul Saab */ 406*d713e089SXin LI static int mca_opt_nonfirst_char(int c) 40733096f16SXin LI { 40833096f16SXin LI char *p; 409a5f0fb15SPaul Saab char *oname; 410b7780dbeSXin LI int err; 411a5f0fb15SPaul Saab 41233096f16SXin LI if (curropt != NULL) 413a5f0fb15SPaul Saab { 414a5f0fb15SPaul Saab /* 415a5f0fb15SPaul Saab * Already have a match for the name. 416a5f0fb15SPaul Saab * Don't accept anything but erase/kill. 417a5f0fb15SPaul Saab */ 41833096f16SXin LI if (is_erase_char(c)) 419a5f0fb15SPaul Saab return (MCA_DONE); 420a5f0fb15SPaul Saab return (MCA_MORE); 421a5f0fb15SPaul Saab } 422a5f0fb15SPaul Saab /* 423a5f0fb15SPaul Saab * Add char to cmd buffer and try to match 424a5f0fb15SPaul Saab * the option name. 425a5f0fb15SPaul Saab */ 426a5f0fb15SPaul Saab if (cmd_char(c) == CC_QUIT) 427a5f0fb15SPaul Saab return (MCA_DONE); 428a5f0fb15SPaul Saab p = get_cmdbuf(); 42995270f73SXin LI if (p == NULL) 43095270f73SXin LI return (MCA_MORE); 43133096f16SXin LI opt_lower = ASCII_IS_LOWER(p[0]); 432b7780dbeSXin LI err = 0; 433b7780dbeSXin LI curropt = findopt_name(&p, &oname, &err); 43433096f16SXin LI if (curropt != NULL) 435a5f0fb15SPaul Saab { 436a5f0fb15SPaul Saab /* 437a5f0fb15SPaul Saab * Got a match. 43833096f16SXin LI * Remember the option and 439a5f0fb15SPaul Saab * display the full option name. 440a5f0fb15SPaul Saab */ 441a5f0fb15SPaul Saab cmd_reset(); 442a5f0fb15SPaul Saab mca_opt_toggle(); 443a5f0fb15SPaul Saab for (p = oname; *p != '\0'; p++) 444a5f0fb15SPaul Saab { 445a5f0fb15SPaul Saab c = *p; 44633096f16SXin LI if (!opt_lower && ASCII_IS_LOWER(c)) 44789dd99dcSXin LI c = ASCII_TO_UPPER(c); 448a5f0fb15SPaul Saab if (cmd_char(c) != CC_OK) 449a5f0fb15SPaul Saab return (MCA_DONE); 450a5f0fb15SPaul Saab } 451b7780dbeSXin LI } else if (err != OPT_AMBIG) 452b7780dbeSXin LI { 453b7780dbeSXin LI bell(); 454a5f0fb15SPaul Saab } 455a5f0fb15SPaul Saab return (MCA_MORE); 456a5f0fb15SPaul Saab } 45733096f16SXin LI 45833096f16SXin LI /* 45933096f16SXin LI * Handle a char of an option toggle command. 46033096f16SXin LI */ 461*d713e089SXin LI static int mca_opt_char(int c) 46233096f16SXin LI { 46333096f16SXin LI PARG parg; 46433096f16SXin LI 46533096f16SXin LI /* 46633096f16SXin LI * This may be a short option (single char), 46733096f16SXin LI * or one char of a long option name, 46833096f16SXin LI * or one char of the option parameter. 46933096f16SXin LI */ 47033096f16SXin LI if (curropt == NULL && len_cmdbuf() == 0) 47133096f16SXin LI { 47233096f16SXin LI int ret = mca_opt_first_char(c); 47333096f16SXin LI if (ret != NO_MCA) 47433096f16SXin LI return (ret); 47533096f16SXin LI } 47633096f16SXin LI if (optgetname) 47733096f16SXin LI { 47833096f16SXin LI /* We're getting a long option name. */ 47995270f73SXin LI if (!is_newline_char(c) && c != '=') 48033096f16SXin LI return (mca_opt_nonfirst_char(c)); 48133096f16SXin LI if (curropt == NULL) 48233096f16SXin LI { 48333096f16SXin LI parg.p_string = get_cmdbuf(); 48495270f73SXin LI if (parg.p_string == NULL) 48595270f73SXin LI return (MCA_MORE); 48633096f16SXin LI error("There is no --%s option", &parg); 48733096f16SXin LI return (MCA_DONE); 48833096f16SXin LI } 48933096f16SXin LI optgetname = FALSE; 49033096f16SXin LI cmd_reset(); 491a5f0fb15SPaul Saab } else 492a5f0fb15SPaul Saab { 49333096f16SXin LI if (is_erase_char(c)) 49433096f16SXin LI return (NO_MCA); 49533096f16SXin LI if (curropt != NULL) 49633096f16SXin LI /* We're getting the option parameter. */ 49733096f16SXin LI return (NO_MCA); 49833096f16SXin LI curropt = findopt(c); 49933096f16SXin LI if (curropt == NULL) 500a5f0fb15SPaul Saab { 50133096f16SXin LI parg.p_string = propt(c); 50233096f16SXin LI error("There is no %s option", &parg); 50333096f16SXin LI return (MCA_DONE); 50433096f16SXin LI } 505b7780dbeSXin LI opt_lower = ASCII_IS_LOWER(c); 50633096f16SXin LI } 50733096f16SXin LI /* 50833096f16SXin LI * If the option which was entered does not take a 50933096f16SXin LI * parameter, toggle the option immediately, 51033096f16SXin LI * so user doesn't have to hit RETURN. 51133096f16SXin LI */ 51233096f16SXin LI if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE || 51333096f16SXin LI !opt_has_param(curropt)) 51433096f16SXin LI { 515b7780dbeSXin LI toggle_option(curropt, opt_lower, "", optflag); 516a5f0fb15SPaul Saab return (MCA_DONE); 517a5f0fb15SPaul Saab } 518a5f0fb15SPaul Saab /* 51933096f16SXin LI * Display a prompt appropriate for the option parameter. 520a5f0fb15SPaul Saab */ 52133096f16SXin LI start_mca(A_OPT_TOGGLE, opt_prompt(curropt), (void*)NULL, 0); 522a5f0fb15SPaul Saab return (MCA_MORE); 52333096f16SXin LI } 524a5f0fb15SPaul Saab 525a5f0fb15SPaul Saab /* 52695270f73SXin LI * Normalize search type. 52795270f73SXin LI */ 528*d713e089SXin LI public int norm_search_type(int st) 52995270f73SXin LI { 53095270f73SXin LI /* WRAP and PAST_EOF are mutually exclusive. */ 53195270f73SXin LI if ((st & (SRCH_PAST_EOF|SRCH_WRAP)) == (SRCH_PAST_EOF|SRCH_WRAP)) 53295270f73SXin LI st ^= SRCH_PAST_EOF; 53395270f73SXin LI return st; 53495270f73SXin LI } 53595270f73SXin LI 53695270f73SXin LI /* 53733096f16SXin LI * Handle a char of a search command. 53833096f16SXin LI */ 539*d713e089SXin LI static int mca_search_char(int c) 54033096f16SXin LI { 54133096f16SXin LI int flag = 0; 54233096f16SXin LI 54333096f16SXin LI /* 544a5f0fb15SPaul Saab * Certain characters as the first char of 545a5f0fb15SPaul Saab * the pattern have special meaning: 546a5f0fb15SPaul Saab * ! Toggle the NO_MATCH flag 547a5f0fb15SPaul Saab * * Toggle the PAST_EOF flag 548a5f0fb15SPaul Saab * @ Toggle the FIRST_FILE flag 549a5f0fb15SPaul Saab */ 550a5f0fb15SPaul Saab if (len_cmdbuf() > 0) 55133096f16SXin LI return (NO_MCA); 552a5f0fb15SPaul Saab 553a5f0fb15SPaul Saab switch (c) 554a5f0fb15SPaul Saab { 555a5f0fb15SPaul Saab case '*': 556720c436cSXin LI if (less_is_more) 557a8f92a7cSPaul Saab break; 558a8f92a7cSPaul Saab case CONTROL('E'): /* ignore END of file */ 5597374caaaSXin LI if (mca != A_FILTER) 560a5f0fb15SPaul Saab flag = SRCH_PAST_EOF; 561a5f0fb15SPaul Saab break; 562a5f0fb15SPaul Saab case '@': 563720c436cSXin LI if (less_is_more) 564a8f92a7cSPaul Saab break; 565a8f92a7cSPaul Saab case CONTROL('F'): /* FIRST file */ 5667374caaaSXin LI if (mca != A_FILTER) 567a5f0fb15SPaul Saab flag = SRCH_FIRST_FILE; 568a5f0fb15SPaul Saab break; 569a5f0fb15SPaul Saab case CONTROL('K'): /* KEEP position */ 5707374caaaSXin LI if (mca != A_FILTER) 571a5f0fb15SPaul Saab flag = SRCH_NO_MOVE; 572a5f0fb15SPaul Saab break; 573*d713e089SXin LI case CONTROL('S'): { /* SUBSEARCH */ 574*d713e089SXin LI char buf[32]; 575*d713e089SXin LI SNPRINTF1(buf, sizeof(buf), "Sub-pattern (1-%d):", NUM_SEARCH_COLORS); 576*d713e089SXin LI clear_bot(); 577*d713e089SXin LI cmd_putstr(buf); 578*d713e089SXin LI flush(); 579*d713e089SXin LI c = getcc(); 580*d713e089SXin LI if (c >= '1' && c <= '0'+NUM_SEARCH_COLORS) 581*d713e089SXin LI flag = SRCH_SUBSEARCH(c-'0'); 582*d713e089SXin LI else 583*d713e089SXin LI flag = -1; /* calls mca_search() below to repaint */ 584*d713e089SXin LI break; } 5852235c7feSXin LI case CONTROL('W'): /* WRAP around */ 5862235c7feSXin LI if (mca != A_FILTER) 5872235c7feSXin LI flag = SRCH_WRAP; 5882235c7feSXin LI break; 589a5f0fb15SPaul Saab case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */ 590a5f0fb15SPaul Saab flag = SRCH_NO_REGEX; 591a5f0fb15SPaul Saab break; 592a5f0fb15SPaul Saab case CONTROL('N'): /* NOT match */ 593a5f0fb15SPaul Saab case '!': 594a5f0fb15SPaul Saab flag = SRCH_NO_MATCH; 595a5f0fb15SPaul Saab break; 596a5f0fb15SPaul Saab } 59733096f16SXin LI 598a5f0fb15SPaul Saab if (flag != 0) 599a5f0fb15SPaul Saab { 600*d713e089SXin LI if (flag != -1) 60195270f73SXin LI search_type = norm_search_type(search_type ^ flag); 602a5f0fb15SPaul Saab mca_search(); 603a5f0fb15SPaul Saab return (MCA_MORE); 604a5f0fb15SPaul Saab } 60533096f16SXin LI return (NO_MCA); 60633096f16SXin LI } 60733096f16SXin LI 60833096f16SXin LI /* 60933096f16SXin LI * Handle a character of a multi-character command. 61033096f16SXin LI */ 611*d713e089SXin LI static int mca_char(int c) 61233096f16SXin LI { 61333096f16SXin LI int ret; 61433096f16SXin LI 61533096f16SXin LI switch (mca) 61633096f16SXin LI { 61733096f16SXin LI case 0: 61833096f16SXin LI /* 61933096f16SXin LI * We're not in a multicharacter command. 62033096f16SXin LI */ 62133096f16SXin LI return (NO_MCA); 62233096f16SXin LI 62333096f16SXin LI case A_PREFIX: 62433096f16SXin LI /* 62533096f16SXin LI * In the prefix of a command. 62633096f16SXin LI * This not considered a multichar command 62733096f16SXin LI * (even tho it uses cmdbuf, etc.). 62833096f16SXin LI * It is handled in the commands() switch. 62933096f16SXin LI */ 63033096f16SXin LI return (NO_MCA); 63133096f16SXin LI 63233096f16SXin LI case A_DIGIT: 63333096f16SXin LI /* 63433096f16SXin LI * Entering digits of a number. 63533096f16SXin LI * Terminated by a non-digit. 63633096f16SXin LI */ 6372235c7feSXin LI if ((c >= '0' && c <= '9') || c == '.') 6382235c7feSXin LI break; 6392235c7feSXin LI switch (editchar(c, ECF_PEEK|ECF_NOHISTORY|ECF_NOCOMPLETE|ECF_NORIGHTLEFT)) 64033096f16SXin LI { 6412235c7feSXin LI case A_NOACTION: 6422235c7feSXin LI /* 6432235c7feSXin LI * Ignore this char and get another one. 6442235c7feSXin LI */ 6452235c7feSXin LI return (MCA_MORE); 6462235c7feSXin LI case A_INVALID: 64733096f16SXin LI /* 64833096f16SXin LI * Not part of the number. 64933096f16SXin LI * End the number and treat this char 65033096f16SXin LI * as a normal command character. 65133096f16SXin LI */ 65233096f16SXin LI number = cmd_int(&fraction); 653b7780dbeSXin LI clear_mca(); 65433096f16SXin LI cmd_accept(); 65533096f16SXin LI return (NO_MCA); 65633096f16SXin LI } 65733096f16SXin LI break; 65833096f16SXin LI 65933096f16SXin LI case A_OPT_TOGGLE: 66033096f16SXin LI ret = mca_opt_char(c); 66133096f16SXin LI if (ret != NO_MCA) 66233096f16SXin LI return (ret); 66333096f16SXin LI break; 66433096f16SXin LI 66533096f16SXin LI case A_F_SEARCH: 66633096f16SXin LI case A_B_SEARCH: 66733096f16SXin LI case A_FILTER: 66833096f16SXin LI ret = mca_search_char(c); 66933096f16SXin LI if (ret != NO_MCA) 67033096f16SXin LI return (ret); 67133096f16SXin LI break; 67233096f16SXin LI 67333096f16SXin LI default: 67433096f16SXin LI /* Other multicharacter command. */ 675a5f0fb15SPaul Saab break; 676a5f0fb15SPaul Saab } 677a5f0fb15SPaul Saab 678a5f0fb15SPaul Saab /* 67933096f16SXin LI * The multichar command is terminated by a newline. 680a5f0fb15SPaul Saab */ 681b2ea2440SXin LI if (is_newline_char(c)) 682a5f0fb15SPaul Saab { 683a5f0fb15SPaul Saab /* 684a5f0fb15SPaul Saab * Execute the command. 685a5f0fb15SPaul Saab */ 686a5f0fb15SPaul Saab exec_mca(); 687a5f0fb15SPaul Saab return (MCA_DONE); 688a5f0fb15SPaul Saab } 689a5f0fb15SPaul Saab 690a5f0fb15SPaul Saab /* 691a5f0fb15SPaul Saab * Append the char to the command buffer. 692a5f0fb15SPaul Saab */ 693a5f0fb15SPaul Saab if (cmd_char(c) == CC_QUIT) 694a5f0fb15SPaul Saab /* 695a5f0fb15SPaul Saab * Abort the multi-char command. 696a5f0fb15SPaul Saab */ 697a5f0fb15SPaul Saab return (MCA_DONE); 698a5f0fb15SPaul Saab 6992235c7feSXin LI switch (mca) 7002235c7feSXin LI { 7012235c7feSXin LI case A_F_BRACKET: 7022235c7feSXin LI case A_B_BRACKET: 7032235c7feSXin LI if (len_cmdbuf() >= 2) 704a5f0fb15SPaul Saab { 705a5f0fb15SPaul Saab /* 706a5f0fb15SPaul Saab * Special case for the bracket-matching commands. 707a5f0fb15SPaul Saab * Execute the command after getting exactly two 708a5f0fb15SPaul Saab * characters from the user. 709a5f0fb15SPaul Saab */ 710a5f0fb15SPaul Saab exec_mca(); 711a5f0fb15SPaul Saab return (MCA_DONE); 712a5f0fb15SPaul Saab } 7132235c7feSXin LI break; 7142235c7feSXin LI case A_F_SEARCH: 7152235c7feSXin LI case A_B_SEARCH: 7162235c7feSXin LI if (incr_search) 7172235c7feSXin LI { 7182235c7feSXin LI /* Incremental search: do a search after every input char. */ 719*d713e089SXin LI int st = (search_type & (SRCH_FORW|SRCH_BACK|SRCH_NO_MATCH|SRCH_NO_REGEX|SRCH_NO_MOVE|SRCH_WRAP|SRCH_SUBSEARCH_ALL)); 7202235c7feSXin LI char *pattern = get_cmdbuf(); 72195270f73SXin LI if (pattern == NULL) 72295270f73SXin LI return (MCA_MORE); 72395270f73SXin LI /* 72495270f73SXin LI * Must save updown_match because mca_search 72595270f73SXin LI * reinits it. That breaks history scrolling. 72695270f73SXin LI * {{ This is ugly. mca_search probably shouldn't call set_mlist. }} 72795270f73SXin LI */ 72895270f73SXin LI int save_updown_match = updown_match; 7292235c7feSXin LI cmd_exec(); 7302235c7feSXin LI if (*pattern == '\0') 7312235c7feSXin LI { 7322235c7feSXin LI /* User has backspaced to an empty pattern. */ 7332235c7feSXin LI undo_search(1); 7342235c7feSXin LI } else 7352235c7feSXin LI { 7362235c7feSXin LI if (search(st | SRCH_INCR, pattern, 1) != 0) 7372235c7feSXin LI /* No match, invalid pattern, etc. */ 7382235c7feSXin LI undo_search(1); 7392235c7feSXin LI } 7402235c7feSXin LI /* Redraw the search prompt and search string. */ 741*d713e089SXin LI if (!full_screen) 742*d713e089SXin LI { 743*d713e089SXin LI clear(); 744*d713e089SXin LI repaint(); 745*d713e089SXin LI } 74695270f73SXin LI mca_search1(); 74795270f73SXin LI updown_match = save_updown_match; 7482235c7feSXin LI cmd_repaint(NULL); 7492235c7feSXin LI } 7502235c7feSXin LI break; 7512235c7feSXin LI } 752a5f0fb15SPaul Saab 753a5f0fb15SPaul Saab /* 754a5f0fb15SPaul Saab * Need another character. 755a5f0fb15SPaul Saab */ 756a5f0fb15SPaul Saab return (MCA_MORE); 757a5f0fb15SPaul Saab } 758a5f0fb15SPaul Saab 759a5f0fb15SPaul Saab /* 760423c5ce5SXin LI * Discard any buffered file data. 761423c5ce5SXin LI */ 762*d713e089SXin LI static void clear_buffers(void) 763423c5ce5SXin LI { 764423c5ce5SXin LI if (!(ch_getflags() & CH_CANSEEK)) 765423c5ce5SXin LI return; 766423c5ce5SXin LI ch_flush(); 767423c5ce5SXin LI clr_linenum(); 768423c5ce5SXin LI #if HILITE_SEARCH 769423c5ce5SXin LI clr_hilite(); 770423c5ce5SXin LI #endif 771423c5ce5SXin LI } 772423c5ce5SXin LI 773423c5ce5SXin LI /* 774a5f0fb15SPaul Saab * Make sure the screen is displayed. 775a5f0fb15SPaul Saab */ 776*d713e089SXin LI static void make_display(void) 777a5f0fb15SPaul Saab { 778a5f0fb15SPaul Saab /* 779*d713e089SXin LI * If not full_screen, we can't rely on scrolling to fill the screen. 780*d713e089SXin LI * We need to clear and repaint screen before any change. 781*d713e089SXin LI */ 782*d713e089SXin LI if (!full_screen && !(quit_if_one_screen && one_screen)) 783*d713e089SXin LI clear(); 784*d713e089SXin LI /* 785a5f0fb15SPaul Saab * If nothing is displayed yet, display starting from initial_scrpos. 786a5f0fb15SPaul Saab */ 787a5f0fb15SPaul Saab if (empty_screen()) 788a5f0fb15SPaul Saab { 789a5f0fb15SPaul Saab if (initial_scrpos.pos == NULL_POSITION) 790a5f0fb15SPaul Saab jump_loc(ch_zero(), 1); 791a5f0fb15SPaul Saab else 792a5f0fb15SPaul Saab jump_loc(initial_scrpos.pos, initial_scrpos.ln); 793*d713e089SXin LI } else if (screen_trashed || !full_screen) 794a5f0fb15SPaul Saab { 795423c5ce5SXin LI int save_top_scroll = top_scroll; 796423c5ce5SXin LI int save_ignore_eoi = ignore_eoi; 797a5f0fb15SPaul Saab top_scroll = 1; 798423c5ce5SXin LI ignore_eoi = 0; 799423c5ce5SXin LI if (screen_trashed == 2) 800423c5ce5SXin LI { 801423c5ce5SXin LI /* Special case used by ignore_eoi: re-open the input file 802423c5ce5SXin LI * and jump to the end of the file. */ 803423c5ce5SXin LI reopen_curr_ifile(); 804423c5ce5SXin LI jump_forw(); 805423c5ce5SXin LI } 806a5f0fb15SPaul Saab repaint(); 807a5f0fb15SPaul Saab top_scroll = save_top_scroll; 808423c5ce5SXin LI ignore_eoi = save_ignore_eoi; 809a5f0fb15SPaul Saab } 810a5f0fb15SPaul Saab } 811a5f0fb15SPaul Saab 812a5f0fb15SPaul Saab /* 813a5f0fb15SPaul Saab * Display the appropriate prompt. 814a5f0fb15SPaul Saab */ 815*d713e089SXin LI static void prompt(void) 816a5f0fb15SPaul Saab { 8171ea31627SRobert Watson constant char *p; 818a5f0fb15SPaul Saab 819b2ea2440SXin LI if (ungot != NULL && ungot->ug_char != CHAR_END_COMMAND) 820a5f0fb15SPaul Saab { 821a5f0fb15SPaul Saab /* 822a5f0fb15SPaul Saab * No prompt necessary if commands are from 823a5f0fb15SPaul Saab * ungotten chars rather than from the user. 824a5f0fb15SPaul Saab */ 825a5f0fb15SPaul Saab return; 826a5f0fb15SPaul Saab } 827a5f0fb15SPaul Saab 828a5f0fb15SPaul Saab /* 829a5f0fb15SPaul Saab * Make sure the screen is displayed. 830a5f0fb15SPaul Saab */ 831a5f0fb15SPaul Saab make_display(); 832a5f0fb15SPaul Saab bottompos = position(BOTTOM_PLUS_ONE); 833a5f0fb15SPaul Saab 834a5f0fb15SPaul Saab /* 8357374caaaSXin LI * If we've hit EOF on the last file and the -E flag is set, quit. 836a5f0fb15SPaul Saab */ 8377374caaaSXin LI if (get_quit_at_eof() == OPT_ONPLUS && 8387374caaaSXin LI eof_displayed() && !(ch_getflags() & CH_HELPFILE) && 839a5f0fb15SPaul Saab next_ifile(curr_ifile) == NULL_IFILE) 840a5f0fb15SPaul Saab quit(QUIT_OK); 8417374caaaSXin LI 842a5f0fb15SPaul Saab /* 8437374caaaSXin LI * If the entire file is displayed and the -F flag is set, quit. 844a5f0fb15SPaul Saab */ 8457374caaaSXin LI if (quit_if_one_screen && 8467374caaaSXin LI entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) && 847a5f0fb15SPaul Saab next_ifile(curr_ifile) == NULL_IFILE) 848a5f0fb15SPaul Saab quit(QUIT_OK); 84930a1828cSXin LI quit_if_one_screen = FALSE; /* only get one chance at this */ 850a5f0fb15SPaul Saab 8518fd4165cSPaul Saab #if MSDOS_COMPILER==WIN32C 8528fd4165cSPaul Saab /* 8538fd4165cSPaul Saab * In Win32, display the file name in the window title. 8548fd4165cSPaul Saab */ 8558fd4165cSPaul Saab if (!(ch_getflags() & CH_HELPFILE)) 856b7780dbeSXin LI { 857b7780dbeSXin LI WCHAR w[MAX_PATH+16]; 85895270f73SXin LI p = pr_expand("Less?f - %f."); 859b7780dbeSXin LI MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w)); 860b7780dbeSXin LI SetConsoleTitleW(w); 861b7780dbeSXin LI } 8628fd4165cSPaul Saab #endif 863b7780dbeSXin LI 864a5f0fb15SPaul Saab /* 865a5f0fb15SPaul Saab * Select the proper prompt and display it. 866a5f0fb15SPaul Saab */ 867720c436cSXin LI /* 868720c436cSXin LI * If the previous action was a forward movement, 869720c436cSXin LI * don't clear the bottom line of the display; 870720c436cSXin LI * just print the prompt since the forward movement guarantees 871720c436cSXin LI * that we're in the right position to display the prompt. 872720c436cSXin LI * Clearing the line could cause a problem: for example, if the last 873720c436cSXin LI * line displayed ended at the right screen edge without a newline, 874720c436cSXin LI * then clearing would clear the last displayed line rather than 875720c436cSXin LI * the prompt line. 876720c436cSXin LI */ 877720c436cSXin LI if (!forw_prompt) 878720c436cSXin LI clear_bot(); 879a5f0fb15SPaul Saab clear_cmd(); 880720c436cSXin LI forw_prompt = 0; 881a5f0fb15SPaul Saab p = pr_string(); 8822235c7feSXin LI #if HILITE_SEARCH 8837374caaaSXin LI if (is_filtering()) 8847374caaaSXin LI putstr("& "); 8852235c7feSXin LI #endif 88689dd99dcSXin LI if (p == NULL || *p == '\0') 8872235c7feSXin LI { 8882235c7feSXin LI at_enter(AT_NORMAL|AT_COLOR_PROMPT); 889a5f0fb15SPaul Saab putchr(':'); 8902235c7feSXin LI at_exit(); 8912235c7feSXin LI } else 892a5f0fb15SPaul Saab { 893b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 894b7780dbeSXin LI WCHAR w[MAX_PATH*2]; 895b7780dbeSXin LI char a[MAX_PATH*2]; 896b7780dbeSXin LI MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w)); 897b7780dbeSXin LI WideCharToMultiByte(utf_mode ? CP_UTF8 : GetConsoleOutputCP(), 898b7780dbeSXin LI 0, w, -1, a, sizeof(a), NULL, NULL); 899b7780dbeSXin LI p = a; 900b7780dbeSXin LI #endif 90195270f73SXin LI load_line(p); 90295270f73SXin LI put_line(); 903a5f0fb15SPaul Saab } 904720c436cSXin LI clear_eol(); 905a5f0fb15SPaul Saab } 906a5f0fb15SPaul Saab 907a5f0fb15SPaul Saab /* 908a5f0fb15SPaul Saab * Display the less version message. 909a5f0fb15SPaul Saab */ 910*d713e089SXin LI public void dispversion(void) 911a5f0fb15SPaul Saab { 912a5f0fb15SPaul Saab PARG parg; 913a5f0fb15SPaul Saab 914a5f0fb15SPaul Saab parg.p_string = version; 915a5f0fb15SPaul Saab error("less %s", &parg); 916a5f0fb15SPaul Saab } 917a5f0fb15SPaul Saab 918a5f0fb15SPaul Saab /* 919b2ea2440SXin LI * Return a character to complete a partial command, if possible. 920b2ea2440SXin LI */ 921*d713e089SXin LI static LWCHAR getcc_end_command(void) 922b2ea2440SXin LI { 923b2ea2440SXin LI switch (mca) 924b2ea2440SXin LI { 925b2ea2440SXin LI case A_DIGIT: 926b2ea2440SXin LI /* We have a number but no command. Treat as #g. */ 927b2ea2440SXin LI return ('g'); 928b2ea2440SXin LI case A_F_SEARCH: 929b2ea2440SXin LI case A_B_SEARCH: 930*d713e089SXin LI case A_FILTER: 931b2ea2440SXin LI /* We have "/string" but no newline. Add the \n. */ 932b2ea2440SXin LI return ('\n'); 933b2ea2440SXin LI default: 934b2ea2440SXin LI /* Some other incomplete command. Let user complete it. */ 9352235c7feSXin LI return ((ungot == NULL) ? getchr() : 0); 936b2ea2440SXin LI } 937b2ea2440SXin LI } 938b2ea2440SXin LI 939b2ea2440SXin LI /* 940a5f0fb15SPaul Saab * Get command character. 941a5f0fb15SPaul Saab * The character normally comes from the keyboard, 942a5f0fb15SPaul Saab * but may come from ungotten characters 943a5f0fb15SPaul Saab * (characters previously given to ungetcc or ungetsc). 944a5f0fb15SPaul Saab */ 945*d713e089SXin LI static LWCHAR getccu(void) 946a5f0fb15SPaul Saab { 9472235c7feSXin LI LWCHAR c = 0; 9482235c7feSXin LI while (c == 0) 9492235c7feSXin LI { 950a15691bfSXin LI if (ungot == NULL) 95133096f16SXin LI { 952b2ea2440SXin LI /* Normal case: no ungotten chars. 953b2ea2440SXin LI * Get char from the user. */ 954b2ea2440SXin LI c = getchr(); 955b2ea2440SXin LI } else 956a15691bfSXin LI { 957b2ea2440SXin LI /* Ungotten chars available: 958b2ea2440SXin LI * Take the top of stack (most recent). */ 959a15691bfSXin LI struct ungot *ug = ungot; 960b2ea2440SXin LI c = ug->ug_char; 961a15691bfSXin LI ungot = ug->ug_next; 962a15691bfSXin LI free(ug); 963a5f0fb15SPaul Saab 964b2ea2440SXin LI if (c == CHAR_END_COMMAND) 965b2ea2440SXin LI c = getcc_end_command(); 966a5f0fb15SPaul Saab } 9672235c7feSXin LI } 96833096f16SXin LI return (c); 96933096f16SXin LI } 970b2ea2440SXin LI 971b2ea2440SXin LI /* 972b2ea2440SXin LI * Get a command character, but if we receive the orig sequence, 973b2ea2440SXin LI * convert it to the repl sequence. 974b2ea2440SXin LI */ 975*d713e089SXin LI static LWCHAR getcc_repl(char constant *orig, char constant *repl, LWCHAR (*gr_getc)(void), void (*gr_ungetc)(LWCHAR)) 976b2ea2440SXin LI { 977b2ea2440SXin LI LWCHAR c; 978b2ea2440SXin LI LWCHAR keys[16]; 979b2ea2440SXin LI int ki = 0; 980b2ea2440SXin LI 981b2ea2440SXin LI c = (*gr_getc)(); 982b2ea2440SXin LI if (orig == NULL || orig[0] == '\0') 983b2ea2440SXin LI return c; 984b2ea2440SXin LI for (;;) 985b2ea2440SXin LI { 986b2ea2440SXin LI keys[ki] = c; 987b2ea2440SXin LI if (c != orig[ki] || ki >= sizeof(keys)-1) 988b2ea2440SXin LI { 989b2ea2440SXin LI /* This is not orig we have been receiving. 990b2ea2440SXin LI * If we have stashed chars in keys[], 991b2ea2440SXin LI * unget them and return the first one. */ 992b2ea2440SXin LI while (ki > 0) 993b2ea2440SXin LI (*gr_ungetc)(keys[ki--]); 994b2ea2440SXin LI return keys[0]; 995b2ea2440SXin LI } 996b2ea2440SXin LI if (orig[++ki] == '\0') 997b2ea2440SXin LI { 998b2ea2440SXin LI /* We've received the full orig sequence. 999b2ea2440SXin LI * Return the repl sequence. */ 1000b2ea2440SXin LI ki = strlen(repl)-1; 1001b2ea2440SXin LI while (ki > 0) 1002b2ea2440SXin LI (*gr_ungetc)(repl[ki--]); 1003b2ea2440SXin LI return repl[0]; 1004b2ea2440SXin LI } 1005b2ea2440SXin LI /* We've received a partial orig sequence (ki chars of it). 1006b2ea2440SXin LI * Get next char and see if it continues to match orig. */ 1007b2ea2440SXin LI c = (*gr_getc)(); 1008b2ea2440SXin LI } 1009b2ea2440SXin LI } 1010b2ea2440SXin LI 1011b2ea2440SXin LI /* 1012b2ea2440SXin LI * Get command character. 1013b2ea2440SXin LI */ 1014*d713e089SXin LI public int getcc(void) 1015b2ea2440SXin LI { 1016b2ea2440SXin LI /* Replace kent (keypad Enter) with a newline. */ 1017b2ea2440SXin LI return getcc_repl(kent, "\n", getccu, ungetcc); 101833096f16SXin LI } 101933096f16SXin LI 1020a5f0fb15SPaul Saab /* 1021a5f0fb15SPaul Saab * "Unget" a command character. 1022a5f0fb15SPaul Saab * The next getcc() will return this character. 1023a5f0fb15SPaul Saab */ 1024*d713e089SXin LI public void ungetcc(LWCHAR c) 1025a5f0fb15SPaul Saab { 102633096f16SXin LI struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); 102733096f16SXin LI 1028b2ea2440SXin LI ug->ug_char = c; 102933096f16SXin LI ug->ug_next = ungot; 103033096f16SXin LI ungot = ug; 1031a5f0fb15SPaul Saab } 1032a5f0fb15SPaul Saab 1033a5f0fb15SPaul Saab /* 10342235c7feSXin LI * "Unget" a command character. 10352235c7feSXin LI * If any other chars are already ungotten, put this one after those. 10362235c7feSXin LI */ 1037*d713e089SXin LI public void ungetcc_back(LWCHAR c) 10382235c7feSXin LI { 10392235c7feSXin LI struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); 10402235c7feSXin LI ug->ug_char = c; 10412235c7feSXin LI ug->ug_next = NULL; 10422235c7feSXin LI if (ungot == NULL) 10432235c7feSXin LI ungot = ug; 10442235c7feSXin LI else 10452235c7feSXin LI { 10462235c7feSXin LI struct ungot *pu; 10472235c7feSXin LI for (pu = ungot; pu->ug_next != NULL; pu = pu->ug_next) 10482235c7feSXin LI continue; 10492235c7feSXin LI pu->ug_next = ug; 10502235c7feSXin LI } 10512235c7feSXin LI } 10522235c7feSXin LI 10532235c7feSXin LI /* 1054a5f0fb15SPaul Saab * Unget a whole string of command characters. 1055a5f0fb15SPaul Saab * The next sequence of getcc()'s will return this string. 1056a5f0fb15SPaul Saab */ 1057*d713e089SXin LI public void ungetsc(char *s) 1058a5f0fb15SPaul Saab { 10592235c7feSXin LI while (*s != '\0') 10602235c7feSXin LI ungetcc_back(*s++); 1061a5f0fb15SPaul Saab } 1062a5f0fb15SPaul Saab 1063a5f0fb15SPaul Saab /* 1064b2ea2440SXin LI * Peek the next command character, without consuming it. 1065b2ea2440SXin LI */ 1066*d713e089SXin LI public LWCHAR peekcc(void) 1067b2ea2440SXin LI { 1068b2ea2440SXin LI LWCHAR c = getcc(); 1069b2ea2440SXin LI ungetcc(c); 1070b2ea2440SXin LI return c; 1071b2ea2440SXin LI } 1072b2ea2440SXin LI 1073b2ea2440SXin LI /* 1074a5f0fb15SPaul Saab * Search for a pattern, possibly in multiple files. 1075a5f0fb15SPaul Saab * If SRCH_FIRST_FILE is set, begin searching at the first file. 1076a5f0fb15SPaul Saab * If SRCH_PAST_EOF is set, continue the search thru multiple files. 1077a5f0fb15SPaul Saab */ 1078*d713e089SXin LI static void multi_search(char *pattern, int n, int silent) 1079a5f0fb15SPaul Saab { 10801ea31627SRobert Watson int nomore; 1081a5f0fb15SPaul Saab IFILE save_ifile; 1082a5f0fb15SPaul Saab int changed_file; 1083a5f0fb15SPaul Saab 1084a5f0fb15SPaul Saab changed_file = 0; 1085a5f0fb15SPaul Saab save_ifile = save_curr_ifile(); 1086a5f0fb15SPaul Saab 1087*d713e089SXin LI if ((search_type & (SRCH_FORW|SRCH_BACK)) == 0) 1088*d713e089SXin LI search_type |= SRCH_FORW; 1089a5f0fb15SPaul Saab if (search_type & SRCH_FIRST_FILE) 1090a5f0fb15SPaul Saab { 1091a5f0fb15SPaul Saab /* 1092a5f0fb15SPaul Saab * Start at the first (or last) file 1093a5f0fb15SPaul Saab * in the command line list. 1094a5f0fb15SPaul Saab */ 1095a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 1096a5f0fb15SPaul Saab nomore = edit_first(); 1097a5f0fb15SPaul Saab else 1098a5f0fb15SPaul Saab nomore = edit_last(); 1099a5f0fb15SPaul Saab if (nomore) 1100a5f0fb15SPaul Saab { 1101a5f0fb15SPaul Saab unsave_ifile(save_ifile); 1102a5f0fb15SPaul Saab return; 1103a5f0fb15SPaul Saab } 1104a5f0fb15SPaul Saab changed_file = 1; 1105a5f0fb15SPaul Saab search_type &= ~SRCH_FIRST_FILE; 1106a5f0fb15SPaul Saab } 1107a5f0fb15SPaul Saab 1108a5f0fb15SPaul Saab for (;;) 1109a5f0fb15SPaul Saab { 1110a5f0fb15SPaul Saab n = search(search_type, pattern, n); 1111a5f0fb15SPaul Saab /* 1112a5f0fb15SPaul Saab * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared 1113a5f0fb15SPaul Saab * after being used once. This allows "n" to work after 1114a5f0fb15SPaul Saab * using a /@@ search. 1115a5f0fb15SPaul Saab */ 1116a5f0fb15SPaul Saab search_type &= ~SRCH_NO_MOVE; 1117*d713e089SXin LI last_search_type = search_type; 1118a5f0fb15SPaul Saab if (n == 0) 1119a5f0fb15SPaul Saab { 1120a5f0fb15SPaul Saab /* 1121a5f0fb15SPaul Saab * Found it. 1122a5f0fb15SPaul Saab */ 1123a5f0fb15SPaul Saab unsave_ifile(save_ifile); 1124a5f0fb15SPaul Saab return; 1125a5f0fb15SPaul Saab } 1126a5f0fb15SPaul Saab 1127a5f0fb15SPaul Saab if (n < 0) 1128a5f0fb15SPaul Saab /* 1129a5f0fb15SPaul Saab * Some kind of error in the search. 1130a5f0fb15SPaul Saab * Error message has been printed by search(). 1131a5f0fb15SPaul Saab */ 1132a5f0fb15SPaul Saab break; 1133a5f0fb15SPaul Saab 1134a5f0fb15SPaul Saab if ((search_type & SRCH_PAST_EOF) == 0) 1135a5f0fb15SPaul Saab /* 1136a5f0fb15SPaul Saab * We didn't find a match, but we're 1137a5f0fb15SPaul Saab * supposed to search only one file. 1138a5f0fb15SPaul Saab */ 1139a5f0fb15SPaul Saab break; 1140a5f0fb15SPaul Saab /* 1141a5f0fb15SPaul Saab * Move on to the next file. 1142a5f0fb15SPaul Saab */ 1143a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 1144a5f0fb15SPaul Saab nomore = edit_next(1); 1145a5f0fb15SPaul Saab else 1146a5f0fb15SPaul Saab nomore = edit_prev(1); 1147a5f0fb15SPaul Saab if (nomore) 1148a5f0fb15SPaul Saab break; 1149a5f0fb15SPaul Saab changed_file = 1; 1150a5f0fb15SPaul Saab } 1151a5f0fb15SPaul Saab 1152a5f0fb15SPaul Saab /* 1153a5f0fb15SPaul Saab * Didn't find it. 1154a5f0fb15SPaul Saab * Print an error message if we haven't already. 1155a5f0fb15SPaul Saab */ 1156a15691bfSXin LI if (n > 0 && !silent) 1157a5f0fb15SPaul Saab error("Pattern not found", NULL_PARG); 1158a5f0fb15SPaul Saab 1159a5f0fb15SPaul Saab if (changed_file) 1160a5f0fb15SPaul Saab { 1161a5f0fb15SPaul Saab /* 1162a5f0fb15SPaul Saab * Restore the file we were originally viewing. 1163a5f0fb15SPaul Saab */ 1164a5f0fb15SPaul Saab reedit_ifile(save_ifile); 116589dd99dcSXin LI } else 116689dd99dcSXin LI { 116789dd99dcSXin LI unsave_ifile(save_ifile); 1168a5f0fb15SPaul Saab } 1169a5f0fb15SPaul Saab } 1170a5f0fb15SPaul Saab 1171a5f0fb15SPaul Saab /* 117296e55cc7SXin LI * Forward forever, or until a highlighted line appears. 117396e55cc7SXin LI */ 1174*d713e089SXin LI static int forw_loop(int until_hilite) 117596e55cc7SXin LI { 117696e55cc7SXin LI POSITION curr_len; 117796e55cc7SXin LI 117896e55cc7SXin LI if (ch_getflags() & CH_HELPFILE) 117996e55cc7SXin LI return (A_NOACTION); 118096e55cc7SXin LI 118196e55cc7SXin LI cmd_exec(); 1182a15691bfSXin LI jump_forw_buffered(); 118396e55cc7SXin LI curr_len = ch_length(); 118496e55cc7SXin LI highest_hilite = until_hilite ? curr_len : NULL_POSITION; 118596e55cc7SXin LI ignore_eoi = 1; 118696e55cc7SXin LI while (!sigs) 118796e55cc7SXin LI { 118896e55cc7SXin LI if (until_hilite && highest_hilite > curr_len) 118996e55cc7SXin LI { 119096e55cc7SXin LI bell(); 119196e55cc7SXin LI break; 119296e55cc7SXin LI } 119396e55cc7SXin LI make_display(); 119496e55cc7SXin LI forward(1, 0, 0); 119596e55cc7SXin LI } 119696e55cc7SXin LI ignore_eoi = 0; 1197e2449719SXin LI ch_set_eof(); 119896e55cc7SXin LI 119996e55cc7SXin LI /* 120096e55cc7SXin LI * This gets us back in "F mode" after processing 120196e55cc7SXin LI * a non-abort signal (e.g. window-change). 120296e55cc7SXin LI */ 120396e55cc7SXin LI if (sigs && !ABORT_SIGS()) 1204e2449719SXin LI return (until_hilite ? A_F_UNTIL_HILITE : A_F_FOREVER); 1205e2449719SXin LI 120696e55cc7SXin LI return (A_NOACTION); 120796e55cc7SXin LI } 120896e55cc7SXin LI 120996e55cc7SXin LI /* 1210a5f0fb15SPaul Saab * Main command processor. 1211a5f0fb15SPaul Saab * Accept and execute commands until a quit command. 1212a5f0fb15SPaul Saab */ 1213*d713e089SXin LI public void commands(void) 1214a5f0fb15SPaul Saab { 12151ea31627SRobert Watson int c; 12161ea31627SRobert Watson int action; 12171ea31627SRobert Watson char *cbuf; 1218a5f0fb15SPaul Saab int newaction; 12192235c7feSXin LI int save_jump_sline; 1220a5f0fb15SPaul Saab int save_search_type; 1221a5f0fb15SPaul Saab char *extra; 1222a5f0fb15SPaul Saab char tbuf[2]; 1223a5f0fb15SPaul Saab PARG parg; 1224a5f0fb15SPaul Saab IFILE old_ifile; 1225a5f0fb15SPaul Saab IFILE new_ifile; 12268fd4165cSPaul Saab char *tagfile; 1227a5f0fb15SPaul Saab 1228a5f0fb15SPaul Saab search_type = SRCH_FORW; 1229a5f0fb15SPaul Saab wscroll = (sc_height + 1) / 2; 1230a5f0fb15SPaul Saab newaction = A_NOACTION; 1231a5f0fb15SPaul Saab 1232a5f0fb15SPaul Saab for (;;) 1233a5f0fb15SPaul Saab { 1234b7780dbeSXin LI clear_mca(); 1235a5f0fb15SPaul Saab cmd_accept(); 1236a5f0fb15SPaul Saab number = 0; 123733096f16SXin LI curropt = NULL; 1238a5f0fb15SPaul Saab 1239a5f0fb15SPaul Saab /* 1240a5f0fb15SPaul Saab * See if any signals need processing. 1241a5f0fb15SPaul Saab */ 1242a5f0fb15SPaul Saab if (sigs) 1243a5f0fb15SPaul Saab { 1244a5f0fb15SPaul Saab psignals(); 1245a5f0fb15SPaul Saab if (quitting) 1246a5f0fb15SPaul Saab quit(QUIT_SAVED_STATUS); 1247a5f0fb15SPaul Saab } 1248a5f0fb15SPaul Saab 1249a5f0fb15SPaul Saab /* 1250a5f0fb15SPaul Saab * See if window size changed, for systems that don't 1251a5f0fb15SPaul Saab * generate SIGWINCH. 1252a5f0fb15SPaul Saab */ 1253a5f0fb15SPaul Saab check_winch(); 1254a5f0fb15SPaul Saab 1255a5f0fb15SPaul Saab /* 1256a5f0fb15SPaul Saab * Display prompt and accept a character. 1257a5f0fb15SPaul Saab */ 1258a5f0fb15SPaul Saab cmd_reset(); 1259a5f0fb15SPaul Saab prompt(); 1260a5f0fb15SPaul Saab if (sigs) 1261a5f0fb15SPaul Saab continue; 1262a5f0fb15SPaul Saab if (newaction == A_NOACTION) 1263a5f0fb15SPaul Saab c = getcc(); 1264a5f0fb15SPaul Saab 1265a5f0fb15SPaul Saab again: 1266a5f0fb15SPaul Saab if (sigs) 1267a5f0fb15SPaul Saab continue; 1268a5f0fb15SPaul Saab 1269a5f0fb15SPaul Saab if (newaction != A_NOACTION) 1270a5f0fb15SPaul Saab { 1271a5f0fb15SPaul Saab action = newaction; 1272a5f0fb15SPaul Saab newaction = A_NOACTION; 1273a5f0fb15SPaul Saab } else 1274a5f0fb15SPaul Saab { 1275a5f0fb15SPaul Saab /* 1276a5f0fb15SPaul Saab * If we are in a multicharacter command, call mca_char. 1277a5f0fb15SPaul Saab * Otherwise we call fcmd_decode to determine the 1278a5f0fb15SPaul Saab * action to be performed. 1279a5f0fb15SPaul Saab */ 1280a5f0fb15SPaul Saab if (mca) 1281a5f0fb15SPaul Saab switch (mca_char(c)) 1282a5f0fb15SPaul Saab { 1283a5f0fb15SPaul Saab case MCA_MORE: 1284a5f0fb15SPaul Saab /* 1285a5f0fb15SPaul Saab * Need another character. 1286a5f0fb15SPaul Saab */ 1287a5f0fb15SPaul Saab c = getcc(); 1288a5f0fb15SPaul Saab goto again; 1289a5f0fb15SPaul Saab case MCA_DONE: 1290a5f0fb15SPaul Saab /* 1291a5f0fb15SPaul Saab * Command has been handled by mca_char. 1292a5f0fb15SPaul Saab * Start clean with a prompt. 1293a5f0fb15SPaul Saab */ 1294a5f0fb15SPaul Saab continue; 1295a5f0fb15SPaul Saab case NO_MCA: 1296a5f0fb15SPaul Saab /* 1297a5f0fb15SPaul Saab * Not a multi-char command 1298a5f0fb15SPaul Saab * (at least, not anymore). 1299a5f0fb15SPaul Saab */ 1300a5f0fb15SPaul Saab break; 1301a5f0fb15SPaul Saab } 1302a5f0fb15SPaul Saab 1303a5f0fb15SPaul Saab /* 1304a5f0fb15SPaul Saab * Decode the command character and decide what to do. 1305a5f0fb15SPaul Saab */ 1306a5f0fb15SPaul Saab if (mca) 1307a5f0fb15SPaul Saab { 1308a5f0fb15SPaul Saab /* 1309a5f0fb15SPaul Saab * We're in a multichar command. 1310a5f0fb15SPaul Saab * Add the character to the command buffer 1311a5f0fb15SPaul Saab * and display it on the screen. 1312a5f0fb15SPaul Saab * If the user backspaces past the start 1313a5f0fb15SPaul Saab * of the line, abort the command. 1314a5f0fb15SPaul Saab */ 1315a5f0fb15SPaul Saab if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0) 1316a5f0fb15SPaul Saab continue; 1317a5f0fb15SPaul Saab cbuf = get_cmdbuf(); 131895270f73SXin LI if (cbuf == NULL) 131995270f73SXin LI continue; 1320a5f0fb15SPaul Saab } else 1321a5f0fb15SPaul Saab { 1322a5f0fb15SPaul Saab /* 1323a5f0fb15SPaul Saab * Don't use cmd_char if we're starting fresh 1324a5f0fb15SPaul Saab * at the beginning of a command, because we 1325a5f0fb15SPaul Saab * don't want to echo the command until we know 1326a5f0fb15SPaul Saab * it is a multichar command. We also don't 1327a5f0fb15SPaul Saab * want erase_char/kill_char to be treated 1328a5f0fb15SPaul Saab * as line editing characters. 1329a5f0fb15SPaul Saab */ 1330a5f0fb15SPaul Saab tbuf[0] = c; 1331a5f0fb15SPaul Saab tbuf[1] = '\0'; 1332a5f0fb15SPaul Saab cbuf = tbuf; 1333a5f0fb15SPaul Saab } 1334a5f0fb15SPaul Saab extra = NULL; 1335a5f0fb15SPaul Saab action = fcmd_decode(cbuf, &extra); 1336a5f0fb15SPaul Saab /* 1337a5f0fb15SPaul Saab * If an "extra" string was returned, 1338a5f0fb15SPaul Saab * process it as a string of command characters. 1339a5f0fb15SPaul Saab */ 1340a5f0fb15SPaul Saab if (extra != NULL) 1341a5f0fb15SPaul Saab ungetsc(extra); 1342a5f0fb15SPaul Saab } 1343a5f0fb15SPaul Saab /* 1344a5f0fb15SPaul Saab * Clear the cmdbuf string. 1345a5f0fb15SPaul Saab * (But not if we're in the prefix of a command, 1346a5f0fb15SPaul Saab * because the partial command string is kept there.) 1347a5f0fb15SPaul Saab */ 1348a5f0fb15SPaul Saab if (action != A_PREFIX) 1349a5f0fb15SPaul Saab cmd_reset(); 1350a5f0fb15SPaul Saab 1351a5f0fb15SPaul Saab switch (action) 1352a5f0fb15SPaul Saab { 1353a5f0fb15SPaul Saab case A_DIGIT: 1354a5f0fb15SPaul Saab /* 1355a5f0fb15SPaul Saab * First digit of a number. 1356a5f0fb15SPaul Saab */ 1357a5f0fb15SPaul Saab start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE); 1358a5f0fb15SPaul Saab goto again; 1359a5f0fb15SPaul Saab 1360a5f0fb15SPaul Saab case A_F_WINDOW: 1361a5f0fb15SPaul Saab /* 1362a5f0fb15SPaul Saab * Forward one window (and set the window size). 1363a5f0fb15SPaul Saab */ 1364a5f0fb15SPaul Saab if (number > 0) 13651ede1615STim J. Robbins swindow = (int) number; 1366a5f0fb15SPaul Saab /* FALLTHRU */ 1367a5f0fb15SPaul Saab case A_F_SCREEN: 1368a5f0fb15SPaul Saab /* 1369a5f0fb15SPaul Saab * Forward one screen. 1370a5f0fb15SPaul Saab */ 1371a5f0fb15SPaul Saab if (number <= 0) 1372a5f0fb15SPaul Saab number = get_swindow(); 1373a5f0fb15SPaul Saab cmd_exec(); 1374a5f0fb15SPaul Saab if (show_attn) 1375a5f0fb15SPaul Saab set_attnpos(bottompos); 13761ede1615STim J. Robbins forward((int) number, 0, 1); 1377a5f0fb15SPaul Saab break; 1378a5f0fb15SPaul Saab 1379a5f0fb15SPaul Saab case A_B_WINDOW: 1380a5f0fb15SPaul Saab /* 1381a5f0fb15SPaul Saab * Backward one window (and set the window size). 1382a5f0fb15SPaul Saab */ 1383a5f0fb15SPaul Saab if (number > 0) 13841ede1615STim J. Robbins swindow = (int) number; 1385a5f0fb15SPaul Saab /* FALLTHRU */ 1386a5f0fb15SPaul Saab case A_B_SCREEN: 1387a5f0fb15SPaul Saab /* 1388a5f0fb15SPaul Saab * Backward one screen. 1389a5f0fb15SPaul Saab */ 1390a5f0fb15SPaul Saab if (number <= 0) 1391a5f0fb15SPaul Saab number = get_swindow(); 1392a5f0fb15SPaul Saab cmd_exec(); 13931ede1615STim J. Robbins backward((int) number, 0, 1); 1394a5f0fb15SPaul Saab break; 1395a5f0fb15SPaul Saab 1396a5f0fb15SPaul Saab case A_F_LINE: 1397a5f0fb15SPaul Saab /* 1398a5f0fb15SPaul Saab * Forward N (default 1) line. 1399a5f0fb15SPaul Saab */ 1400a5f0fb15SPaul Saab if (number <= 0) 1401a5f0fb15SPaul Saab number = 1; 1402a5f0fb15SPaul Saab cmd_exec(); 1403a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS && number > 1) 1404a5f0fb15SPaul Saab set_attnpos(bottompos); 14051ede1615STim J. Robbins forward((int) number, 0, 0); 1406a5f0fb15SPaul Saab break; 1407a5f0fb15SPaul Saab 1408a5f0fb15SPaul Saab case A_B_LINE: 1409a5f0fb15SPaul Saab /* 1410a5f0fb15SPaul Saab * Backward N (default 1) line. 1411a5f0fb15SPaul Saab */ 1412a5f0fb15SPaul Saab if (number <= 0) 1413a5f0fb15SPaul Saab number = 1; 1414a5f0fb15SPaul Saab cmd_exec(); 14151ede1615STim J. Robbins backward((int) number, 0, 0); 1416a5f0fb15SPaul Saab break; 1417a5f0fb15SPaul Saab 1418b7780dbeSXin LI case A_F_MOUSE: 1419b7780dbeSXin LI /* 1420b7780dbeSXin LI * Forward wheel_lines lines. 1421b7780dbeSXin LI */ 1422b7780dbeSXin LI cmd_exec(); 1423b7780dbeSXin LI forward(wheel_lines, 0, 0); 1424b7780dbeSXin LI break; 1425b7780dbeSXin LI 1426b7780dbeSXin LI case A_B_MOUSE: 1427b7780dbeSXin LI /* 1428b7780dbeSXin LI * Backward wheel_lines lines. 1429b7780dbeSXin LI */ 1430b7780dbeSXin LI cmd_exec(); 1431b7780dbeSXin LI backward(wheel_lines, 0, 0); 1432b7780dbeSXin LI break; 1433b7780dbeSXin LI 1434a5f0fb15SPaul Saab case A_FF_LINE: 1435a5f0fb15SPaul Saab /* 1436a5f0fb15SPaul Saab * Force forward N (default 1) line. 1437a5f0fb15SPaul Saab */ 1438a5f0fb15SPaul Saab if (number <= 0) 1439a5f0fb15SPaul Saab number = 1; 1440a5f0fb15SPaul Saab cmd_exec(); 1441a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS && number > 1) 1442a5f0fb15SPaul Saab set_attnpos(bottompos); 14431ede1615STim J. Robbins forward((int) number, 1, 0); 1444a5f0fb15SPaul Saab break; 1445a5f0fb15SPaul Saab 1446a5f0fb15SPaul Saab case A_BF_LINE: 1447a5f0fb15SPaul Saab /* 1448a5f0fb15SPaul Saab * Force backward N (default 1) line. 1449a5f0fb15SPaul Saab */ 1450a5f0fb15SPaul Saab if (number <= 0) 1451a5f0fb15SPaul Saab number = 1; 1452a5f0fb15SPaul Saab cmd_exec(); 14531ede1615STim J. Robbins backward((int) number, 1, 0); 1454a5f0fb15SPaul Saab break; 1455a5f0fb15SPaul Saab 1456a5f0fb15SPaul Saab case A_FF_SCREEN: 1457a5f0fb15SPaul Saab /* 1458a5f0fb15SPaul Saab * Force forward one screen. 1459a5f0fb15SPaul Saab */ 1460a5f0fb15SPaul Saab if (number <= 0) 1461a5f0fb15SPaul Saab number = get_swindow(); 1462a5f0fb15SPaul Saab cmd_exec(); 1463a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS) 1464a5f0fb15SPaul Saab set_attnpos(bottompos); 14651ede1615STim J. Robbins forward((int) number, 1, 0); 1466a5f0fb15SPaul Saab break; 1467a5f0fb15SPaul Saab 1468a5f0fb15SPaul Saab case A_F_FOREVER: 1469a5f0fb15SPaul Saab /* 1470a5f0fb15SPaul Saab * Forward forever, ignoring EOF. 1471a5f0fb15SPaul Saab */ 1472a15691bfSXin LI if (show_attn) 1473a15691bfSXin LI set_attnpos(bottompos); 147496e55cc7SXin LI newaction = forw_loop(0); 1475a5f0fb15SPaul Saab break; 147696e55cc7SXin LI 147796e55cc7SXin LI case A_F_UNTIL_HILITE: 147896e55cc7SXin LI newaction = forw_loop(1); 1479a5f0fb15SPaul Saab break; 1480a5f0fb15SPaul Saab 1481a5f0fb15SPaul Saab case A_F_SCROLL: 1482a5f0fb15SPaul Saab /* 1483a5f0fb15SPaul Saab * Forward N lines 1484a5f0fb15SPaul Saab * (default same as last 'd' or 'u' command). 1485a5f0fb15SPaul Saab */ 1486a5f0fb15SPaul Saab if (number > 0) 14871ede1615STim J. Robbins wscroll = (int) number; 1488a5f0fb15SPaul Saab cmd_exec(); 1489a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS) 1490a5f0fb15SPaul Saab set_attnpos(bottompos); 1491a5f0fb15SPaul Saab forward(wscroll, 0, 0); 1492a5f0fb15SPaul Saab break; 1493a5f0fb15SPaul Saab 1494a5f0fb15SPaul Saab case A_B_SCROLL: 1495a5f0fb15SPaul Saab /* 1496a5f0fb15SPaul Saab * Forward N lines 1497a5f0fb15SPaul Saab * (default same as last 'd' or 'u' command). 1498a5f0fb15SPaul Saab */ 1499a5f0fb15SPaul Saab if (number > 0) 15001ede1615STim J. Robbins wscroll = (int) number; 1501a5f0fb15SPaul Saab cmd_exec(); 1502a5f0fb15SPaul Saab backward(wscroll, 0, 0); 1503a5f0fb15SPaul Saab break; 1504a5f0fb15SPaul Saab 1505a5f0fb15SPaul Saab case A_FREPAINT: 1506a5f0fb15SPaul Saab /* 1507a5f0fb15SPaul Saab * Flush buffers, then repaint screen. 1508a5f0fb15SPaul Saab * Don't flush the buffers on a pipe! 1509a5f0fb15SPaul Saab */ 1510423c5ce5SXin LI clear_buffers(); 1511a5f0fb15SPaul Saab /* FALLTHRU */ 1512a5f0fb15SPaul Saab case A_REPAINT: 1513a5f0fb15SPaul Saab /* 1514a5f0fb15SPaul Saab * Repaint screen. 1515a5f0fb15SPaul Saab */ 1516a5f0fb15SPaul Saab cmd_exec(); 1517a5f0fb15SPaul Saab repaint(); 1518a5f0fb15SPaul Saab break; 1519a5f0fb15SPaul Saab 1520a5f0fb15SPaul Saab case A_GOLINE: 1521a5f0fb15SPaul Saab /* 1522a5f0fb15SPaul Saab * Go to line N, default beginning of file. 15232235c7feSXin LI * If N <= 0, ignore jump_sline in order to avoid 15242235c7feSXin LI * empty lines before the beginning of the file. 1525a5f0fb15SPaul Saab */ 15262235c7feSXin LI save_jump_sline = jump_sline; 1527a5f0fb15SPaul Saab if (number <= 0) 15282235c7feSXin LI { 1529a5f0fb15SPaul Saab number = 1; 15302235c7feSXin LI jump_sline = 0; 15312235c7feSXin LI } 1532a5f0fb15SPaul Saab cmd_exec(); 1533a5f0fb15SPaul Saab jump_back(number); 15342235c7feSXin LI jump_sline = save_jump_sline; 1535a5f0fb15SPaul Saab break; 1536a5f0fb15SPaul Saab 1537a5f0fb15SPaul Saab case A_PERCENT: 1538a5f0fb15SPaul Saab /* 1539a5f0fb15SPaul Saab * Go to a specified percentage into the file. 1540a5f0fb15SPaul Saab */ 1541a5f0fb15SPaul Saab if (number < 0) 1542720c436cSXin LI { 1543a5f0fb15SPaul Saab number = 0; 1544720c436cSXin LI fraction = 0; 1545720c436cSXin LI } 1546b7780dbeSXin LI if (number > 100 || (number == 100 && fraction != 0)) 1547720c436cSXin LI { 1548a5f0fb15SPaul Saab number = 100; 1549720c436cSXin LI fraction = 0; 1550720c436cSXin LI } 1551a5f0fb15SPaul Saab cmd_exec(); 1552720c436cSXin LI jump_percent((int) number, fraction); 1553a5f0fb15SPaul Saab break; 1554a5f0fb15SPaul Saab 1555a5f0fb15SPaul Saab case A_GOEND: 1556a5f0fb15SPaul Saab /* 1557a5f0fb15SPaul Saab * Go to line N, default end of file. 1558a5f0fb15SPaul Saab */ 1559a5f0fb15SPaul Saab cmd_exec(); 1560a5f0fb15SPaul Saab if (number <= 0) 1561a5f0fb15SPaul Saab jump_forw(); 1562a5f0fb15SPaul Saab else 1563a5f0fb15SPaul Saab jump_back(number); 1564a5f0fb15SPaul Saab break; 1565a5f0fb15SPaul Saab 1566a15691bfSXin LI case A_GOEND_BUF: 1567a15691bfSXin LI /* 1568a15691bfSXin LI * Go to line N, default last buffered byte. 1569a15691bfSXin LI */ 1570a15691bfSXin LI cmd_exec(); 1571a15691bfSXin LI if (number <= 0) 1572a15691bfSXin LI jump_forw_buffered(); 1573a15691bfSXin LI else 1574a15691bfSXin LI jump_back(number); 1575a15691bfSXin LI break; 1576a15691bfSXin LI 1577a5f0fb15SPaul Saab case A_GOPOS: 1578a5f0fb15SPaul Saab /* 1579a5f0fb15SPaul Saab * Go to a specified byte position in the file. 1580a5f0fb15SPaul Saab */ 1581a5f0fb15SPaul Saab cmd_exec(); 1582a5f0fb15SPaul Saab if (number < 0) 1583a5f0fb15SPaul Saab number = 0; 1584a5f0fb15SPaul Saab jump_line_loc((POSITION) number, jump_sline); 1585a5f0fb15SPaul Saab break; 1586a5f0fb15SPaul Saab 1587a5f0fb15SPaul Saab case A_STAT: 1588a5f0fb15SPaul Saab /* 1589a5f0fb15SPaul Saab * Print file name, etc. 1590a5f0fb15SPaul Saab */ 1591a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1592a5f0fb15SPaul Saab break; 1593a5f0fb15SPaul Saab cmd_exec(); 1594a5f0fb15SPaul Saab parg.p_string = eq_message(); 1595a5f0fb15SPaul Saab error("%s", &parg); 1596a5f0fb15SPaul Saab break; 1597a5f0fb15SPaul Saab 1598a5f0fb15SPaul Saab case A_VERSION: 1599a5f0fb15SPaul Saab /* 16002235c7feSXin LI * Print version number. 1601a5f0fb15SPaul Saab */ 1602a5f0fb15SPaul Saab cmd_exec(); 1603a5f0fb15SPaul Saab dispversion(); 1604a5f0fb15SPaul Saab break; 1605a5f0fb15SPaul Saab 1606a5f0fb15SPaul Saab case A_QUIT: 1607a5f0fb15SPaul Saab /* 1608a5f0fb15SPaul Saab * Exit. 1609a5f0fb15SPaul Saab */ 1610a5f0fb15SPaul Saab if (curr_ifile != NULL_IFILE && 1611a5f0fb15SPaul Saab ch_getflags() & CH_HELPFILE) 1612a5f0fb15SPaul Saab { 1613a5f0fb15SPaul Saab /* 1614a5f0fb15SPaul Saab * Quit while viewing the help file 1615a5f0fb15SPaul Saab * just means return to viewing the 1616a5f0fb15SPaul Saab * previous file. 1617a5f0fb15SPaul Saab */ 161889dd99dcSXin LI hshift = save_hshift; 1619a15691bfSXin LI bs_mode = save_bs_mode; 1620*d713e089SXin LI proc_backspace = save_proc_backspace; 1621a5f0fb15SPaul Saab if (edit_prev(1) == 0) 1622a5f0fb15SPaul Saab break; 1623a5f0fb15SPaul Saab } 1624a5f0fb15SPaul Saab if (extra != NULL) 1625a5f0fb15SPaul Saab quit(*extra); 1626a5f0fb15SPaul Saab quit(QUIT_OK); 1627a5f0fb15SPaul Saab break; 1628a5f0fb15SPaul Saab 1629a5f0fb15SPaul Saab /* 1630a5f0fb15SPaul Saab * Define abbreviation for a commonly used sequence below. 1631a5f0fb15SPaul Saab */ 1632423c5ce5SXin LI #define DO_SEARCH() \ 1633423c5ce5SXin LI if (number <= 0) number = 1; \ 1634a5f0fb15SPaul Saab mca_search(); \ 1635a5f0fb15SPaul Saab cmd_exec(); \ 1636a15691bfSXin LI multi_search((char *)NULL, (int) number, 0); 1637a5f0fb15SPaul Saab 1638a5f0fb15SPaul Saab case A_F_SEARCH: 1639a5f0fb15SPaul Saab /* 1640a5f0fb15SPaul Saab * Search forward for a pattern. 1641a5f0fb15SPaul Saab * Get the first char of the pattern. 1642a5f0fb15SPaul Saab */ 164395270f73SXin LI search_type = SRCH_FORW | def_search_type; 1644a5f0fb15SPaul Saab if (number <= 0) 1645a5f0fb15SPaul Saab number = 1; 1646a5f0fb15SPaul Saab mca_search(); 1647a5f0fb15SPaul Saab c = getcc(); 1648a5f0fb15SPaul Saab goto again; 1649a5f0fb15SPaul Saab 1650a5f0fb15SPaul Saab case A_B_SEARCH: 1651a5f0fb15SPaul Saab /* 1652a5f0fb15SPaul Saab * Search backward for a pattern. 1653a5f0fb15SPaul Saab * Get the first char of the pattern. 1654a5f0fb15SPaul Saab */ 165595270f73SXin LI search_type = SRCH_BACK | def_search_type; 1656a5f0fb15SPaul Saab if (number <= 0) 1657a5f0fb15SPaul Saab number = 1; 1658a5f0fb15SPaul Saab mca_search(); 1659a5f0fb15SPaul Saab c = getcc(); 1660a5f0fb15SPaul Saab goto again; 1661a5f0fb15SPaul Saab 16627374caaaSXin LI case A_FILTER: 16637374caaaSXin LI #if HILITE_SEARCH 16647374caaaSXin LI search_type = SRCH_FORW | SRCH_FILTER; 16657374caaaSXin LI mca_search(); 16667374caaaSXin LI c = getcc(); 16677374caaaSXin LI goto again; 16687374caaaSXin LI #else 16697374caaaSXin LI error("Command not available", NULL_PARG); 16707374caaaSXin LI break; 16717374caaaSXin LI #endif 16727374caaaSXin LI 1673a5f0fb15SPaul Saab case A_AGAIN_SEARCH: 1674a5f0fb15SPaul Saab /* 1675a5f0fb15SPaul Saab * Repeat previous search. 1676a5f0fb15SPaul Saab */ 1677*d713e089SXin LI search_type = last_search_type; 1678a5f0fb15SPaul Saab DO_SEARCH(); 1679a5f0fb15SPaul Saab break; 1680a5f0fb15SPaul Saab 1681a5f0fb15SPaul Saab case A_T_AGAIN_SEARCH: 1682a5f0fb15SPaul Saab /* 1683a5f0fb15SPaul Saab * Repeat previous search, multiple files. 1684a5f0fb15SPaul Saab */ 1685*d713e089SXin LI search_type = last_search_type | SRCH_PAST_EOF; 1686a5f0fb15SPaul Saab DO_SEARCH(); 1687a5f0fb15SPaul Saab break; 1688a5f0fb15SPaul Saab 1689a5f0fb15SPaul Saab case A_REVERSE_SEARCH: 1690a5f0fb15SPaul Saab /* 1691a5f0fb15SPaul Saab * Repeat previous search, in reverse direction. 1692a5f0fb15SPaul Saab */ 1693*d713e089SXin LI save_search_type = search_type = last_search_type; 1694a5f0fb15SPaul Saab search_type = SRCH_REVERSE(search_type); 1695a5f0fb15SPaul Saab DO_SEARCH(); 1696*d713e089SXin LI last_search_type = save_search_type; 1697a5f0fb15SPaul Saab break; 1698a5f0fb15SPaul Saab 1699a5f0fb15SPaul Saab case A_T_REVERSE_SEARCH: 1700a5f0fb15SPaul Saab /* 1701a5f0fb15SPaul Saab * Repeat previous search, 1702a5f0fb15SPaul Saab * multiple files in reverse direction. 1703a5f0fb15SPaul Saab */ 1704*d713e089SXin LI save_search_type = search_type = last_search_type; 1705*d713e089SXin LI search_type = SRCH_REVERSE(search_type) | SRCH_PAST_EOF; 1706a5f0fb15SPaul Saab DO_SEARCH(); 1707*d713e089SXin LI last_search_type = save_search_type; 1708a5f0fb15SPaul Saab break; 1709a5f0fb15SPaul Saab 1710a5f0fb15SPaul Saab case A_UNDO_SEARCH: 17112235c7feSXin LI case A_CLR_SEARCH: 1712b2ea2440SXin LI /* 1713b2ea2440SXin LI * Clear search string highlighting. 1714b2ea2440SXin LI */ 17152235c7feSXin LI undo_search(action == A_CLR_SEARCH); 1716a5f0fb15SPaul Saab break; 1717a5f0fb15SPaul Saab 1718a5f0fb15SPaul Saab case A_HELP: 1719a5f0fb15SPaul Saab /* 1720a5f0fb15SPaul Saab * Help. 1721a5f0fb15SPaul Saab */ 1722a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1723a5f0fb15SPaul Saab break; 1724a5f0fb15SPaul Saab cmd_exec(); 172589dd99dcSXin LI save_hshift = hshift; 172689dd99dcSXin LI hshift = 0; 1727a15691bfSXin LI save_bs_mode = bs_mode; 1728a15691bfSXin LI bs_mode = BS_SPECIAL; 1729*d713e089SXin LI save_proc_backspace = proc_backspace; 1730*d713e089SXin LI proc_backspace = OPT_OFF; 1731a5f0fb15SPaul Saab (void) edit(FAKE_HELPFILE); 1732a5f0fb15SPaul Saab break; 1733a5f0fb15SPaul Saab 1734a5f0fb15SPaul Saab case A_EXAMINE: 1735a5f0fb15SPaul Saab /* 1736a5f0fb15SPaul Saab * Edit a new file. Get the filename. 1737a5f0fb15SPaul Saab */ 1738b2ea2440SXin LI #if EXAMINE 1739b2ea2440SXin LI if (!secure) 1740a5f0fb15SPaul Saab { 1741dd3bd0edSDimitry Andric start_mca(A_EXAMINE, "Examine: ", ml_examine, 0); 1742a5f0fb15SPaul Saab c = getcc(); 1743a5f0fb15SPaul Saab goto again; 1744b2ea2440SXin LI } 1745b2ea2440SXin LI #endif 1746a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 1747a5f0fb15SPaul Saab break; 1748a5f0fb15SPaul Saab 1749a5f0fb15SPaul Saab case A_VISUAL: 1750a5f0fb15SPaul Saab /* 1751a5f0fb15SPaul Saab * Invoke an editor on the input file. 1752a5f0fb15SPaul Saab */ 1753a5f0fb15SPaul Saab #if EDITOR 1754b2ea2440SXin LI if (!secure) 1755a5f0fb15SPaul Saab { 1756a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1757a5f0fb15SPaul Saab break; 1758a5f0fb15SPaul Saab if (strcmp(get_filename(curr_ifile), "-") == 0) 1759a5f0fb15SPaul Saab { 1760a5f0fb15SPaul Saab error("Cannot edit standard input", NULL_PARG); 1761a5f0fb15SPaul Saab break; 1762a5f0fb15SPaul Saab } 1763b2ea2440SXin LI if (get_altfilename(curr_ifile) != NULL) 1764a5f0fb15SPaul Saab { 176589dd99dcSXin LI error("WARNING: This file was viewed via LESSOPEN", 1766a5f0fb15SPaul Saab NULL_PARG); 1767a5f0fb15SPaul Saab } 1768dd3bd0edSDimitry Andric start_mca(A_SHELL, "!", ml_shell, 0); 1769a5f0fb15SPaul Saab /* 1770a5f0fb15SPaul Saab * Expand the editor prototype string 1771a5f0fb15SPaul Saab * and pass it to the system to execute. 1772a5f0fb15SPaul Saab * (Make sure the screen is displayed so the 1773a5f0fb15SPaul Saab * expansion of "+%lm" works.) 1774a5f0fb15SPaul Saab */ 1775a5f0fb15SPaul Saab make_display(); 1776a5f0fb15SPaul Saab cmd_exec(); 177795270f73SXin LI lsystem(pr_expand(editproto), (char*)NULL); 1778a5f0fb15SPaul Saab break; 1779b2ea2440SXin LI } 1780b2ea2440SXin LI #endif 1781a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 1782a5f0fb15SPaul Saab break; 1783a5f0fb15SPaul Saab 1784a5f0fb15SPaul Saab case A_NEXT_FILE: 1785a5f0fb15SPaul Saab /* 1786a5f0fb15SPaul Saab * Examine next file. 1787a5f0fb15SPaul Saab */ 17881ede1615STim J. Robbins #if TAGS 17898fd4165cSPaul Saab if (ntags()) 17908fd4165cSPaul Saab { 17918fd4165cSPaul Saab error("No next file", NULL_PARG); 17928fd4165cSPaul Saab break; 17938fd4165cSPaul Saab } 17941ede1615STim J. Robbins #endif 1795a5f0fb15SPaul Saab if (number <= 0) 1796a5f0fb15SPaul Saab number = 1; 17971ede1615STim J. Robbins if (edit_next((int) number)) 1798a5f0fb15SPaul Saab { 17997374caaaSXin LI if (get_quit_at_eof() && eof_displayed() && 1800a5f0fb15SPaul Saab !(ch_getflags() & CH_HELPFILE)) 1801a5f0fb15SPaul Saab quit(QUIT_OK); 1802a5f0fb15SPaul Saab parg.p_string = (number > 1) ? "(N-th) " : ""; 1803a5f0fb15SPaul Saab error("No %snext file", &parg); 1804a5f0fb15SPaul Saab } 1805a5f0fb15SPaul Saab break; 1806a5f0fb15SPaul Saab 1807a5f0fb15SPaul Saab case A_PREV_FILE: 1808a5f0fb15SPaul Saab /* 1809a5f0fb15SPaul Saab * Examine previous file. 1810a5f0fb15SPaul Saab */ 18111ede1615STim J. Robbins #if TAGS 18128fd4165cSPaul Saab if (ntags()) 18138fd4165cSPaul Saab { 18148fd4165cSPaul Saab error("No previous file", NULL_PARG); 18158fd4165cSPaul Saab break; 18168fd4165cSPaul Saab } 18171ede1615STim J. Robbins #endif 1818a5f0fb15SPaul Saab if (number <= 0) 1819a5f0fb15SPaul Saab number = 1; 18201ede1615STim J. Robbins if (edit_prev((int) number)) 1821a5f0fb15SPaul Saab { 1822a5f0fb15SPaul Saab parg.p_string = (number > 1) ? "(N-th) " : ""; 1823a5f0fb15SPaul Saab error("No %sprevious file", &parg); 1824a5f0fb15SPaul Saab } 1825a5f0fb15SPaul Saab break; 1826a5f0fb15SPaul Saab 18278fd4165cSPaul Saab case A_NEXT_TAG: 1828b2ea2440SXin LI /* 1829b2ea2440SXin LI * Jump to the next tag in the current tag list. 1830b2ea2440SXin LI */ 18311ede1615STim J. Robbins #if TAGS 18328fd4165cSPaul Saab if (number <= 0) 18338fd4165cSPaul Saab number = 1; 18341ede1615STim J. Robbins tagfile = nexttag((int) number); 18358fd4165cSPaul Saab if (tagfile == NULL) 18368fd4165cSPaul Saab { 18378fd4165cSPaul Saab error("No next tag", NULL_PARG); 18388fd4165cSPaul Saab break; 18398fd4165cSPaul Saab } 1840b2ea2440SXin LI cmd_exec(); 18418fd4165cSPaul Saab if (edit(tagfile) == 0) 18428fd4165cSPaul Saab { 18438fd4165cSPaul Saab POSITION pos = tagsearch(); 18448fd4165cSPaul Saab if (pos != NULL_POSITION) 18458fd4165cSPaul Saab jump_loc(pos, jump_sline); 18468fd4165cSPaul Saab } 18471ede1615STim J. Robbins #else 18481ede1615STim J. Robbins error("Command not available", NULL_PARG); 18491ede1615STim J. Robbins #endif 18508fd4165cSPaul Saab break; 18518fd4165cSPaul Saab 18528fd4165cSPaul Saab case A_PREV_TAG: 1853b2ea2440SXin LI /* 1854b2ea2440SXin LI * Jump to the previous tag in the current tag list. 1855b2ea2440SXin LI */ 18561ede1615STim J. Robbins #if TAGS 18578fd4165cSPaul Saab if (number <= 0) 18588fd4165cSPaul Saab number = 1; 18591ede1615STim J. Robbins tagfile = prevtag((int) number); 18608fd4165cSPaul Saab if (tagfile == NULL) 18618fd4165cSPaul Saab { 18628fd4165cSPaul Saab error("No previous tag", NULL_PARG); 18638fd4165cSPaul Saab break; 18648fd4165cSPaul Saab } 1865b2ea2440SXin LI cmd_exec(); 18668fd4165cSPaul Saab if (edit(tagfile) == 0) 18678fd4165cSPaul Saab { 18688fd4165cSPaul Saab POSITION pos = tagsearch(); 18698fd4165cSPaul Saab if (pos != NULL_POSITION) 18708fd4165cSPaul Saab jump_loc(pos, jump_sline); 18718fd4165cSPaul Saab } 18721ede1615STim J. Robbins #else 18731ede1615STim J. Robbins error("Command not available", NULL_PARG); 18741ede1615STim J. Robbins #endif 18758fd4165cSPaul Saab break; 18768fd4165cSPaul Saab 1877a5f0fb15SPaul Saab case A_INDEX_FILE: 1878a5f0fb15SPaul Saab /* 1879a5f0fb15SPaul Saab * Examine a particular file. 1880a5f0fb15SPaul Saab */ 1881a5f0fb15SPaul Saab if (number <= 0) 1882a5f0fb15SPaul Saab number = 1; 18831ede1615STim J. Robbins if (edit_index((int) number)) 1884a5f0fb15SPaul Saab error("No such file", NULL_PARG); 1885a5f0fb15SPaul Saab break; 1886a5f0fb15SPaul Saab 1887a5f0fb15SPaul Saab case A_REMOVE_FILE: 1888b2ea2440SXin LI /* 1889b2ea2440SXin LI * Remove a file from the input file list. 1890b2ea2440SXin LI */ 1891a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1892a5f0fb15SPaul Saab break; 1893a5f0fb15SPaul Saab old_ifile = curr_ifile; 1894a5f0fb15SPaul Saab new_ifile = getoff_ifile(curr_ifile); 1895a5f0fb15SPaul Saab if (new_ifile == NULL_IFILE) 1896a5f0fb15SPaul Saab { 1897a5f0fb15SPaul Saab bell(); 1898a5f0fb15SPaul Saab break; 1899a5f0fb15SPaul Saab } 1900a5f0fb15SPaul Saab if (edit_ifile(new_ifile) != 0) 1901a5f0fb15SPaul Saab { 1902a5f0fb15SPaul Saab reedit_ifile(old_ifile); 1903a5f0fb15SPaul Saab break; 1904a5f0fb15SPaul Saab } 1905a5f0fb15SPaul Saab del_ifile(old_ifile); 1906a5f0fb15SPaul Saab break; 1907a5f0fb15SPaul Saab 1908a5f0fb15SPaul Saab case A_OPT_TOGGLE: 1909b2ea2440SXin LI /* 1910b2ea2440SXin LI * Change the setting of an option. 1911b2ea2440SXin LI */ 1912a5f0fb15SPaul Saab optflag = OPT_TOGGLE; 1913a5f0fb15SPaul Saab optgetname = FALSE; 1914a5f0fb15SPaul Saab mca_opt_toggle(); 1915a5f0fb15SPaul Saab c = getcc(); 19166f26c71dSXin LI cbuf = opt_toggle_disallowed(c); 19176f26c71dSXin LI if (cbuf != NULL) 19186f26c71dSXin LI { 19196f26c71dSXin LI error(cbuf, NULL_PARG); 19206f26c71dSXin LI break; 19216f26c71dSXin LI } 1922a5f0fb15SPaul Saab goto again; 1923a5f0fb15SPaul Saab 1924a5f0fb15SPaul Saab case A_DISP_OPTION: 1925a5f0fb15SPaul Saab /* 1926b2ea2440SXin LI * Report the setting of an option. 1927a5f0fb15SPaul Saab */ 1928a5f0fb15SPaul Saab optflag = OPT_NO_TOGGLE; 1929a5f0fb15SPaul Saab optgetname = FALSE; 1930a5f0fb15SPaul Saab mca_opt_toggle(); 1931a5f0fb15SPaul Saab c = getcc(); 1932a5f0fb15SPaul Saab goto again; 1933a5f0fb15SPaul Saab 1934a5f0fb15SPaul Saab case A_FIRSTCMD: 1935a5f0fb15SPaul Saab /* 1936a5f0fb15SPaul Saab * Set an initial command for new files. 1937a5f0fb15SPaul Saab */ 1938a5f0fb15SPaul Saab start_mca(A_FIRSTCMD, "+", (void*)NULL, 0); 1939a5f0fb15SPaul Saab c = getcc(); 1940a5f0fb15SPaul Saab goto again; 1941a5f0fb15SPaul Saab 1942a5f0fb15SPaul Saab case A_SHELL: 1943*d713e089SXin LI case A_PSHELL: 1944a5f0fb15SPaul Saab /* 1945a5f0fb15SPaul Saab * Shell escape. 1946a5f0fb15SPaul Saab */ 1947a5f0fb15SPaul Saab #if SHELL_ESCAPE 1948b2ea2440SXin LI if (!secure) 1949a5f0fb15SPaul Saab { 1950*d713e089SXin LI start_mca(action, (action == A_SHELL) ? "!" : "#", ml_shell, 0); 1951a5f0fb15SPaul Saab c = getcc(); 1952a5f0fb15SPaul Saab goto again; 1953b2ea2440SXin LI } 1954b2ea2440SXin LI #endif 1955a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 1956a5f0fb15SPaul Saab break; 1957a5f0fb15SPaul Saab 1958a5f0fb15SPaul Saab case A_SETMARK: 1959b2ea2440SXin LI case A_SETMARKBOT: 1960a5f0fb15SPaul Saab /* 1961a5f0fb15SPaul Saab * Set a mark. 1962a5f0fb15SPaul Saab */ 1963a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1964a5f0fb15SPaul Saab break; 1965b2ea2440SXin LI start_mca(A_SETMARK, "set mark: ", (void*)NULL, 0); 1966a5f0fb15SPaul Saab c = getcc(); 1967b2ea2440SXin LI if (is_erase_char(c) || is_newline_char(c)) 1968a5f0fb15SPaul Saab break; 1969b2ea2440SXin LI setmark(c, action == A_SETMARKBOT ? BOTTOM : TOP); 1970b2ea2440SXin LI repaint(); 1971b2ea2440SXin LI break; 1972b2ea2440SXin LI 1973b2ea2440SXin LI case A_CLRMARK: 1974b2ea2440SXin LI /* 1975b2ea2440SXin LI * Clear a mark. 1976b2ea2440SXin LI */ 1977b2ea2440SXin LI start_mca(A_CLRMARK, "clear mark: ", (void*)NULL, 0); 1978b2ea2440SXin LI c = getcc(); 1979b2ea2440SXin LI if (is_erase_char(c) || is_newline_char(c)) 1980b2ea2440SXin LI break; 1981b2ea2440SXin LI clrmark(c); 1982b2ea2440SXin LI repaint(); 1983a5f0fb15SPaul Saab break; 1984a5f0fb15SPaul Saab 1985a5f0fb15SPaul Saab case A_GOMARK: 1986a5f0fb15SPaul Saab /* 1987b2ea2440SXin LI * Jump to a marked position. 1988a5f0fb15SPaul Saab */ 1989a5f0fb15SPaul Saab start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0); 1990a5f0fb15SPaul Saab c = getcc(); 1991b2ea2440SXin LI if (is_erase_char(c) || is_newline_char(c)) 1992a5f0fb15SPaul Saab break; 19937374caaaSXin LI cmd_exec(); 1994a5f0fb15SPaul Saab gomark(c); 1995a5f0fb15SPaul Saab break; 1996a5f0fb15SPaul Saab 1997a5f0fb15SPaul Saab case A_PIPE: 1998b2ea2440SXin LI /* 1999b2ea2440SXin LI * Write part of the input to a pipe to a shell command. 2000b2ea2440SXin LI */ 2001a5f0fb15SPaul Saab #if PIPEC 2002b2ea2440SXin LI if (!secure) 2003a5f0fb15SPaul Saab { 2004a5f0fb15SPaul Saab start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); 2005a5f0fb15SPaul Saab c = getcc(); 2006b2ea2440SXin LI if (is_erase_char(c)) 2007a5f0fb15SPaul Saab break; 2008b2ea2440SXin LI if (is_newline_char(c)) 2009a5f0fb15SPaul Saab c = '.'; 2010a5f0fb15SPaul Saab if (badmark(c)) 2011a5f0fb15SPaul Saab break; 2012a5f0fb15SPaul Saab pipec = c; 2013dd3bd0edSDimitry Andric start_mca(A_PIPE, "!", ml_shell, 0); 2014a5f0fb15SPaul Saab c = getcc(); 2015a5f0fb15SPaul Saab goto again; 2016b2ea2440SXin LI } 2017b2ea2440SXin LI #endif 2018a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 2019a5f0fb15SPaul Saab break; 2020a5f0fb15SPaul Saab 2021a5f0fb15SPaul Saab case A_B_BRACKET: 2022a5f0fb15SPaul Saab case A_F_BRACKET: 2023a5f0fb15SPaul Saab start_mca(action, "Brackets: ", (void*)NULL, 0); 2024a5f0fb15SPaul Saab c = getcc(); 2025a5f0fb15SPaul Saab goto again; 2026a5f0fb15SPaul Saab 2027a5f0fb15SPaul Saab case A_LSHIFT: 2028b2ea2440SXin LI /* 2029b2ea2440SXin LI * Shift view left. 2030b2ea2440SXin LI */ 20318fd4165cSPaul Saab if (number > 0) 20328fd4165cSPaul Saab shift_count = number; 20338fd4165cSPaul Saab else 203415596da4SPaul Saab number = (shift_count > 0) ? 203515596da4SPaul Saab shift_count : sc_width / 2; 2036a5f0fb15SPaul Saab if (number > hshift) 2037a5f0fb15SPaul Saab number = hshift; 2038a5f0fb15SPaul Saab hshift -= number; 2039a5f0fb15SPaul Saab screen_trashed = 1; 2040a5f0fb15SPaul Saab break; 2041a5f0fb15SPaul Saab 2042a5f0fb15SPaul Saab case A_RSHIFT: 2043b2ea2440SXin LI /* 2044b2ea2440SXin LI * Shift view right. 2045b2ea2440SXin LI */ 20468fd4165cSPaul Saab if (number > 0) 20478fd4165cSPaul Saab shift_count = number; 20488fd4165cSPaul Saab else 204915596da4SPaul Saab number = (shift_count > 0) ? 205015596da4SPaul Saab shift_count : sc_width / 2; 2051a5f0fb15SPaul Saab hshift += number; 2052a5f0fb15SPaul Saab screen_trashed = 1; 2053a5f0fb15SPaul Saab break; 2054a5f0fb15SPaul Saab 2055f6b74a7dSXin LI case A_LLSHIFT: 2056b2ea2440SXin LI /* 2057b2ea2440SXin LI * Shift view left to margin. 2058b2ea2440SXin LI */ 2059f6b74a7dSXin LI hshift = 0; 2060f6b74a7dSXin LI screen_trashed = 1; 2061f6b74a7dSXin LI break; 2062f6b74a7dSXin LI 2063f6b74a7dSXin LI case A_RRSHIFT: 2064b2ea2440SXin LI /* 2065b2ea2440SXin LI * Shift view right to view rightmost char on screen. 2066b2ea2440SXin LI */ 2067f6b74a7dSXin LI hshift = rrshift(); 2068f6b74a7dSXin LI screen_trashed = 1; 2069f6b74a7dSXin LI break; 2070f6b74a7dSXin LI 2071a5f0fb15SPaul Saab case A_PREFIX: 2072a5f0fb15SPaul Saab /* 2073a5f0fb15SPaul Saab * The command is incomplete (more chars are needed). 2074a5f0fb15SPaul Saab * Display the current char, so the user knows 2075a5f0fb15SPaul Saab * what's going on, and get another character. 2076a5f0fb15SPaul Saab */ 2077a5f0fb15SPaul Saab if (mca != A_PREFIX) 2078a5f0fb15SPaul Saab { 2079a5f0fb15SPaul Saab cmd_reset(); 2080a5f0fb15SPaul Saab start_mca(A_PREFIX, " ", (void*)NULL, 2081a5f0fb15SPaul Saab CF_QUIT_ON_ERASE); 2082a5f0fb15SPaul Saab (void) cmd_char(c); 2083a5f0fb15SPaul Saab } 2084a5f0fb15SPaul Saab c = getcc(); 2085a5f0fb15SPaul Saab goto again; 2086a5f0fb15SPaul Saab 2087a5f0fb15SPaul Saab case A_NOACTION: 2088a5f0fb15SPaul Saab break; 2089a5f0fb15SPaul Saab 2090a5f0fb15SPaul Saab default: 2091a5f0fb15SPaul Saab bell(); 2092a5f0fb15SPaul Saab break; 2093a5f0fb15SPaul Saab } 2094a5f0fb15SPaul Saab } 2095a5f0fb15SPaul Saab } 2096