1a8f92a7cSPaul Saab /* $FreeBSD$ */ 2a5f0fb15SPaul Saab /* 3*c77c4889SXin LI * Copyright (C) 1984-2024 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; 27d713e089SXin LI extern int one_screen; 28a5f0fb15SPaul Saab extern int sc_width; 29a5f0fb15SPaul Saab extern int sc_height; 30b2ea2440SXin LI extern char *kent; 31a5f0fb15SPaul Saab extern int swindow; 32a5f0fb15SPaul Saab extern int jump_sline; 33a5f0fb15SPaul Saab extern int quitting; 34a5f0fb15SPaul Saab extern int wscroll; 35a5f0fb15SPaul Saab extern int top_scroll; 36a5f0fb15SPaul Saab extern int ignore_eoi; 37a5f0fb15SPaul Saab extern int hshift; 38a15691bfSXin LI extern int bs_mode; 39d713e089SXin LI extern int proc_backspace; 40a5f0fb15SPaul Saab extern int show_attn; 41720c436cSXin LI extern int less_is_more; 4296e55cc7SXin LI extern POSITION highest_hilite; 43a5f0fb15SPaul Saab extern char *every_first_cmd; 44a5f0fb15SPaul Saab extern char version[]; 45a5f0fb15SPaul Saab extern struct scrpos initial_scrpos; 46a5f0fb15SPaul Saab extern IFILE curr_ifile; 47f6b74a7dSXin LI extern void *ml_search; 48f6b74a7dSXin LI extern void *ml_examine; 49b7780dbeSXin LI extern int wheel_lines; 5095270f73SXin LI extern int def_search_type; 51*c77c4889SXin LI extern lbool search_wrapped; 52a5f0fb15SPaul Saab #if SHELL_ESCAPE || PIPEC 53f6b74a7dSXin LI extern void *ml_shell; 54a5f0fb15SPaul Saab #endif 55a5f0fb15SPaul Saab #if EDITOR 56*c77c4889SXin LI extern constant char *editproto; 57a5f0fb15SPaul Saab #endif 58*c77c4889SXin LI #if OSC8_LINK 59*c77c4889SXin LI extern char *osc8_uri; 60*c77c4889SXin LI #endif 6115596da4SPaul Saab extern int shift_count; 62720c436cSXin LI extern int forw_prompt; 632235c7feSXin LI extern int incr_search; 64d713e089SXin LI extern int full_screen; 65b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 66b7780dbeSXin LI extern int utf_mode; 67*c77c4889SXin LI extern unsigned less_acp; 68b7780dbeSXin LI #endif 69a5f0fb15SPaul Saab 70a5f0fb15SPaul Saab #if SHELL_ESCAPE 71a5f0fb15SPaul Saab static char *shellcmd = NULL; /* For holding last shell command for "!!" */ 72a5f0fb15SPaul Saab #endif 73a5f0fb15SPaul Saab static int mca; /* The multicharacter command (action) */ 74a5f0fb15SPaul Saab static int search_type; /* The previous type of search */ 75d713e089SXin LI static int last_search_type; /* Type of last executed search */ 761ede1615STim J. Robbins static LINENUM number; /* The number typed by the user */ 77720c436cSXin LI static long fraction; /* The fractional part of the number */ 7833096f16SXin LI static struct loption *curropt; 7933096f16SXin LI static int opt_lower; 80a5f0fb15SPaul Saab static int optflag; 81*c77c4889SXin LI static lbool optgetname; 82a5f0fb15SPaul Saab static POSITION bottompos; 8389dd99dcSXin LI static int save_hshift; 84a15691bfSXin LI static int save_bs_mode; 85d713e089SXin LI static int save_proc_backspace; 86*c77c4889SXin LI static int screen_trashed_value = 0; 87*c77c4889SXin LI static lbool literal_char = FALSE; 88a5f0fb15SPaul Saab #if PIPEC 89a5f0fb15SPaul Saab static char pipec; 90a5f0fb15SPaul Saab #endif 91a5f0fb15SPaul Saab 92b2ea2440SXin LI /* Stack of ungotten chars (via ungetcc) */ 9333096f16SXin LI struct ungot { 9433096f16SXin LI struct ungot *ug_next; 95*c77c4889SXin LI char ug_char; 96*c77c4889SXin LI lbool ug_end_command; 9733096f16SXin LI }; 9833096f16SXin LI static struct ungot* ungot = NULL; 9933096f16SXin LI 100*c77c4889SXin LI static void multi_search(constant char *pattern, int n, int silent); 101a5f0fb15SPaul Saab 102a5f0fb15SPaul Saab /* 103720c436cSXin LI * Move the cursor to start of prompt line before executing a command. 104a5f0fb15SPaul Saab * This looks nicer if the command takes a long time before 105a5f0fb15SPaul Saab * updating the screen. 106a5f0fb15SPaul Saab */ 107d713e089SXin LI static void cmd_exec(void) 108a5f0fb15SPaul Saab { 109a5f0fb15SPaul Saab clear_attn(); 110aa22b8b6SXin LI clear_bot(); 111a5f0fb15SPaul Saab flush(); 112a5f0fb15SPaul Saab } 113a5f0fb15SPaul Saab 114a5f0fb15SPaul Saab /* 115b7780dbeSXin LI * Indicate we are reading a multi-character command. 116b7780dbeSXin LI */ 117d713e089SXin LI static void set_mca(int action) 118b7780dbeSXin LI { 119b7780dbeSXin LI mca = action; 120b7780dbeSXin LI clear_bot(); 121b7780dbeSXin LI clear_cmd(); 122b7780dbeSXin LI } 123b7780dbeSXin LI 124b7780dbeSXin LI /* 125b7780dbeSXin LI * Indicate we are not reading a multi-character command. 126b7780dbeSXin LI */ 127d713e089SXin LI static void clear_mca(void) 128b7780dbeSXin LI { 129b7780dbeSXin LI if (mca == 0) 130b7780dbeSXin LI return; 131b7780dbeSXin LI mca = 0; 132b7780dbeSXin LI } 133b7780dbeSXin LI 134b7780dbeSXin LI /* 135a5f0fb15SPaul Saab * Set up the display to start a new multi-character command. 136a5f0fb15SPaul Saab */ 137d713e089SXin LI static void start_mca(int action, constant char *prompt, void *mlist, int cmdflags) 138a5f0fb15SPaul Saab { 139b7780dbeSXin LI set_mca(action); 140a5f0fb15SPaul Saab cmd_putstr(prompt); 141a5f0fb15SPaul Saab set_mlist(mlist, cmdflags); 142a5f0fb15SPaul Saab } 143a5f0fb15SPaul Saab 144d713e089SXin LI public int in_mca(void) 145a5f0fb15SPaul Saab { 146a5f0fb15SPaul Saab return (mca != 0 && mca != A_PREFIX); 147a5f0fb15SPaul Saab } 148a5f0fb15SPaul Saab 149a5f0fb15SPaul Saab /* 150a5f0fb15SPaul Saab * Set up the display to start a new search command. 151a5f0fb15SPaul Saab */ 152d713e089SXin LI static void mca_search1(void) 153a5f0fb15SPaul Saab { 154d713e089SXin LI int i; 155d713e089SXin LI 1567374caaaSXin LI #if HILITE_SEARCH 1577374caaaSXin LI if (search_type & SRCH_FILTER) 158b7780dbeSXin LI set_mca(A_FILTER); 1597374caaaSXin LI else 1607374caaaSXin LI #endif 161a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 162b7780dbeSXin LI set_mca(A_F_SEARCH); 163a5f0fb15SPaul Saab else 164b7780dbeSXin LI set_mca(A_B_SEARCH); 165a5f0fb15SPaul Saab 166a5f0fb15SPaul Saab if (search_type & SRCH_NO_MATCH) 167a5f0fb15SPaul Saab cmd_putstr("Non-match "); 168a5f0fb15SPaul Saab if (search_type & SRCH_FIRST_FILE) 169a5f0fb15SPaul Saab cmd_putstr("First-file "); 170a5f0fb15SPaul Saab if (search_type & SRCH_PAST_EOF) 171a5f0fb15SPaul Saab cmd_putstr("EOF-ignore "); 172a5f0fb15SPaul Saab if (search_type & SRCH_NO_MOVE) 173a5f0fb15SPaul Saab cmd_putstr("Keep-pos "); 174a5f0fb15SPaul Saab if (search_type & SRCH_NO_REGEX) 175a5f0fb15SPaul Saab cmd_putstr("Regex-off "); 1762235c7feSXin LI if (search_type & SRCH_WRAP) 1772235c7feSXin LI cmd_putstr("Wrap "); 178d713e089SXin LI for (i = 1; i <= NUM_SEARCH_COLORS; i++) 179d713e089SXin LI { 180d713e089SXin LI if (search_type & SRCH_SUBSEARCH(i)) 181d713e089SXin LI { 182f80a33eaSXin LI char buf[INT_STRLEN_BOUND(int)+8]; 183d713e089SXin LI SNPRINTF1(buf, sizeof(buf), "Sub-%d ", i); 184d713e089SXin LI cmd_putstr(buf); 185d713e089SXin LI } 186d713e089SXin LI } 187*c77c4889SXin LI if (literal_char) 188*c77c4889SXin LI cmd_putstr("Lit "); 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 202d713e089SXin 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 */ 211d713e089SXin LI static void mca_opt_toggle(void) 212a5f0fb15SPaul Saab { 213*c77c4889SXin LI int no_prompt = (optflag & OPT_NO_PROMPT); 214*c77c4889SXin LI int flag = (optflag & ~OPT_NO_PROMPT); 215*c77c4889SXin LI constant char *dash = (flag == OPT_NO_TOGGLE) ? "_" : "-"; 216a5f0fb15SPaul Saab 217b7780dbeSXin LI set_mca(A_OPT_TOGGLE); 218a5f0fb15SPaul Saab cmd_putstr(dash); 219a5f0fb15SPaul Saab if (optgetname) 220a5f0fb15SPaul Saab cmd_putstr(dash); 221a5f0fb15SPaul Saab if (no_prompt) 222a5f0fb15SPaul Saab cmd_putstr("(P)"); 223a5f0fb15SPaul Saab switch (flag) 224a5f0fb15SPaul Saab { 225a5f0fb15SPaul Saab case OPT_UNSET: 226a5f0fb15SPaul Saab cmd_putstr("+"); 227a5f0fb15SPaul Saab break; 228a5f0fb15SPaul Saab case OPT_SET: 229a5f0fb15SPaul Saab cmd_putstr("!"); 230a5f0fb15SPaul Saab break; 231a5f0fb15SPaul Saab } 232a15691bfSXin LI forw_prompt = 0; 233a5f0fb15SPaul Saab set_mlist(NULL, 0); 234a5f0fb15SPaul Saab } 235a5f0fb15SPaul Saab 236a5f0fb15SPaul Saab /* 237a5f0fb15SPaul Saab * Execute a multicharacter command. 238a5f0fb15SPaul Saab */ 239d713e089SXin LI static void exec_mca(void) 240a5f0fb15SPaul Saab { 241*c77c4889SXin LI constant char *cbuf; 242*c77c4889SXin LI char *p; 243a5f0fb15SPaul Saab 244a5f0fb15SPaul Saab cmd_exec(); 245a5f0fb15SPaul Saab cbuf = get_cmdbuf(); 24695270f73SXin LI if (cbuf == NULL) 24795270f73SXin LI return; 248a5f0fb15SPaul Saab 249a5f0fb15SPaul Saab switch (mca) 250a5f0fb15SPaul Saab { 251a5f0fb15SPaul Saab case A_F_SEARCH: 252a5f0fb15SPaul Saab case A_B_SEARCH: 253a15691bfSXin LI multi_search(cbuf, (int) number, 0); 254a5f0fb15SPaul Saab break; 2557374caaaSXin LI #if HILITE_SEARCH 2567374caaaSXin LI case A_FILTER: 2577374caaaSXin LI search_type ^= SRCH_NO_MATCH; 2587374caaaSXin LI set_filter_pattern(cbuf, search_type); 2597374caaaSXin LI break; 2607374caaaSXin LI #endif 261a5f0fb15SPaul Saab case A_FIRSTCMD: 262a5f0fb15SPaul Saab /* 263a5f0fb15SPaul Saab * Skip leading spaces or + signs in the string. 264a5f0fb15SPaul Saab */ 265a5f0fb15SPaul Saab while (*cbuf == '+' || *cbuf == ' ') 266a5f0fb15SPaul Saab cbuf++; 267a5f0fb15SPaul Saab if (every_first_cmd != NULL) 268a5f0fb15SPaul Saab free(every_first_cmd); 269a5f0fb15SPaul Saab if (*cbuf == '\0') 270a5f0fb15SPaul Saab every_first_cmd = NULL; 271a5f0fb15SPaul Saab else 272a5f0fb15SPaul Saab every_first_cmd = save(cbuf); 273a5f0fb15SPaul Saab break; 274a5f0fb15SPaul Saab case A_OPT_TOGGLE: 27533096f16SXin LI toggle_option(curropt, opt_lower, cbuf, optflag); 27633096f16SXin LI curropt = NULL; 277a5f0fb15SPaul Saab break; 278a5f0fb15SPaul Saab case A_F_BRACKET: 2791ede1615STim J. Robbins match_brac(cbuf[0], cbuf[1], 1, (int) number); 280a5f0fb15SPaul Saab break; 281a5f0fb15SPaul Saab case A_B_BRACKET: 2821ede1615STim J. Robbins match_brac(cbuf[1], cbuf[0], 0, (int) number); 283a5f0fb15SPaul Saab break; 284a5f0fb15SPaul Saab #if EXAMINE 285a5f0fb15SPaul Saab case A_EXAMINE: 286*c77c4889SXin LI if (!secure_allow(SF_EXAMINE)) 287a5f0fb15SPaul Saab break; 288*c77c4889SXin LI p = save(cbuf); 289*c77c4889SXin LI edit_list(p); 290*c77c4889SXin LI free(p); 2911ede1615STim J. Robbins #if TAGS 2928fd4165cSPaul Saab /* If tag structure is loaded then clean it up. */ 2938fd4165cSPaul Saab cleantags(); 2941ede1615STim J. Robbins #endif 295a5f0fb15SPaul Saab break; 296a5f0fb15SPaul Saab #endif 297a5f0fb15SPaul Saab #if SHELL_ESCAPE 298*c77c4889SXin LI case A_SHELL: { 299a5f0fb15SPaul Saab /* 300a5f0fb15SPaul Saab * !! just uses whatever is in shellcmd. 301a5f0fb15SPaul Saab * Otherwise, copy cmdbuf to shellcmd, 302a5f0fb15SPaul Saab * expanding any special characters ("%" or "#"). 303a5f0fb15SPaul Saab */ 304*c77c4889SXin LI constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "!done"; 305*c77c4889SXin LI if (done_msg == NULL) 306*c77c4889SXin LI ++cbuf; 307a5f0fb15SPaul Saab if (*cbuf != '!') 308a5f0fb15SPaul Saab { 309a5f0fb15SPaul Saab if (shellcmd != NULL) 310a5f0fb15SPaul Saab free(shellcmd); 311a5f0fb15SPaul Saab shellcmd = fexpand(cbuf); 312a5f0fb15SPaul Saab } 313*c77c4889SXin LI if (!secure_allow(SF_SHELL)) 314a5f0fb15SPaul Saab break; 315a5f0fb15SPaul Saab if (shellcmd == NULL) 316*c77c4889SXin LI shellcmd = ""; 317*c77c4889SXin LI lsystem(shellcmd, done_msg); 318*c77c4889SXin LI break; } 319*c77c4889SXin LI case A_PSHELL: { 320*c77c4889SXin LI constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "#done"; 321*c77c4889SXin LI if (done_msg == NULL) 322*c77c4889SXin LI ++cbuf; 323*c77c4889SXin LI if (!secure_allow(SF_SHELL)) 324a5f0fb15SPaul Saab break; 325*c77c4889SXin LI lsystem(pr_expand(cbuf), done_msg); 326*c77c4889SXin LI break; } 327a5f0fb15SPaul Saab #endif 328a5f0fb15SPaul Saab #if PIPEC 329*c77c4889SXin LI case A_PIPE: { 330*c77c4889SXin LI constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "|done"; 331*c77c4889SXin LI if (done_msg == NULL) 332*c77c4889SXin LI ++cbuf; 333*c77c4889SXin LI if (!secure_allow(SF_PIPE)) 334a5f0fb15SPaul Saab break; 335a5f0fb15SPaul Saab (void) pipe_mark(pipec, cbuf); 336*c77c4889SXin LI if (done_msg != NULL) 337*c77c4889SXin LI error(done_msg, NULL_PARG); 338*c77c4889SXin LI break; } 339a5f0fb15SPaul Saab #endif 340a5f0fb15SPaul Saab } 341a5f0fb15SPaul Saab } 342a5f0fb15SPaul Saab 343a5f0fb15SPaul Saab /* 34433096f16SXin LI * Is a character an erase or kill char? 345a5f0fb15SPaul Saab */ 346*c77c4889SXin LI static lbool is_erase_char(char c) 347a5f0fb15SPaul Saab { 34833096f16SXin LI return (c == erase_char || c == erase2_char || c == kill_char); 349a5f0fb15SPaul Saab } 350a5f0fb15SPaul Saab 351a5f0fb15SPaul Saab /* 352b2ea2440SXin LI * Is a character a carriage return or newline? 353b2ea2440SXin LI */ 354*c77c4889SXin LI static lbool is_newline_char(char c) 355b2ea2440SXin LI { 356b2ea2440SXin LI return (c == '\n' || c == '\r'); 357b2ea2440SXin LI } 358b2ea2440SXin LI 359b2ea2440SXin LI /* 36033096f16SXin LI * Handle the first char of an option (after the initial dash). 361a5f0fb15SPaul Saab */ 362*c77c4889SXin LI static int mca_opt_first_char(char c) 363a5f0fb15SPaul Saab { 36495270f73SXin LI int no_prompt = (optflag & OPT_NO_PROMPT); 36533096f16SXin LI int flag = (optflag & ~OPT_NO_PROMPT); 366a5f0fb15SPaul Saab if (flag == OPT_NO_TOGGLE) 367a5f0fb15SPaul Saab { 368a5f0fb15SPaul Saab switch (c) 369a5f0fb15SPaul Saab { 370a5f0fb15SPaul Saab case '_': 371a5f0fb15SPaul Saab /* "__" = long option name. */ 372a5f0fb15SPaul Saab optgetname = TRUE; 373a5f0fb15SPaul Saab mca_opt_toggle(); 374a5f0fb15SPaul Saab return (MCA_MORE); 375a5f0fb15SPaul Saab } 376a5f0fb15SPaul Saab } else 377a5f0fb15SPaul Saab { 378a5f0fb15SPaul Saab switch (c) 379a5f0fb15SPaul Saab { 380a5f0fb15SPaul Saab case '+': 381a5f0fb15SPaul Saab /* "-+" = UNSET. */ 38295270f73SXin LI optflag = no_prompt | ((flag == OPT_UNSET) ? 38395270f73SXin LI OPT_TOGGLE : OPT_UNSET); 384a5f0fb15SPaul Saab mca_opt_toggle(); 385a5f0fb15SPaul Saab return (MCA_MORE); 386a5f0fb15SPaul Saab case '!': 387a5f0fb15SPaul Saab /* "-!" = SET */ 38895270f73SXin LI optflag = no_prompt | ((flag == OPT_SET) ? 38995270f73SXin LI OPT_TOGGLE : OPT_SET); 390a5f0fb15SPaul Saab mca_opt_toggle(); 391a5f0fb15SPaul Saab return (MCA_MORE); 392a5f0fb15SPaul Saab case CONTROL('P'): 393a5f0fb15SPaul Saab optflag ^= OPT_NO_PROMPT; 394a5f0fb15SPaul Saab mca_opt_toggle(); 395a5f0fb15SPaul Saab return (MCA_MORE); 396a5f0fb15SPaul Saab case '-': 397a5f0fb15SPaul Saab /* "--" = long option name. */ 398a5f0fb15SPaul Saab optgetname = TRUE; 399a5f0fb15SPaul Saab mca_opt_toggle(); 400a5f0fb15SPaul Saab return (MCA_MORE); 401a5f0fb15SPaul Saab } 402a5f0fb15SPaul Saab } 40333096f16SXin LI /* Char was not handled here. */ 40433096f16SXin LI return (NO_MCA); 405a5f0fb15SPaul Saab } 40633096f16SXin LI 407a5f0fb15SPaul Saab /* 40833096f16SXin LI * Add a char to a long option name. 40933096f16SXin LI * See if we've got a match for an option name yet. 410a5f0fb15SPaul Saab * If so, display the complete name and stop 411a5f0fb15SPaul Saab * accepting chars until user hits RETURN. 412a5f0fb15SPaul Saab */ 413*c77c4889SXin LI static int mca_opt_nonfirst_char(char c) 41433096f16SXin LI { 415*c77c4889SXin LI constant char *p; 416*c77c4889SXin LI constant char *oname; 417*c77c4889SXin LI lbool ambig; 418a5f0fb15SPaul Saab 41933096f16SXin LI if (curropt != NULL) 420a5f0fb15SPaul Saab { 421a5f0fb15SPaul Saab /* 422a5f0fb15SPaul Saab * Already have a match for the name. 423a5f0fb15SPaul Saab * Don't accept anything but erase/kill. 424a5f0fb15SPaul Saab */ 42533096f16SXin LI if (is_erase_char(c)) 426a5f0fb15SPaul Saab return (MCA_DONE); 427a5f0fb15SPaul Saab return (MCA_MORE); 428a5f0fb15SPaul Saab } 429a5f0fb15SPaul Saab /* 430a5f0fb15SPaul Saab * Add char to cmd buffer and try to match 431a5f0fb15SPaul Saab * the option name. 432a5f0fb15SPaul Saab */ 433a5f0fb15SPaul Saab if (cmd_char(c) == CC_QUIT) 434a5f0fb15SPaul Saab return (MCA_DONE); 435a5f0fb15SPaul Saab p = get_cmdbuf(); 43695270f73SXin LI if (p == NULL) 43795270f73SXin LI return (MCA_MORE); 43833096f16SXin LI opt_lower = ASCII_IS_LOWER(p[0]); 439*c77c4889SXin LI curropt = findopt_name(&p, &oname, &ambig); 44033096f16SXin LI if (curropt != NULL) 441a5f0fb15SPaul Saab { 442a5f0fb15SPaul Saab /* 443a5f0fb15SPaul Saab * Got a match. 44433096f16SXin LI * Remember the option and 445a5f0fb15SPaul Saab * display the full option name. 446a5f0fb15SPaul Saab */ 447a5f0fb15SPaul Saab cmd_reset(); 448a5f0fb15SPaul Saab mca_opt_toggle(); 449a5f0fb15SPaul Saab for (p = oname; *p != '\0'; p++) 450a5f0fb15SPaul Saab { 451a5f0fb15SPaul Saab c = *p; 45233096f16SXin LI if (!opt_lower && ASCII_IS_LOWER(c)) 45389dd99dcSXin LI c = ASCII_TO_UPPER(c); 454a5f0fb15SPaul Saab if (cmd_char(c) != CC_OK) 455a5f0fb15SPaul Saab return (MCA_DONE); 456a5f0fb15SPaul Saab } 457*c77c4889SXin LI } else if (!ambig) 458b7780dbeSXin LI { 459b7780dbeSXin LI bell(); 460a5f0fb15SPaul Saab } 461a5f0fb15SPaul Saab return (MCA_MORE); 462a5f0fb15SPaul Saab } 46333096f16SXin LI 46433096f16SXin LI /* 46533096f16SXin LI * Handle a char of an option toggle command. 46633096f16SXin LI */ 467*c77c4889SXin LI static int mca_opt_char(char c) 46833096f16SXin LI { 46933096f16SXin LI PARG parg; 47033096f16SXin LI 47133096f16SXin LI /* 47233096f16SXin LI * This may be a short option (single char), 47333096f16SXin LI * or one char of a long option name, 47433096f16SXin LI * or one char of the option parameter. 47533096f16SXin LI */ 47633096f16SXin LI if (curropt == NULL && len_cmdbuf() == 0) 47733096f16SXin LI { 47833096f16SXin LI int ret = mca_opt_first_char(c); 47933096f16SXin LI if (ret != NO_MCA) 48033096f16SXin LI return (ret); 48133096f16SXin LI } 48233096f16SXin LI if (optgetname) 48333096f16SXin LI { 48433096f16SXin LI /* We're getting a long option name. */ 48595270f73SXin LI if (!is_newline_char(c) && c != '=') 48633096f16SXin LI return (mca_opt_nonfirst_char(c)); 48733096f16SXin LI if (curropt == NULL) 48833096f16SXin LI { 48933096f16SXin LI parg.p_string = get_cmdbuf(); 49095270f73SXin LI if (parg.p_string == NULL) 49195270f73SXin LI return (MCA_MORE); 49233096f16SXin LI error("There is no --%s option", &parg); 49333096f16SXin LI return (MCA_DONE); 49433096f16SXin LI } 49533096f16SXin LI optgetname = FALSE; 49633096f16SXin LI cmd_reset(); 497a5f0fb15SPaul Saab } else 498a5f0fb15SPaul Saab { 49933096f16SXin LI if (is_erase_char(c)) 50033096f16SXin LI return (NO_MCA); 50133096f16SXin LI if (curropt != NULL) 50233096f16SXin LI /* We're getting the option parameter. */ 50333096f16SXin LI return (NO_MCA); 50433096f16SXin LI curropt = findopt(c); 50533096f16SXin LI if (curropt == NULL) 506a5f0fb15SPaul Saab { 50733096f16SXin LI parg.p_string = propt(c); 50833096f16SXin LI error("There is no %s option", &parg); 50933096f16SXin LI return (MCA_DONE); 51033096f16SXin LI } 511b7780dbeSXin LI opt_lower = ASCII_IS_LOWER(c); 51233096f16SXin LI } 51333096f16SXin LI /* 51433096f16SXin LI * If the option which was entered does not take a 51533096f16SXin LI * parameter, toggle the option immediately, 51633096f16SXin LI * so user doesn't have to hit RETURN. 51733096f16SXin LI */ 51833096f16SXin LI if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE || 51933096f16SXin LI !opt_has_param(curropt)) 52033096f16SXin LI { 521b7780dbeSXin LI toggle_option(curropt, opt_lower, "", optflag); 522a5f0fb15SPaul Saab return (MCA_DONE); 523a5f0fb15SPaul Saab } 524a5f0fb15SPaul Saab /* 52533096f16SXin LI * Display a prompt appropriate for the option parameter. 526a5f0fb15SPaul Saab */ 527*c77c4889SXin LI start_mca(A_OPT_TOGGLE, opt_prompt(curropt), NULL, 0); 528a5f0fb15SPaul Saab return (MCA_MORE); 52933096f16SXin LI } 530a5f0fb15SPaul Saab 531a5f0fb15SPaul Saab /* 53295270f73SXin LI * Normalize search type. 53395270f73SXin LI */ 534d713e089SXin LI public int norm_search_type(int st) 53595270f73SXin LI { 53695270f73SXin LI /* WRAP and PAST_EOF are mutually exclusive. */ 53795270f73SXin LI if ((st & (SRCH_PAST_EOF|SRCH_WRAP)) == (SRCH_PAST_EOF|SRCH_WRAP)) 53895270f73SXin LI st ^= SRCH_PAST_EOF; 53995270f73SXin LI return st; 54095270f73SXin LI } 54195270f73SXin LI 54295270f73SXin LI /* 54333096f16SXin LI * Handle a char of a search command. 54433096f16SXin LI */ 545*c77c4889SXin LI static int mca_search_char(char c) 54633096f16SXin LI { 54733096f16SXin LI int flag = 0; 54833096f16SXin LI 54933096f16SXin LI /* 550a5f0fb15SPaul Saab * Certain characters as the first char of 551a5f0fb15SPaul Saab * the pattern have special meaning: 552a5f0fb15SPaul Saab * ! Toggle the NO_MATCH flag 553a5f0fb15SPaul Saab * * Toggle the PAST_EOF flag 554a5f0fb15SPaul Saab * @ Toggle the FIRST_FILE flag 555a5f0fb15SPaul Saab */ 556*c77c4889SXin LI if (len_cmdbuf() > 0 || literal_char) 557*c77c4889SXin LI { 558*c77c4889SXin LI literal_char = FALSE; 55933096f16SXin LI return (NO_MCA); 560*c77c4889SXin LI } 561a5f0fb15SPaul Saab 562a5f0fb15SPaul Saab switch (c) 563a5f0fb15SPaul Saab { 564a5f0fb15SPaul Saab case '*': 565720c436cSXin LI if (less_is_more) 566a8f92a7cSPaul Saab break; 567a8f92a7cSPaul Saab case CONTROL('E'): /* ignore END of file */ 5687374caaaSXin LI if (mca != A_FILTER) 569a5f0fb15SPaul Saab flag = SRCH_PAST_EOF; 570f80a33eaSXin LI search_type &= ~SRCH_WRAP; 571a5f0fb15SPaul Saab break; 572a5f0fb15SPaul Saab case '@': 573720c436cSXin LI if (less_is_more) 574a8f92a7cSPaul Saab break; 575a8f92a7cSPaul Saab case CONTROL('F'): /* FIRST file */ 5767374caaaSXin LI if (mca != A_FILTER) 577a5f0fb15SPaul Saab flag = SRCH_FIRST_FILE; 578a5f0fb15SPaul Saab break; 579a5f0fb15SPaul Saab case CONTROL('K'): /* KEEP position */ 5807374caaaSXin LI if (mca != A_FILTER) 581a5f0fb15SPaul Saab flag = SRCH_NO_MOVE; 582a5f0fb15SPaul Saab break; 583d713e089SXin LI case CONTROL('S'): { /* SUBSEARCH */ 584f80a33eaSXin LI char buf[INT_STRLEN_BOUND(int)+24]; 585d713e089SXin LI SNPRINTF1(buf, sizeof(buf), "Sub-pattern (1-%d):", NUM_SEARCH_COLORS); 586d713e089SXin LI clear_bot(); 587d713e089SXin LI cmd_putstr(buf); 588d713e089SXin LI flush(); 589d713e089SXin LI c = getcc(); 590d713e089SXin LI if (c >= '1' && c <= '0'+NUM_SEARCH_COLORS) 591d713e089SXin LI flag = SRCH_SUBSEARCH(c-'0'); 592d713e089SXin LI else 593d713e089SXin LI flag = -1; /* calls mca_search() below to repaint */ 594d713e089SXin LI break; } 5952235c7feSXin LI case CONTROL('W'): /* WRAP around */ 5962235c7feSXin LI if (mca != A_FILTER) 5972235c7feSXin LI flag = SRCH_WRAP; 5982235c7feSXin LI break; 599a5f0fb15SPaul Saab case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */ 600a5f0fb15SPaul Saab flag = SRCH_NO_REGEX; 601a5f0fb15SPaul Saab break; 602a5f0fb15SPaul Saab case CONTROL('N'): /* NOT match */ 603a5f0fb15SPaul Saab case '!': 604a5f0fb15SPaul Saab flag = SRCH_NO_MATCH; 605a5f0fb15SPaul Saab break; 606*c77c4889SXin LI case CONTROL('L'): 607*c77c4889SXin LI literal_char = TRUE; 608*c77c4889SXin LI flag = -1; 609*c77c4889SXin LI break; 610a5f0fb15SPaul Saab } 61133096f16SXin LI 612a5f0fb15SPaul Saab if (flag != 0) 613a5f0fb15SPaul Saab { 614d713e089SXin LI if (flag != -1) 61595270f73SXin LI search_type = norm_search_type(search_type ^ flag); 616a5f0fb15SPaul Saab mca_search(); 617a5f0fb15SPaul Saab return (MCA_MORE); 618a5f0fb15SPaul Saab } 61933096f16SXin LI return (NO_MCA); 62033096f16SXin LI } 62133096f16SXin LI 62233096f16SXin LI /* 62333096f16SXin LI * Handle a character of a multi-character command. 62433096f16SXin LI */ 625*c77c4889SXin LI static int mca_char(char c) 62633096f16SXin LI { 62733096f16SXin LI int ret; 62833096f16SXin LI 62933096f16SXin LI switch (mca) 63033096f16SXin LI { 63133096f16SXin LI case 0: 63233096f16SXin LI /* 63333096f16SXin LI * We're not in a multicharacter command. 63433096f16SXin LI */ 63533096f16SXin LI return (NO_MCA); 63633096f16SXin LI 63733096f16SXin LI case A_PREFIX: 63833096f16SXin LI /* 63933096f16SXin LI * In the prefix of a command. 64033096f16SXin LI * This not considered a multichar command 64133096f16SXin LI * (even tho it uses cmdbuf, etc.). 64233096f16SXin LI * It is handled in the commands() switch. 64333096f16SXin LI */ 64433096f16SXin LI return (NO_MCA); 64533096f16SXin LI 64633096f16SXin LI case A_DIGIT: 64733096f16SXin LI /* 64833096f16SXin LI * Entering digits of a number. 64933096f16SXin LI * Terminated by a non-digit. 65033096f16SXin LI */ 6512235c7feSXin LI if ((c >= '0' && c <= '9') || c == '.') 6522235c7feSXin LI break; 6532235c7feSXin LI switch (editchar(c, ECF_PEEK|ECF_NOHISTORY|ECF_NOCOMPLETE|ECF_NORIGHTLEFT)) 65433096f16SXin LI { 6552235c7feSXin LI case A_NOACTION: 6562235c7feSXin LI /* 6572235c7feSXin LI * Ignore this char and get another one. 6582235c7feSXin LI */ 6592235c7feSXin LI return (MCA_MORE); 6602235c7feSXin LI case A_INVALID: 66133096f16SXin LI /* 66233096f16SXin LI * Not part of the number. 66333096f16SXin LI * End the number and treat this char 66433096f16SXin LI * as a normal command character. 66533096f16SXin LI */ 66633096f16SXin LI number = cmd_int(&fraction); 667b7780dbeSXin LI clear_mca(); 66833096f16SXin LI cmd_accept(); 66933096f16SXin LI return (NO_MCA); 67033096f16SXin LI } 67133096f16SXin LI break; 67233096f16SXin LI 67333096f16SXin LI case A_OPT_TOGGLE: 67433096f16SXin LI ret = mca_opt_char(c); 67533096f16SXin LI if (ret != NO_MCA) 67633096f16SXin LI return (ret); 67733096f16SXin LI break; 67833096f16SXin LI 67933096f16SXin LI case A_F_SEARCH: 68033096f16SXin LI case A_B_SEARCH: 68133096f16SXin LI case A_FILTER: 68233096f16SXin LI ret = mca_search_char(c); 68333096f16SXin LI if (ret != NO_MCA) 68433096f16SXin LI return (ret); 68533096f16SXin LI break; 68633096f16SXin LI 68733096f16SXin LI default: 68833096f16SXin LI /* Other multicharacter command. */ 689a5f0fb15SPaul Saab break; 690a5f0fb15SPaul Saab } 691a5f0fb15SPaul Saab 692a5f0fb15SPaul Saab /* 69333096f16SXin LI * The multichar command is terminated by a newline. 694a5f0fb15SPaul Saab */ 695b2ea2440SXin LI if (is_newline_char(c)) 696a5f0fb15SPaul Saab { 697a5f0fb15SPaul Saab /* 698a5f0fb15SPaul Saab * Execute the command. 699a5f0fb15SPaul Saab */ 700a5f0fb15SPaul Saab exec_mca(); 701a5f0fb15SPaul Saab return (MCA_DONE); 702a5f0fb15SPaul Saab } 703a5f0fb15SPaul Saab 704a5f0fb15SPaul Saab /* 705a5f0fb15SPaul Saab * Append the char to the command buffer. 706a5f0fb15SPaul Saab */ 707a5f0fb15SPaul Saab if (cmd_char(c) == CC_QUIT) 708a5f0fb15SPaul Saab /* 709a5f0fb15SPaul Saab * Abort the multi-char command. 710a5f0fb15SPaul Saab */ 711a5f0fb15SPaul Saab return (MCA_DONE); 712a5f0fb15SPaul Saab 7132235c7feSXin LI switch (mca) 7142235c7feSXin LI { 7152235c7feSXin LI case A_F_BRACKET: 7162235c7feSXin LI case A_B_BRACKET: 7172235c7feSXin LI if (len_cmdbuf() >= 2) 718a5f0fb15SPaul Saab { 719a5f0fb15SPaul Saab /* 720a5f0fb15SPaul Saab * Special case for the bracket-matching commands. 721a5f0fb15SPaul Saab * Execute the command after getting exactly two 722a5f0fb15SPaul Saab * characters from the user. 723a5f0fb15SPaul Saab */ 724a5f0fb15SPaul Saab exec_mca(); 725a5f0fb15SPaul Saab return (MCA_DONE); 726a5f0fb15SPaul Saab } 7272235c7feSXin LI break; 7282235c7feSXin LI case A_F_SEARCH: 7292235c7feSXin LI case A_B_SEARCH: 7302235c7feSXin LI if (incr_search) 7312235c7feSXin LI { 7322235c7feSXin LI /* Incremental search: do a search after every input char. */ 733d713e089SXin LI int st = (search_type & (SRCH_FORW|SRCH_BACK|SRCH_NO_MATCH|SRCH_NO_REGEX|SRCH_NO_MOVE|SRCH_WRAP|SRCH_SUBSEARCH_ALL)); 734*c77c4889SXin LI ssize_t save_updown; 735*c77c4889SXin LI constant char *pattern = get_cmdbuf(); 73695270f73SXin LI if (pattern == NULL) 73795270f73SXin LI return (MCA_MORE); 73895270f73SXin LI /* 73995270f73SXin LI * Must save updown_match because mca_search 74095270f73SXin LI * reinits it. That breaks history scrolling. 74195270f73SXin LI * {{ This is ugly. mca_search probably shouldn't call set_mlist. }} 74295270f73SXin LI */ 743*c77c4889SXin LI save_updown = save_updown_match(); 7442235c7feSXin LI cmd_exec(); 7452235c7feSXin LI if (*pattern == '\0') 7462235c7feSXin LI { 7472235c7feSXin LI /* User has backspaced to an empty pattern. */ 7482235c7feSXin LI undo_search(1); 7492235c7feSXin LI } else 7502235c7feSXin LI { 7512235c7feSXin LI if (search(st | SRCH_INCR, pattern, 1) != 0) 7522235c7feSXin LI /* No match, invalid pattern, etc. */ 7532235c7feSXin LI undo_search(1); 7542235c7feSXin LI } 7552235c7feSXin LI /* Redraw the search prompt and search string. */ 756*c77c4889SXin LI if (is_screen_trashed() || !full_screen) 757d713e089SXin LI { 758d713e089SXin LI clear(); 759d713e089SXin LI repaint(); 760d713e089SXin LI } 76195270f73SXin LI mca_search1(); 762*c77c4889SXin LI restore_updown_match(save_updown); 7632235c7feSXin LI cmd_repaint(NULL); 7642235c7feSXin LI } 7652235c7feSXin LI break; 7662235c7feSXin LI } 767a5f0fb15SPaul Saab 768a5f0fb15SPaul Saab /* 769a5f0fb15SPaul Saab * Need another character. 770a5f0fb15SPaul Saab */ 771a5f0fb15SPaul Saab return (MCA_MORE); 772a5f0fb15SPaul Saab } 773a5f0fb15SPaul Saab 774a5f0fb15SPaul Saab /* 775423c5ce5SXin LI * Discard any buffered file data. 776423c5ce5SXin LI */ 777d713e089SXin LI static void clear_buffers(void) 778423c5ce5SXin LI { 779423c5ce5SXin LI if (!(ch_getflags() & CH_CANSEEK)) 780423c5ce5SXin LI return; 781423c5ce5SXin LI ch_flush(); 782423c5ce5SXin LI clr_linenum(); 783423c5ce5SXin LI #if HILITE_SEARCH 784423c5ce5SXin LI clr_hilite(); 785423c5ce5SXin LI #endif 786423c5ce5SXin LI } 787423c5ce5SXin LI 788*c77c4889SXin LI public void screen_trashed_num(int trashed) 789*c77c4889SXin LI { 790*c77c4889SXin LI screen_trashed_value = trashed; 791*c77c4889SXin LI } 792*c77c4889SXin LI 793*c77c4889SXin LI public void screen_trashed(void) 794*c77c4889SXin LI { 795*c77c4889SXin LI screen_trashed_num(1); 796*c77c4889SXin LI } 797*c77c4889SXin LI 798*c77c4889SXin LI public int is_screen_trashed(void) 799*c77c4889SXin LI { 800*c77c4889SXin LI return screen_trashed_value; 801*c77c4889SXin LI } 802*c77c4889SXin LI 803423c5ce5SXin LI /* 804a5f0fb15SPaul Saab * Make sure the screen is displayed. 805a5f0fb15SPaul Saab */ 806d713e089SXin LI static void make_display(void) 807a5f0fb15SPaul Saab { 808a5f0fb15SPaul Saab /* 809d713e089SXin LI * If not full_screen, we can't rely on scrolling to fill the screen. 810d713e089SXin LI * We need to clear and repaint screen before any change. 811d713e089SXin LI */ 812d713e089SXin LI if (!full_screen && !(quit_if_one_screen && one_screen)) 813d713e089SXin LI clear(); 814d713e089SXin LI /* 815a5f0fb15SPaul Saab * If nothing is displayed yet, display starting from initial_scrpos. 816a5f0fb15SPaul Saab */ 817a5f0fb15SPaul Saab if (empty_screen()) 818a5f0fb15SPaul Saab { 819a5f0fb15SPaul Saab if (initial_scrpos.pos == NULL_POSITION) 820a5f0fb15SPaul Saab jump_loc(ch_zero(), 1); 821a5f0fb15SPaul Saab else 822a5f0fb15SPaul Saab jump_loc(initial_scrpos.pos, initial_scrpos.ln); 823*c77c4889SXin LI } else if (is_screen_trashed() || !full_screen) 824a5f0fb15SPaul Saab { 825423c5ce5SXin LI int save_top_scroll = top_scroll; 826423c5ce5SXin LI int save_ignore_eoi = ignore_eoi; 827a5f0fb15SPaul Saab top_scroll = 1; 828423c5ce5SXin LI ignore_eoi = 0; 829*c77c4889SXin LI if (is_screen_trashed() == 2) 830423c5ce5SXin LI { 831423c5ce5SXin LI /* Special case used by ignore_eoi: re-open the input file 832423c5ce5SXin LI * and jump to the end of the file. */ 833423c5ce5SXin LI reopen_curr_ifile(); 834423c5ce5SXin LI jump_forw(); 835423c5ce5SXin LI } 836a5f0fb15SPaul Saab repaint(); 837a5f0fb15SPaul Saab top_scroll = save_top_scroll; 838423c5ce5SXin LI ignore_eoi = save_ignore_eoi; 839a5f0fb15SPaul Saab } 840a5f0fb15SPaul Saab } 841a5f0fb15SPaul Saab 842a5f0fb15SPaul Saab /* 843a5f0fb15SPaul Saab * Display the appropriate prompt. 844a5f0fb15SPaul Saab */ 845d713e089SXin LI static void prompt(void) 846a5f0fb15SPaul Saab { 8471ea31627SRobert Watson constant char *p; 848a5f0fb15SPaul Saab 849*c77c4889SXin LI if (ungot != NULL && !ungot->ug_end_command) 850a5f0fb15SPaul Saab { 851a5f0fb15SPaul Saab /* 852a5f0fb15SPaul Saab * No prompt necessary if commands are from 853a5f0fb15SPaul Saab * ungotten chars rather than from the user. 854a5f0fb15SPaul Saab */ 855a5f0fb15SPaul Saab return; 856a5f0fb15SPaul Saab } 857a5f0fb15SPaul Saab 858a5f0fb15SPaul Saab /* 859a5f0fb15SPaul Saab * Make sure the screen is displayed. 860a5f0fb15SPaul Saab */ 861a5f0fb15SPaul Saab make_display(); 862a5f0fb15SPaul Saab bottompos = position(BOTTOM_PLUS_ONE); 863a5f0fb15SPaul Saab 864a5f0fb15SPaul Saab /* 8657374caaaSXin LI * If we've hit EOF on the last file and the -E flag is set, quit. 866a5f0fb15SPaul Saab */ 8677374caaaSXin LI if (get_quit_at_eof() == OPT_ONPLUS && 8687374caaaSXin LI eof_displayed() && !(ch_getflags() & CH_HELPFILE) && 869a5f0fb15SPaul Saab next_ifile(curr_ifile) == NULL_IFILE) 870a5f0fb15SPaul Saab quit(QUIT_OK); 8717374caaaSXin LI 872a5f0fb15SPaul Saab /* 8737374caaaSXin LI * If the entire file is displayed and the -F flag is set, quit. 874a5f0fb15SPaul Saab */ 8757374caaaSXin LI if (quit_if_one_screen && 8767374caaaSXin LI entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) && 877a5f0fb15SPaul Saab next_ifile(curr_ifile) == NULL_IFILE) 878a5f0fb15SPaul Saab quit(QUIT_OK); 87930a1828cSXin LI quit_if_one_screen = FALSE; /* only get one chance at this */ 880a5f0fb15SPaul Saab 8818fd4165cSPaul Saab #if MSDOS_COMPILER==WIN32C 8828fd4165cSPaul Saab /* 8838fd4165cSPaul Saab * In Win32, display the file name in the window title. 8848fd4165cSPaul Saab */ 8858fd4165cSPaul Saab if (!(ch_getflags() & CH_HELPFILE)) 886b7780dbeSXin LI { 887b7780dbeSXin LI WCHAR w[MAX_PATH+16]; 88895270f73SXin LI p = pr_expand("Less?f - %f."); 889*c77c4889SXin LI MultiByteToWideChar(less_acp, 0, p, -1, w, countof(w)); 890b7780dbeSXin LI SetConsoleTitleW(w); 891b7780dbeSXin LI } 8928fd4165cSPaul Saab #endif 893b7780dbeSXin LI 894a5f0fb15SPaul Saab /* 895a5f0fb15SPaul Saab * Select the proper prompt and display it. 896a5f0fb15SPaul Saab */ 897720c436cSXin LI /* 898720c436cSXin LI * If the previous action was a forward movement, 899720c436cSXin LI * don't clear the bottom line of the display; 900720c436cSXin LI * just print the prompt since the forward movement guarantees 901720c436cSXin LI * that we're in the right position to display the prompt. 902720c436cSXin LI * Clearing the line could cause a problem: for example, if the last 903720c436cSXin LI * line displayed ended at the right screen edge without a newline, 904720c436cSXin LI * then clearing would clear the last displayed line rather than 905720c436cSXin LI * the prompt line. 906720c436cSXin LI */ 907720c436cSXin LI if (!forw_prompt) 908720c436cSXin LI clear_bot(); 909a5f0fb15SPaul Saab clear_cmd(); 910720c436cSXin LI forw_prompt = 0; 911a5f0fb15SPaul Saab p = pr_string(); 9122235c7feSXin LI #if HILITE_SEARCH 9137374caaaSXin LI if (is_filtering()) 9147374caaaSXin LI putstr("& "); 9152235c7feSXin LI #endif 916*c77c4889SXin LI if (search_wrapped) 917*c77c4889SXin LI { 918*c77c4889SXin LI if (search_type & SRCH_BACK) 919*c77c4889SXin LI error("Search hit top; continuing at bottom", NULL_PARG); 920*c77c4889SXin LI else 921*c77c4889SXin LI error("Search hit bottom; continuing at top", NULL_PARG); 922*c77c4889SXin LI search_wrapped = FALSE; 923*c77c4889SXin LI } 924*c77c4889SXin LI #if OSC8_LINK 925*c77c4889SXin LI if (osc8_uri != NULL) 926*c77c4889SXin LI { 927*c77c4889SXin LI PARG parg; 928*c77c4889SXin LI parg.p_string = osc8_uri; 929*c77c4889SXin LI error("Link: %s", &parg); 930*c77c4889SXin LI free(osc8_uri); 931*c77c4889SXin LI osc8_uri = NULL; 932*c77c4889SXin LI } 933*c77c4889SXin LI #endif 93489dd99dcSXin LI if (p == NULL || *p == '\0') 9352235c7feSXin LI { 9362235c7feSXin LI at_enter(AT_NORMAL|AT_COLOR_PROMPT); 937a5f0fb15SPaul Saab putchr(':'); 9382235c7feSXin LI at_exit(); 9392235c7feSXin LI } else 940a5f0fb15SPaul Saab { 941b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 942b7780dbeSXin LI WCHAR w[MAX_PATH*2]; 943b7780dbeSXin LI char a[MAX_PATH*2]; 944*c77c4889SXin LI MultiByteToWideChar(less_acp, 0, p, -1, w, countof(w)); 945b7780dbeSXin LI WideCharToMultiByte(utf_mode ? CP_UTF8 : GetConsoleOutputCP(), 946b7780dbeSXin LI 0, w, -1, a, sizeof(a), NULL, NULL); 947b7780dbeSXin LI p = a; 948b7780dbeSXin LI #endif 94995270f73SXin LI load_line(p); 95095270f73SXin LI put_line(); 951a5f0fb15SPaul Saab } 952720c436cSXin LI clear_eol(); 953a5f0fb15SPaul Saab } 954a5f0fb15SPaul Saab 955a5f0fb15SPaul Saab /* 956a5f0fb15SPaul Saab * Display the less version message. 957a5f0fb15SPaul Saab */ 958d713e089SXin LI public void dispversion(void) 959a5f0fb15SPaul Saab { 960a5f0fb15SPaul Saab PARG parg; 961a5f0fb15SPaul Saab 962a5f0fb15SPaul Saab parg.p_string = version; 963a5f0fb15SPaul Saab error("less %s", &parg); 964a5f0fb15SPaul Saab } 965a5f0fb15SPaul Saab 966a5f0fb15SPaul Saab /* 967b2ea2440SXin LI * Return a character to complete a partial command, if possible. 968b2ea2440SXin LI */ 969*c77c4889SXin LI static char getcc_end_command(void) 970b2ea2440SXin LI { 971*c77c4889SXin LI int ch; 972b2ea2440SXin LI switch (mca) 973b2ea2440SXin LI { 974b2ea2440SXin LI case A_DIGIT: 975b2ea2440SXin LI /* We have a number but no command. Treat as #g. */ 976b2ea2440SXin LI return ('g'); 977b2ea2440SXin LI case A_F_SEARCH: 978b2ea2440SXin LI case A_B_SEARCH: 979d713e089SXin LI case A_FILTER: 980b2ea2440SXin LI /* We have "/string" but no newline. Add the \n. */ 981b2ea2440SXin LI return ('\n'); 982b2ea2440SXin LI default: 983b2ea2440SXin LI /* Some other incomplete command. Let user complete it. */ 984*c77c4889SXin LI if (ungot != NULL) 985*c77c4889SXin LI return ('\0'); 986*c77c4889SXin LI ch = getchr(); 987*c77c4889SXin LI if (ch < 0) ch = '\0'; 988*c77c4889SXin LI return (char) ch; 989b2ea2440SXin LI } 990b2ea2440SXin LI } 991b2ea2440SXin LI 992b2ea2440SXin LI /* 993*c77c4889SXin LI * Get a command character from the ungotten stack. 994*c77c4889SXin LI */ 995*c77c4889SXin LI static char get_ungot(lbool *p_end_command) 996*c77c4889SXin LI { 997*c77c4889SXin LI struct ungot *ug = ungot; 998*c77c4889SXin LI char c = ug->ug_char; 999*c77c4889SXin LI if (p_end_command != NULL) 1000*c77c4889SXin LI *p_end_command = ug->ug_end_command; 1001*c77c4889SXin LI ungot = ug->ug_next; 1002*c77c4889SXin LI free(ug); 1003*c77c4889SXin LI return c; 1004*c77c4889SXin LI } 1005*c77c4889SXin LI 1006*c77c4889SXin LI /* 1007*c77c4889SXin LI * Delete all ungotten characters. 1008*c77c4889SXin LI */ 1009*c77c4889SXin LI public void getcc_clear(void) 1010*c77c4889SXin LI { 1011*c77c4889SXin LI while (ungot != NULL) 1012*c77c4889SXin LI (void) get_ungot(NULL); 1013*c77c4889SXin LI } 1014*c77c4889SXin LI 1015*c77c4889SXin LI /* 1016a5f0fb15SPaul Saab * Get command character. 1017a5f0fb15SPaul Saab * The character normally comes from the keyboard, 1018a5f0fb15SPaul Saab * but may come from ungotten characters 1019a5f0fb15SPaul Saab * (characters previously given to ungetcc or ungetsc). 1020a5f0fb15SPaul Saab */ 1021*c77c4889SXin LI static char getccu(void) 1022a5f0fb15SPaul Saab { 1023*c77c4889SXin LI int c = 0; 1024*c77c4889SXin LI while (c == 0 && !ABORT_SIGS()) 10252235c7feSXin LI { 1026a15691bfSXin LI if (ungot == NULL) 102733096f16SXin LI { 1028b2ea2440SXin LI /* Normal case: no ungotten chars. 1029b2ea2440SXin LI * Get char from the user. */ 1030b2ea2440SXin LI c = getchr(); 1031*c77c4889SXin LI if (c < 0) return ('\0'); 1032b2ea2440SXin LI } else 1033a15691bfSXin LI { 1034b2ea2440SXin LI /* Ungotten chars available: 1035b2ea2440SXin LI * Take the top of stack (most recent). */ 1036*c77c4889SXin LI lbool end_command; 1037*c77c4889SXin LI c = get_ungot(&end_command); 1038*c77c4889SXin LI if (end_command) 1039b2ea2440SXin LI c = getcc_end_command(); 1040a5f0fb15SPaul Saab } 10412235c7feSXin LI } 1042*c77c4889SXin LI return ((char) c); 104333096f16SXin LI } 1044b2ea2440SXin LI 1045b2ea2440SXin LI /* 1046b2ea2440SXin LI * Get a command character, but if we receive the orig sequence, 1047b2ea2440SXin LI * convert it to the repl sequence. 1048b2ea2440SXin LI */ 1049*c77c4889SXin LI static char getcc_repl(char constant *orig, char constant *repl, char (*gr_getc)(void), void (*gr_ungetc)(char)) 1050b2ea2440SXin LI { 1051*c77c4889SXin LI char c; 1052*c77c4889SXin LI char keys[16]; 1053*c77c4889SXin LI size_t ki = 0; 1054b2ea2440SXin LI 1055b2ea2440SXin LI c = (*gr_getc)(); 1056b2ea2440SXin LI if (orig == NULL || orig[0] == '\0') 1057b2ea2440SXin LI return c; 1058b2ea2440SXin LI for (;;) 1059b2ea2440SXin LI { 1060b2ea2440SXin LI keys[ki] = c; 1061b2ea2440SXin LI if (c != orig[ki] || ki >= sizeof(keys)-1) 1062b2ea2440SXin LI { 1063b2ea2440SXin LI /* This is not orig we have been receiving. 1064b2ea2440SXin LI * If we have stashed chars in keys[], 1065b2ea2440SXin LI * unget them and return the first one. */ 1066b2ea2440SXin LI while (ki > 0) 1067b2ea2440SXin LI (*gr_ungetc)(keys[ki--]); 1068b2ea2440SXin LI return keys[0]; 1069b2ea2440SXin LI } 1070b2ea2440SXin LI if (orig[++ki] == '\0') 1071b2ea2440SXin LI { 1072b2ea2440SXin LI /* We've received the full orig sequence. 1073b2ea2440SXin LI * Return the repl sequence. */ 1074b2ea2440SXin LI ki = strlen(repl)-1; 1075b2ea2440SXin LI while (ki > 0) 1076b2ea2440SXin LI (*gr_ungetc)(repl[ki--]); 1077b2ea2440SXin LI return repl[0]; 1078b2ea2440SXin LI } 1079b2ea2440SXin LI /* We've received a partial orig sequence (ki chars of it). 1080b2ea2440SXin LI * Get next char and see if it continues to match orig. */ 1081b2ea2440SXin LI c = (*gr_getc)(); 1082b2ea2440SXin LI } 1083b2ea2440SXin LI } 1084b2ea2440SXin LI 1085b2ea2440SXin LI /* 1086b2ea2440SXin LI * Get command character. 1087b2ea2440SXin LI */ 1088*c77c4889SXin LI public char getcc(void) 1089b2ea2440SXin LI { 1090b2ea2440SXin LI /* Replace kent (keypad Enter) with a newline. */ 1091b2ea2440SXin LI return getcc_repl(kent, "\n", getccu, ungetcc); 109233096f16SXin LI } 109333096f16SXin LI 1094a5f0fb15SPaul Saab /* 1095a5f0fb15SPaul Saab * "Unget" a command character. 1096a5f0fb15SPaul Saab * The next getcc() will return this character. 1097a5f0fb15SPaul Saab */ 1098*c77c4889SXin LI public void ungetcc(char c) 1099a5f0fb15SPaul Saab { 110033096f16SXin LI struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); 110133096f16SXin LI 1102b2ea2440SXin LI ug->ug_char = c; 110333096f16SXin LI ug->ug_next = ungot; 110433096f16SXin LI ungot = ug; 1105a5f0fb15SPaul Saab } 1106a5f0fb15SPaul Saab 1107a5f0fb15SPaul Saab /* 11082235c7feSXin LI * "Unget" a command character. 11092235c7feSXin LI * If any other chars are already ungotten, put this one after those. 11102235c7feSXin LI */ 1111*c77c4889SXin LI static void ungetcc_back1(char c, lbool end_command) 11122235c7feSXin LI { 11132235c7feSXin LI struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); 11142235c7feSXin LI ug->ug_char = c; 1115*c77c4889SXin LI ug->ug_end_command = end_command; 11162235c7feSXin LI ug->ug_next = NULL; 11172235c7feSXin LI if (ungot == NULL) 11182235c7feSXin LI ungot = ug; 11192235c7feSXin LI else 11202235c7feSXin LI { 11212235c7feSXin LI struct ungot *pu; 11222235c7feSXin LI for (pu = ungot; pu->ug_next != NULL; pu = pu->ug_next) 11232235c7feSXin LI continue; 11242235c7feSXin LI pu->ug_next = ug; 11252235c7feSXin LI } 11262235c7feSXin LI } 11272235c7feSXin LI 1128*c77c4889SXin LI public void ungetcc_back(char c) 1129*c77c4889SXin LI { 1130*c77c4889SXin LI ungetcc_back1(c, FALSE); 1131*c77c4889SXin LI } 1132*c77c4889SXin LI 1133*c77c4889SXin LI public void ungetcc_end_command(void) 1134*c77c4889SXin LI { 1135*c77c4889SXin LI ungetcc_back1('\0', TRUE); 1136*c77c4889SXin LI } 1137*c77c4889SXin LI 11382235c7feSXin LI /* 1139a5f0fb15SPaul Saab * Unget a whole string of command characters. 1140a5f0fb15SPaul Saab * The next sequence of getcc()'s will return this string. 1141a5f0fb15SPaul Saab */ 1142*c77c4889SXin LI public void ungetsc(constant char *s) 1143a5f0fb15SPaul Saab { 11442235c7feSXin LI while (*s != '\0') 11452235c7feSXin LI ungetcc_back(*s++); 1146a5f0fb15SPaul Saab } 1147a5f0fb15SPaul Saab 1148a5f0fb15SPaul Saab /* 1149b2ea2440SXin LI * Peek the next command character, without consuming it. 1150b2ea2440SXin LI */ 1151*c77c4889SXin LI public char peekcc(void) 1152b2ea2440SXin LI { 1153*c77c4889SXin LI char c = getcc(); 1154b2ea2440SXin LI ungetcc(c); 1155b2ea2440SXin LI return c; 1156b2ea2440SXin LI } 1157b2ea2440SXin LI 1158b2ea2440SXin LI /* 1159a5f0fb15SPaul Saab * Search for a pattern, possibly in multiple files. 1160a5f0fb15SPaul Saab * If SRCH_FIRST_FILE is set, begin searching at the first file. 1161a5f0fb15SPaul Saab * If SRCH_PAST_EOF is set, continue the search thru multiple files. 1162a5f0fb15SPaul Saab */ 1163*c77c4889SXin LI static void multi_search(constant char *pattern, int n, int silent) 1164a5f0fb15SPaul Saab { 11651ea31627SRobert Watson int nomore; 1166a5f0fb15SPaul Saab IFILE save_ifile; 1167*c77c4889SXin LI lbool changed_file; 1168a5f0fb15SPaul Saab 1169*c77c4889SXin LI changed_file = FALSE; 1170a5f0fb15SPaul Saab save_ifile = save_curr_ifile(); 1171a5f0fb15SPaul Saab 1172d713e089SXin LI if ((search_type & (SRCH_FORW|SRCH_BACK)) == 0) 1173d713e089SXin LI search_type |= SRCH_FORW; 1174a5f0fb15SPaul Saab if (search_type & SRCH_FIRST_FILE) 1175a5f0fb15SPaul Saab { 1176a5f0fb15SPaul Saab /* 1177a5f0fb15SPaul Saab * Start at the first (or last) file 1178a5f0fb15SPaul Saab * in the command line list. 1179a5f0fb15SPaul Saab */ 1180a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 1181a5f0fb15SPaul Saab nomore = edit_first(); 1182a5f0fb15SPaul Saab else 1183a5f0fb15SPaul Saab nomore = edit_last(); 1184a5f0fb15SPaul Saab if (nomore) 1185a5f0fb15SPaul Saab { 1186a5f0fb15SPaul Saab unsave_ifile(save_ifile); 1187a5f0fb15SPaul Saab return; 1188a5f0fb15SPaul Saab } 1189*c77c4889SXin LI changed_file = TRUE; 1190a5f0fb15SPaul Saab search_type &= ~SRCH_FIRST_FILE; 1191a5f0fb15SPaul Saab } 1192a5f0fb15SPaul Saab 1193a5f0fb15SPaul Saab for (;;) 1194a5f0fb15SPaul Saab { 1195a5f0fb15SPaul Saab n = search(search_type, pattern, n); 1196a5f0fb15SPaul Saab /* 1197a5f0fb15SPaul Saab * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared 1198a5f0fb15SPaul Saab * after being used once. This allows "n" to work after 1199a5f0fb15SPaul Saab * using a /@@ search. 1200a5f0fb15SPaul Saab */ 1201a5f0fb15SPaul Saab search_type &= ~SRCH_NO_MOVE; 1202d713e089SXin LI last_search_type = search_type; 1203a5f0fb15SPaul Saab if (n == 0) 1204a5f0fb15SPaul Saab { 1205a5f0fb15SPaul Saab /* 1206a5f0fb15SPaul Saab * Found it. 1207a5f0fb15SPaul Saab */ 1208a5f0fb15SPaul Saab unsave_ifile(save_ifile); 1209a5f0fb15SPaul Saab return; 1210a5f0fb15SPaul Saab } 1211a5f0fb15SPaul Saab 1212a5f0fb15SPaul Saab if (n < 0) 1213a5f0fb15SPaul Saab /* 1214a5f0fb15SPaul Saab * Some kind of error in the search. 1215a5f0fb15SPaul Saab * Error message has been printed by search(). 1216a5f0fb15SPaul Saab */ 1217a5f0fb15SPaul Saab break; 1218a5f0fb15SPaul Saab 1219a5f0fb15SPaul Saab if ((search_type & SRCH_PAST_EOF) == 0) 1220a5f0fb15SPaul Saab /* 1221a5f0fb15SPaul Saab * We didn't find a match, but we're 1222a5f0fb15SPaul Saab * supposed to search only one file. 1223a5f0fb15SPaul Saab */ 1224a5f0fb15SPaul Saab break; 1225a5f0fb15SPaul Saab /* 1226a5f0fb15SPaul Saab * Move on to the next file. 1227a5f0fb15SPaul Saab */ 1228a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 1229a5f0fb15SPaul Saab nomore = edit_next(1); 1230a5f0fb15SPaul Saab else 1231a5f0fb15SPaul Saab nomore = edit_prev(1); 1232a5f0fb15SPaul Saab if (nomore) 1233a5f0fb15SPaul Saab break; 1234*c77c4889SXin LI changed_file = TRUE; 1235a5f0fb15SPaul Saab } 1236a5f0fb15SPaul Saab 1237a5f0fb15SPaul Saab /* 1238a5f0fb15SPaul Saab * Didn't find it. 1239a5f0fb15SPaul Saab * Print an error message if we haven't already. 1240a5f0fb15SPaul Saab */ 1241a15691bfSXin LI if (n > 0 && !silent) 1242a5f0fb15SPaul Saab error("Pattern not found", NULL_PARG); 1243a5f0fb15SPaul Saab 1244a5f0fb15SPaul Saab if (changed_file) 1245a5f0fb15SPaul Saab { 1246a5f0fb15SPaul Saab /* 1247a5f0fb15SPaul Saab * Restore the file we were originally viewing. 1248a5f0fb15SPaul Saab */ 1249a5f0fb15SPaul Saab reedit_ifile(save_ifile); 125089dd99dcSXin LI } else 125189dd99dcSXin LI { 125289dd99dcSXin LI unsave_ifile(save_ifile); 1253a5f0fb15SPaul Saab } 1254a5f0fb15SPaul Saab } 1255a5f0fb15SPaul Saab 1256a5f0fb15SPaul Saab /* 125796e55cc7SXin LI * Forward forever, or until a highlighted line appears. 125896e55cc7SXin LI */ 1259d713e089SXin LI static int forw_loop(int until_hilite) 126096e55cc7SXin LI { 126196e55cc7SXin LI POSITION curr_len; 126296e55cc7SXin LI 126396e55cc7SXin LI if (ch_getflags() & CH_HELPFILE) 126496e55cc7SXin LI return (A_NOACTION); 126596e55cc7SXin LI 126696e55cc7SXin LI cmd_exec(); 1267a15691bfSXin LI jump_forw_buffered(); 126896e55cc7SXin LI curr_len = ch_length(); 126996e55cc7SXin LI highest_hilite = until_hilite ? curr_len : NULL_POSITION; 127096e55cc7SXin LI ignore_eoi = 1; 127196e55cc7SXin LI while (!sigs) 127296e55cc7SXin LI { 127396e55cc7SXin LI if (until_hilite && highest_hilite > curr_len) 127496e55cc7SXin LI { 127596e55cc7SXin LI bell(); 127696e55cc7SXin LI break; 127796e55cc7SXin LI } 127896e55cc7SXin LI make_display(); 127996e55cc7SXin LI forward(1, 0, 0); 128096e55cc7SXin LI } 128196e55cc7SXin LI ignore_eoi = 0; 1282e2449719SXin LI ch_set_eof(); 128396e55cc7SXin LI 128496e55cc7SXin LI /* 128596e55cc7SXin LI * This gets us back in "F mode" after processing 128696e55cc7SXin LI * a non-abort signal (e.g. window-change). 128796e55cc7SXin LI */ 128896e55cc7SXin LI if (sigs && !ABORT_SIGS()) 1289e2449719SXin LI return (until_hilite ? A_F_UNTIL_HILITE : A_F_FOREVER); 1290e2449719SXin LI 129196e55cc7SXin LI return (A_NOACTION); 129296e55cc7SXin LI } 129396e55cc7SXin LI 129496e55cc7SXin LI /* 1295a5f0fb15SPaul Saab * Main command processor. 1296a5f0fb15SPaul Saab * Accept and execute commands until a quit command. 1297a5f0fb15SPaul Saab */ 1298d713e089SXin LI public void commands(void) 1299a5f0fb15SPaul Saab { 1300*c77c4889SXin LI char c; 13011ea31627SRobert Watson int action; 1302*c77c4889SXin LI constant char *cbuf; 1303*c77c4889SXin LI constant char *msg; 1304a5f0fb15SPaul Saab int newaction; 13052235c7feSXin LI int save_jump_sline; 1306a5f0fb15SPaul Saab int save_search_type; 1307*c77c4889SXin LI constant char *extra; 1308a5f0fb15SPaul Saab PARG parg; 1309a5f0fb15SPaul Saab IFILE old_ifile; 1310a5f0fb15SPaul Saab IFILE new_ifile; 1311*c77c4889SXin LI constant char *tagfile; 1312a5f0fb15SPaul Saab 1313a5f0fb15SPaul Saab search_type = SRCH_FORW; 1314a5f0fb15SPaul Saab wscroll = (sc_height + 1) / 2; 1315a5f0fb15SPaul Saab newaction = A_NOACTION; 1316a5f0fb15SPaul Saab 1317a5f0fb15SPaul Saab for (;;) 1318a5f0fb15SPaul Saab { 1319b7780dbeSXin LI clear_mca(); 1320a5f0fb15SPaul Saab cmd_accept(); 1321a5f0fb15SPaul Saab number = 0; 132233096f16SXin LI curropt = NULL; 1323a5f0fb15SPaul Saab 1324a5f0fb15SPaul Saab /* 1325a5f0fb15SPaul Saab * See if any signals need processing. 1326a5f0fb15SPaul Saab */ 1327a5f0fb15SPaul Saab if (sigs) 1328a5f0fb15SPaul Saab { 1329a5f0fb15SPaul Saab psignals(); 1330a5f0fb15SPaul Saab if (quitting) 1331a5f0fb15SPaul Saab quit(QUIT_SAVED_STATUS); 1332a5f0fb15SPaul Saab } 1333a5f0fb15SPaul Saab 1334a5f0fb15SPaul Saab /* 1335a5f0fb15SPaul Saab * See if window size changed, for systems that don't 1336a5f0fb15SPaul Saab * generate SIGWINCH. 1337a5f0fb15SPaul Saab */ 1338a5f0fb15SPaul Saab check_winch(); 1339a5f0fb15SPaul Saab 1340a5f0fb15SPaul Saab /* 1341a5f0fb15SPaul Saab * Display prompt and accept a character. 1342a5f0fb15SPaul Saab */ 1343a5f0fb15SPaul Saab cmd_reset(); 1344a5f0fb15SPaul Saab prompt(); 1345a5f0fb15SPaul Saab if (sigs) 1346a5f0fb15SPaul Saab continue; 1347a5f0fb15SPaul Saab if (newaction == A_NOACTION) 1348a5f0fb15SPaul Saab c = getcc(); 1349a5f0fb15SPaul Saab 1350a5f0fb15SPaul Saab again: 1351a5f0fb15SPaul Saab if (sigs) 1352a5f0fb15SPaul Saab continue; 1353a5f0fb15SPaul Saab 1354a5f0fb15SPaul Saab if (newaction != A_NOACTION) 1355a5f0fb15SPaul Saab { 1356a5f0fb15SPaul Saab action = newaction; 1357a5f0fb15SPaul Saab newaction = A_NOACTION; 1358a5f0fb15SPaul Saab } else 1359a5f0fb15SPaul Saab { 1360a5f0fb15SPaul Saab /* 1361a5f0fb15SPaul Saab * If we are in a multicharacter command, call mca_char. 1362a5f0fb15SPaul Saab * Otherwise we call fcmd_decode to determine the 1363a5f0fb15SPaul Saab * action to be performed. 1364a5f0fb15SPaul Saab */ 1365a5f0fb15SPaul Saab if (mca) 1366a5f0fb15SPaul Saab switch (mca_char(c)) 1367a5f0fb15SPaul Saab { 1368a5f0fb15SPaul Saab case MCA_MORE: 1369a5f0fb15SPaul Saab /* 1370a5f0fb15SPaul Saab * Need another character. 1371a5f0fb15SPaul Saab */ 1372a5f0fb15SPaul Saab c = getcc(); 1373a5f0fb15SPaul Saab goto again; 1374a5f0fb15SPaul Saab case MCA_DONE: 1375a5f0fb15SPaul Saab /* 1376a5f0fb15SPaul Saab * Command has been handled by mca_char. 1377a5f0fb15SPaul Saab * Start clean with a prompt. 1378a5f0fb15SPaul Saab */ 1379a5f0fb15SPaul Saab continue; 1380a5f0fb15SPaul Saab case NO_MCA: 1381a5f0fb15SPaul Saab /* 1382a5f0fb15SPaul Saab * Not a multi-char command 1383a5f0fb15SPaul Saab * (at least, not anymore). 1384a5f0fb15SPaul Saab */ 1385a5f0fb15SPaul Saab break; 1386a5f0fb15SPaul Saab } 1387a5f0fb15SPaul Saab 1388a5f0fb15SPaul Saab /* 1389a5f0fb15SPaul Saab * Decode the command character and decide what to do. 1390a5f0fb15SPaul Saab */ 1391*c77c4889SXin LI extra = NULL; 1392a5f0fb15SPaul Saab if (mca) 1393a5f0fb15SPaul Saab { 1394a5f0fb15SPaul Saab /* 1395a5f0fb15SPaul Saab * We're in a multichar command. 1396a5f0fb15SPaul Saab * Add the character to the command buffer 1397a5f0fb15SPaul Saab * and display it on the screen. 1398a5f0fb15SPaul Saab * If the user backspaces past the start 1399a5f0fb15SPaul Saab * of the line, abort the command. 1400a5f0fb15SPaul Saab */ 1401a5f0fb15SPaul Saab if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0) 1402a5f0fb15SPaul Saab continue; 1403a5f0fb15SPaul Saab cbuf = get_cmdbuf(); 140495270f73SXin LI if (cbuf == NULL) 140595270f73SXin LI continue; 1406*c77c4889SXin LI action = fcmd_decode(cbuf, &extra); 1407a5f0fb15SPaul Saab } else 1408a5f0fb15SPaul Saab { 1409a5f0fb15SPaul Saab /* 1410a5f0fb15SPaul Saab * Don't use cmd_char if we're starting fresh 1411a5f0fb15SPaul Saab * at the beginning of a command, because we 1412a5f0fb15SPaul Saab * don't want to echo the command until we know 1413a5f0fb15SPaul Saab * it is a multichar command. We also don't 1414a5f0fb15SPaul Saab * want erase_char/kill_char to be treated 1415a5f0fb15SPaul Saab * as line editing characters. 1416a5f0fb15SPaul Saab */ 1417*c77c4889SXin LI constant char tbuf[2] = { c, '\0' }; 1418*c77c4889SXin LI action = fcmd_decode(tbuf, &extra); 1419a5f0fb15SPaul Saab } 1420a5f0fb15SPaul Saab /* 1421a5f0fb15SPaul Saab * If an "extra" string was returned, 1422a5f0fb15SPaul Saab * process it as a string of command characters. 1423a5f0fb15SPaul Saab */ 1424a5f0fb15SPaul Saab if (extra != NULL) 1425a5f0fb15SPaul Saab ungetsc(extra); 1426a5f0fb15SPaul Saab } 1427a5f0fb15SPaul Saab /* 1428a5f0fb15SPaul Saab * Clear the cmdbuf string. 1429a5f0fb15SPaul Saab * (But not if we're in the prefix of a command, 1430a5f0fb15SPaul Saab * because the partial command string is kept there.) 1431a5f0fb15SPaul Saab */ 1432a5f0fb15SPaul Saab if (action != A_PREFIX) 1433a5f0fb15SPaul Saab cmd_reset(); 1434a5f0fb15SPaul Saab 1435a5f0fb15SPaul Saab switch (action) 1436a5f0fb15SPaul Saab { 1437a5f0fb15SPaul Saab case A_DIGIT: 1438a5f0fb15SPaul Saab /* 1439a5f0fb15SPaul Saab * First digit of a number. 1440a5f0fb15SPaul Saab */ 1441*c77c4889SXin LI start_mca(A_DIGIT, ":", NULL, CF_QUIT_ON_ERASE); 1442a5f0fb15SPaul Saab goto again; 1443a5f0fb15SPaul Saab 1444a5f0fb15SPaul Saab case A_F_WINDOW: 1445a5f0fb15SPaul Saab /* 1446a5f0fb15SPaul Saab * Forward one window (and set the window size). 1447a5f0fb15SPaul Saab */ 1448a5f0fb15SPaul Saab if (number > 0) 14491ede1615STim J. Robbins swindow = (int) number; 1450a5f0fb15SPaul Saab /* FALLTHRU */ 1451a5f0fb15SPaul Saab case A_F_SCREEN: 1452a5f0fb15SPaul Saab /* 1453a5f0fb15SPaul Saab * Forward one screen. 1454a5f0fb15SPaul Saab */ 1455a5f0fb15SPaul Saab if (number <= 0) 1456a5f0fb15SPaul Saab number = get_swindow(); 1457a5f0fb15SPaul Saab cmd_exec(); 1458a5f0fb15SPaul Saab if (show_attn) 1459a5f0fb15SPaul Saab set_attnpos(bottompos); 14601ede1615STim J. Robbins forward((int) number, 0, 1); 1461a5f0fb15SPaul Saab break; 1462a5f0fb15SPaul Saab 1463a5f0fb15SPaul Saab case A_B_WINDOW: 1464a5f0fb15SPaul Saab /* 1465a5f0fb15SPaul Saab * Backward one window (and set the window size). 1466a5f0fb15SPaul Saab */ 1467a5f0fb15SPaul Saab if (number > 0) 14681ede1615STim J. Robbins swindow = (int) number; 1469a5f0fb15SPaul Saab /* FALLTHRU */ 1470a5f0fb15SPaul Saab case A_B_SCREEN: 1471a5f0fb15SPaul Saab /* 1472a5f0fb15SPaul Saab * Backward one screen. 1473a5f0fb15SPaul Saab */ 1474a5f0fb15SPaul Saab if (number <= 0) 1475a5f0fb15SPaul Saab number = get_swindow(); 1476a5f0fb15SPaul Saab cmd_exec(); 14771ede1615STim J. Robbins backward((int) number, 0, 1); 1478a5f0fb15SPaul Saab break; 1479a5f0fb15SPaul Saab 1480a5f0fb15SPaul Saab case A_F_LINE: 1481a5f0fb15SPaul Saab /* 1482a5f0fb15SPaul Saab * Forward N (default 1) line. 1483a5f0fb15SPaul Saab */ 1484a5f0fb15SPaul Saab if (number <= 0) 1485a5f0fb15SPaul Saab number = 1; 1486a5f0fb15SPaul Saab cmd_exec(); 1487a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS && number > 1) 1488a5f0fb15SPaul Saab set_attnpos(bottompos); 14891ede1615STim J. Robbins forward((int) number, 0, 0); 1490a5f0fb15SPaul Saab break; 1491a5f0fb15SPaul Saab 1492a5f0fb15SPaul Saab case A_B_LINE: 1493a5f0fb15SPaul Saab /* 1494a5f0fb15SPaul Saab * Backward N (default 1) line. 1495a5f0fb15SPaul Saab */ 1496a5f0fb15SPaul Saab if (number <= 0) 1497a5f0fb15SPaul Saab number = 1; 1498a5f0fb15SPaul Saab cmd_exec(); 14991ede1615STim J. Robbins backward((int) number, 0, 0); 1500a5f0fb15SPaul Saab break; 1501a5f0fb15SPaul Saab 1502b7780dbeSXin LI case A_F_MOUSE: 1503b7780dbeSXin LI /* 1504b7780dbeSXin LI * Forward wheel_lines lines. 1505b7780dbeSXin LI */ 1506b7780dbeSXin LI cmd_exec(); 1507b7780dbeSXin LI forward(wheel_lines, 0, 0); 1508b7780dbeSXin LI break; 1509b7780dbeSXin LI 1510b7780dbeSXin LI case A_B_MOUSE: 1511b7780dbeSXin LI /* 1512b7780dbeSXin LI * Backward wheel_lines lines. 1513b7780dbeSXin LI */ 1514b7780dbeSXin LI cmd_exec(); 1515b7780dbeSXin LI backward(wheel_lines, 0, 0); 1516b7780dbeSXin LI break; 1517b7780dbeSXin LI 1518a5f0fb15SPaul Saab case A_FF_LINE: 1519a5f0fb15SPaul Saab /* 1520a5f0fb15SPaul Saab * Force forward N (default 1) line. 1521a5f0fb15SPaul Saab */ 1522a5f0fb15SPaul Saab if (number <= 0) 1523a5f0fb15SPaul Saab number = 1; 1524a5f0fb15SPaul Saab cmd_exec(); 1525a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS && number > 1) 1526a5f0fb15SPaul Saab set_attnpos(bottompos); 15271ede1615STim J. Robbins forward((int) number, 1, 0); 1528a5f0fb15SPaul Saab break; 1529a5f0fb15SPaul Saab 1530a5f0fb15SPaul Saab case A_BF_LINE: 1531a5f0fb15SPaul Saab /* 1532a5f0fb15SPaul Saab * Force backward N (default 1) line. 1533a5f0fb15SPaul Saab */ 1534a5f0fb15SPaul Saab if (number <= 0) 1535a5f0fb15SPaul Saab number = 1; 1536a5f0fb15SPaul Saab cmd_exec(); 15371ede1615STim J. Robbins backward((int) number, 1, 0); 1538a5f0fb15SPaul Saab break; 1539a5f0fb15SPaul Saab 1540a5f0fb15SPaul Saab case A_FF_SCREEN: 1541a5f0fb15SPaul Saab /* 1542a5f0fb15SPaul Saab * Force forward one screen. 1543a5f0fb15SPaul Saab */ 1544a5f0fb15SPaul Saab if (number <= 0) 1545a5f0fb15SPaul Saab number = get_swindow(); 1546a5f0fb15SPaul Saab cmd_exec(); 1547a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS) 1548a5f0fb15SPaul Saab set_attnpos(bottompos); 15491ede1615STim J. Robbins forward((int) number, 1, 0); 1550a5f0fb15SPaul Saab break; 1551a5f0fb15SPaul Saab 1552a5f0fb15SPaul Saab case A_F_FOREVER: 1553a5f0fb15SPaul Saab /* 1554a5f0fb15SPaul Saab * Forward forever, ignoring EOF. 1555a5f0fb15SPaul Saab */ 1556a15691bfSXin LI if (show_attn) 1557a15691bfSXin LI set_attnpos(bottompos); 155896e55cc7SXin LI newaction = forw_loop(0); 1559a5f0fb15SPaul Saab break; 156096e55cc7SXin LI 156196e55cc7SXin LI case A_F_UNTIL_HILITE: 156296e55cc7SXin LI newaction = forw_loop(1); 1563a5f0fb15SPaul Saab break; 1564a5f0fb15SPaul Saab 1565a5f0fb15SPaul Saab case A_F_SCROLL: 1566a5f0fb15SPaul Saab /* 1567a5f0fb15SPaul Saab * Forward N lines 1568a5f0fb15SPaul Saab * (default same as last 'd' or 'u' command). 1569a5f0fb15SPaul Saab */ 1570a5f0fb15SPaul Saab if (number > 0) 15711ede1615STim J. Robbins wscroll = (int) number; 1572a5f0fb15SPaul Saab cmd_exec(); 1573a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS) 1574a5f0fb15SPaul Saab set_attnpos(bottompos); 1575a5f0fb15SPaul Saab forward(wscroll, 0, 0); 1576a5f0fb15SPaul Saab break; 1577a5f0fb15SPaul Saab 1578a5f0fb15SPaul Saab case A_B_SCROLL: 1579a5f0fb15SPaul Saab /* 1580a5f0fb15SPaul Saab * Forward N lines 1581a5f0fb15SPaul Saab * (default same as last 'd' or 'u' command). 1582a5f0fb15SPaul Saab */ 1583a5f0fb15SPaul Saab if (number > 0) 15841ede1615STim J. Robbins wscroll = (int) number; 1585a5f0fb15SPaul Saab cmd_exec(); 1586a5f0fb15SPaul Saab backward(wscroll, 0, 0); 1587a5f0fb15SPaul Saab break; 1588a5f0fb15SPaul Saab 1589a5f0fb15SPaul Saab case A_FREPAINT: 1590a5f0fb15SPaul Saab /* 1591a5f0fb15SPaul Saab * Flush buffers, then repaint screen. 1592a5f0fb15SPaul Saab * Don't flush the buffers on a pipe! 1593a5f0fb15SPaul Saab */ 1594423c5ce5SXin LI clear_buffers(); 1595a5f0fb15SPaul Saab /* FALLTHRU */ 1596a5f0fb15SPaul Saab case A_REPAINT: 1597a5f0fb15SPaul Saab /* 1598a5f0fb15SPaul Saab * Repaint screen. 1599a5f0fb15SPaul Saab */ 1600a5f0fb15SPaul Saab cmd_exec(); 1601a5f0fb15SPaul Saab repaint(); 1602a5f0fb15SPaul Saab break; 1603a5f0fb15SPaul Saab 1604a5f0fb15SPaul Saab case A_GOLINE: 1605a5f0fb15SPaul Saab /* 1606a5f0fb15SPaul Saab * Go to line N, default beginning of file. 16072235c7feSXin LI * If N <= 0, ignore jump_sline in order to avoid 16082235c7feSXin LI * empty lines before the beginning of the file. 1609a5f0fb15SPaul Saab */ 16102235c7feSXin LI save_jump_sline = jump_sline; 1611a5f0fb15SPaul Saab if (number <= 0) 16122235c7feSXin LI { 1613a5f0fb15SPaul Saab number = 1; 16142235c7feSXin LI jump_sline = 0; 16152235c7feSXin LI } 1616a5f0fb15SPaul Saab cmd_exec(); 1617a5f0fb15SPaul Saab jump_back(number); 16182235c7feSXin LI jump_sline = save_jump_sline; 1619a5f0fb15SPaul Saab break; 1620a5f0fb15SPaul Saab 1621a5f0fb15SPaul Saab case A_PERCENT: 1622a5f0fb15SPaul Saab /* 1623a5f0fb15SPaul Saab * Go to a specified percentage into the file. 1624a5f0fb15SPaul Saab */ 1625a5f0fb15SPaul Saab if (number < 0) 1626720c436cSXin LI { 1627a5f0fb15SPaul Saab number = 0; 1628720c436cSXin LI fraction = 0; 1629720c436cSXin LI } 1630b7780dbeSXin LI if (number > 100 || (number == 100 && fraction != 0)) 1631720c436cSXin LI { 1632a5f0fb15SPaul Saab number = 100; 1633720c436cSXin LI fraction = 0; 1634720c436cSXin LI } 1635a5f0fb15SPaul Saab cmd_exec(); 1636720c436cSXin LI jump_percent((int) number, fraction); 1637a5f0fb15SPaul Saab break; 1638a5f0fb15SPaul Saab 1639a5f0fb15SPaul Saab case A_GOEND: 1640a5f0fb15SPaul Saab /* 1641a5f0fb15SPaul Saab * Go to line N, default end of file. 1642a5f0fb15SPaul Saab */ 1643a5f0fb15SPaul Saab cmd_exec(); 1644a5f0fb15SPaul Saab if (number <= 0) 1645a5f0fb15SPaul Saab jump_forw(); 1646a5f0fb15SPaul Saab else 1647a5f0fb15SPaul Saab jump_back(number); 1648a5f0fb15SPaul Saab break; 1649a5f0fb15SPaul Saab 1650a15691bfSXin LI case A_GOEND_BUF: 1651a15691bfSXin LI /* 1652a15691bfSXin LI * Go to line N, default last buffered byte. 1653a15691bfSXin LI */ 1654a15691bfSXin LI cmd_exec(); 1655a15691bfSXin LI if (number <= 0) 1656a15691bfSXin LI jump_forw_buffered(); 1657a15691bfSXin LI else 1658a15691bfSXin LI jump_back(number); 1659a15691bfSXin LI break; 1660a15691bfSXin LI 1661a5f0fb15SPaul Saab case A_GOPOS: 1662a5f0fb15SPaul Saab /* 1663a5f0fb15SPaul Saab * Go to a specified byte position in the file. 1664a5f0fb15SPaul Saab */ 1665a5f0fb15SPaul Saab cmd_exec(); 1666a5f0fb15SPaul Saab if (number < 0) 1667a5f0fb15SPaul Saab number = 0; 1668a5f0fb15SPaul Saab jump_line_loc((POSITION) number, jump_sline); 1669a5f0fb15SPaul Saab break; 1670a5f0fb15SPaul Saab 1671a5f0fb15SPaul Saab case A_STAT: 1672a5f0fb15SPaul Saab /* 1673a5f0fb15SPaul Saab * Print file name, etc. 1674a5f0fb15SPaul Saab */ 1675a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1676a5f0fb15SPaul Saab break; 1677a5f0fb15SPaul Saab cmd_exec(); 1678a5f0fb15SPaul Saab parg.p_string = eq_message(); 1679a5f0fb15SPaul Saab error("%s", &parg); 1680a5f0fb15SPaul Saab break; 1681a5f0fb15SPaul Saab 1682a5f0fb15SPaul Saab case A_VERSION: 1683a5f0fb15SPaul Saab /* 16842235c7feSXin LI * Print version number. 1685a5f0fb15SPaul Saab */ 1686a5f0fb15SPaul Saab cmd_exec(); 1687a5f0fb15SPaul Saab dispversion(); 1688a5f0fb15SPaul Saab break; 1689a5f0fb15SPaul Saab 1690a5f0fb15SPaul Saab case A_QUIT: 1691a5f0fb15SPaul Saab /* 1692a5f0fb15SPaul Saab * Exit. 1693a5f0fb15SPaul Saab */ 1694a5f0fb15SPaul Saab if (curr_ifile != NULL_IFILE && 1695a5f0fb15SPaul Saab ch_getflags() & CH_HELPFILE) 1696a5f0fb15SPaul Saab { 1697a5f0fb15SPaul Saab /* 1698a5f0fb15SPaul Saab * Quit while viewing the help file 1699a5f0fb15SPaul Saab * just means return to viewing the 1700a5f0fb15SPaul Saab * previous file. 1701a5f0fb15SPaul Saab */ 170289dd99dcSXin LI hshift = save_hshift; 1703a15691bfSXin LI bs_mode = save_bs_mode; 1704d713e089SXin LI proc_backspace = save_proc_backspace; 1705a5f0fb15SPaul Saab if (edit_prev(1) == 0) 1706a5f0fb15SPaul Saab break; 1707a5f0fb15SPaul Saab } 1708a5f0fb15SPaul Saab if (extra != NULL) 1709a5f0fb15SPaul Saab quit(*extra); 1710a5f0fb15SPaul Saab quit(QUIT_OK); 1711a5f0fb15SPaul Saab break; 1712a5f0fb15SPaul Saab 1713a5f0fb15SPaul Saab /* 1714a5f0fb15SPaul Saab * Define abbreviation for a commonly used sequence below. 1715a5f0fb15SPaul Saab */ 1716423c5ce5SXin LI #define DO_SEARCH() \ 1717423c5ce5SXin LI if (number <= 0) number = 1; \ 1718a5f0fb15SPaul Saab mca_search(); \ 1719a5f0fb15SPaul Saab cmd_exec(); \ 1720*c77c4889SXin LI multi_search(NULL, (int) number, 0); 1721a5f0fb15SPaul Saab 1722a5f0fb15SPaul Saab case A_F_SEARCH: 1723a5f0fb15SPaul Saab /* 1724a5f0fb15SPaul Saab * Search forward for a pattern. 1725a5f0fb15SPaul Saab * Get the first char of the pattern. 1726a5f0fb15SPaul Saab */ 172795270f73SXin LI search_type = SRCH_FORW | def_search_type; 1728a5f0fb15SPaul Saab if (number <= 0) 1729a5f0fb15SPaul Saab number = 1; 1730*c77c4889SXin LI literal_char = FALSE; 1731a5f0fb15SPaul Saab mca_search(); 1732a5f0fb15SPaul Saab c = getcc(); 1733a5f0fb15SPaul Saab goto again; 1734a5f0fb15SPaul Saab 1735a5f0fb15SPaul Saab case A_B_SEARCH: 1736a5f0fb15SPaul Saab /* 1737a5f0fb15SPaul Saab * Search backward for a pattern. 1738a5f0fb15SPaul Saab * Get the first char of the pattern. 1739a5f0fb15SPaul Saab */ 174095270f73SXin LI search_type = SRCH_BACK | def_search_type; 1741a5f0fb15SPaul Saab if (number <= 0) 1742a5f0fb15SPaul Saab number = 1; 1743*c77c4889SXin LI literal_char = FALSE; 1744a5f0fb15SPaul Saab mca_search(); 1745a5f0fb15SPaul Saab c = getcc(); 1746a5f0fb15SPaul Saab goto again; 1747a5f0fb15SPaul Saab 1748*c77c4889SXin LI case A_OSC8_F_SEARCH: 1749*c77c4889SXin LI #if OSC8_LINK 1750*c77c4889SXin LI cmd_exec(); 1751*c77c4889SXin LI if (number <= 0) 1752*c77c4889SXin LI number = 1; 1753*c77c4889SXin LI osc8_search(SRCH_FORW, NULL, number); 1754*c77c4889SXin LI #else 1755*c77c4889SXin LI error("Command not available", NULL_PARG); 1756*c77c4889SXin LI #endif 1757*c77c4889SXin LI break; 1758*c77c4889SXin LI 1759*c77c4889SXin LI case A_OSC8_B_SEARCH: 1760*c77c4889SXin LI #if OSC8_LINK 1761*c77c4889SXin LI cmd_exec(); 1762*c77c4889SXin LI if (number <= 0) 1763*c77c4889SXin LI number = 1; 1764*c77c4889SXin LI osc8_search(SRCH_BACK, NULL, number); 1765*c77c4889SXin LI #else 1766*c77c4889SXin LI error("Command not available", NULL_PARG); 1767*c77c4889SXin LI #endif 1768*c77c4889SXin LI break; 1769*c77c4889SXin LI 1770*c77c4889SXin LI case A_OSC8_OPEN: 1771*c77c4889SXin LI #if OSC8_LINK 1772*c77c4889SXin LI if (secure_allow(SF_OSC8_OPEN)) 1773*c77c4889SXin LI { 1774*c77c4889SXin LI cmd_exec(); 1775*c77c4889SXin LI osc8_open(); 1776*c77c4889SXin LI break; 1777*c77c4889SXin LI } 1778*c77c4889SXin LI #endif 1779*c77c4889SXin LI error("Command not available", NULL_PARG); 1780*c77c4889SXin LI break; 1781*c77c4889SXin LI 1782*c77c4889SXin LI case A_OSC8_JUMP: 1783*c77c4889SXin LI #if OSC8_LINK 1784*c77c4889SXin LI cmd_exec(); 1785*c77c4889SXin LI osc8_jump(); 1786*c77c4889SXin LI #else 1787*c77c4889SXin LI error("Command not available", NULL_PARG); 1788*c77c4889SXin LI #endif 1789*c77c4889SXin LI break; 1790*c77c4889SXin LI 17917374caaaSXin LI case A_FILTER: 17927374caaaSXin LI #if HILITE_SEARCH 17937374caaaSXin LI search_type = SRCH_FORW | SRCH_FILTER; 1794*c77c4889SXin LI literal_char = FALSE; 17957374caaaSXin LI mca_search(); 17967374caaaSXin LI c = getcc(); 17977374caaaSXin LI goto again; 17987374caaaSXin LI #else 17997374caaaSXin LI error("Command not available", NULL_PARG); 18007374caaaSXin LI break; 18017374caaaSXin LI #endif 18027374caaaSXin LI 1803a5f0fb15SPaul Saab case A_AGAIN_SEARCH: 1804a5f0fb15SPaul Saab /* 1805a5f0fb15SPaul Saab * Repeat previous search. 1806a5f0fb15SPaul Saab */ 1807d713e089SXin LI search_type = last_search_type; 1808a5f0fb15SPaul Saab DO_SEARCH(); 1809a5f0fb15SPaul Saab break; 1810a5f0fb15SPaul Saab 1811a5f0fb15SPaul Saab case A_T_AGAIN_SEARCH: 1812a5f0fb15SPaul Saab /* 1813a5f0fb15SPaul Saab * Repeat previous search, multiple files. 1814a5f0fb15SPaul Saab */ 1815d713e089SXin LI search_type = last_search_type | SRCH_PAST_EOF; 1816a5f0fb15SPaul Saab DO_SEARCH(); 1817a5f0fb15SPaul Saab break; 1818a5f0fb15SPaul Saab 1819a5f0fb15SPaul Saab case A_REVERSE_SEARCH: 1820a5f0fb15SPaul Saab /* 1821a5f0fb15SPaul Saab * Repeat previous search, in reverse direction. 1822a5f0fb15SPaul Saab */ 1823d713e089SXin LI save_search_type = search_type = last_search_type; 1824a5f0fb15SPaul Saab search_type = SRCH_REVERSE(search_type); 1825a5f0fb15SPaul Saab DO_SEARCH(); 1826d713e089SXin LI last_search_type = save_search_type; 1827a5f0fb15SPaul Saab break; 1828a5f0fb15SPaul Saab 1829a5f0fb15SPaul Saab case A_T_REVERSE_SEARCH: 1830a5f0fb15SPaul Saab /* 1831a5f0fb15SPaul Saab * Repeat previous search, 1832a5f0fb15SPaul Saab * multiple files in reverse direction. 1833a5f0fb15SPaul Saab */ 1834d713e089SXin LI save_search_type = search_type = last_search_type; 1835d713e089SXin LI search_type = SRCH_REVERSE(search_type) | SRCH_PAST_EOF; 1836a5f0fb15SPaul Saab DO_SEARCH(); 1837d713e089SXin LI last_search_type = save_search_type; 1838a5f0fb15SPaul Saab break; 1839a5f0fb15SPaul Saab 1840a5f0fb15SPaul Saab case A_UNDO_SEARCH: 18412235c7feSXin LI case A_CLR_SEARCH: 1842b2ea2440SXin LI /* 1843b2ea2440SXin LI * Clear search string highlighting. 1844b2ea2440SXin LI */ 18452235c7feSXin LI undo_search(action == A_CLR_SEARCH); 1846a5f0fb15SPaul Saab break; 1847a5f0fb15SPaul Saab 1848a5f0fb15SPaul Saab case A_HELP: 1849a5f0fb15SPaul Saab /* 1850a5f0fb15SPaul Saab * Help. 1851a5f0fb15SPaul Saab */ 1852a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1853a5f0fb15SPaul Saab break; 1854a5f0fb15SPaul Saab cmd_exec(); 185589dd99dcSXin LI save_hshift = hshift; 185689dd99dcSXin LI hshift = 0; 1857a15691bfSXin LI save_bs_mode = bs_mode; 1858a15691bfSXin LI bs_mode = BS_SPECIAL; 1859d713e089SXin LI save_proc_backspace = proc_backspace; 1860d713e089SXin LI proc_backspace = OPT_OFF; 1861a5f0fb15SPaul Saab (void) edit(FAKE_HELPFILE); 1862a5f0fb15SPaul Saab break; 1863a5f0fb15SPaul Saab 1864a5f0fb15SPaul Saab case A_EXAMINE: 1865a5f0fb15SPaul Saab /* 1866a5f0fb15SPaul Saab * Edit a new file. Get the filename. 1867a5f0fb15SPaul Saab */ 1868b2ea2440SXin LI #if EXAMINE 1869*c77c4889SXin LI if (secure_allow(SF_EXAMINE)) 1870a5f0fb15SPaul Saab { 1871dd3bd0edSDimitry Andric start_mca(A_EXAMINE, "Examine: ", ml_examine, 0); 1872a5f0fb15SPaul Saab c = getcc(); 1873a5f0fb15SPaul Saab goto again; 1874b2ea2440SXin LI } 1875b2ea2440SXin LI #endif 1876a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 1877a5f0fb15SPaul Saab break; 1878a5f0fb15SPaul Saab 1879a5f0fb15SPaul Saab case A_VISUAL: 1880a5f0fb15SPaul Saab /* 1881a5f0fb15SPaul Saab * Invoke an editor on the input file. 1882a5f0fb15SPaul Saab */ 1883a5f0fb15SPaul Saab #if EDITOR 1884*c77c4889SXin LI if (secure_allow(SF_EDIT)) 1885a5f0fb15SPaul Saab { 1886a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1887a5f0fb15SPaul Saab break; 1888a5f0fb15SPaul Saab if (strcmp(get_filename(curr_ifile), "-") == 0) 1889a5f0fb15SPaul Saab { 1890a5f0fb15SPaul Saab error("Cannot edit standard input", NULL_PARG); 1891a5f0fb15SPaul Saab break; 1892a5f0fb15SPaul Saab } 1893b2ea2440SXin LI if (get_altfilename(curr_ifile) != NULL) 1894a5f0fb15SPaul Saab { 189589dd99dcSXin LI error("WARNING: This file was viewed via LESSOPEN", 1896a5f0fb15SPaul Saab NULL_PARG); 1897a5f0fb15SPaul Saab } 1898dd3bd0edSDimitry Andric start_mca(A_SHELL, "!", ml_shell, 0); 1899a5f0fb15SPaul Saab /* 1900a5f0fb15SPaul Saab * Expand the editor prototype string 1901a5f0fb15SPaul Saab * and pass it to the system to execute. 1902a5f0fb15SPaul Saab * (Make sure the screen is displayed so the 1903a5f0fb15SPaul Saab * expansion of "+%lm" works.) 1904a5f0fb15SPaul Saab */ 1905a5f0fb15SPaul Saab make_display(); 1906a5f0fb15SPaul Saab cmd_exec(); 1907*c77c4889SXin LI lsystem(pr_expand(editproto), NULL); 1908a5f0fb15SPaul Saab break; 1909b2ea2440SXin LI } 1910b2ea2440SXin LI #endif 1911a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 1912a5f0fb15SPaul Saab break; 1913a5f0fb15SPaul Saab 1914a5f0fb15SPaul Saab case A_NEXT_FILE: 1915a5f0fb15SPaul Saab /* 1916a5f0fb15SPaul Saab * Examine next file. 1917a5f0fb15SPaul Saab */ 19181ede1615STim J. Robbins #if TAGS 19198fd4165cSPaul Saab if (ntags()) 19208fd4165cSPaul Saab { 19218fd4165cSPaul Saab error("No next file", NULL_PARG); 19228fd4165cSPaul Saab break; 19238fd4165cSPaul Saab } 19241ede1615STim J. Robbins #endif 1925a5f0fb15SPaul Saab if (number <= 0) 1926a5f0fb15SPaul Saab number = 1; 19271ede1615STim J. Robbins if (edit_next((int) number)) 1928a5f0fb15SPaul Saab { 19297374caaaSXin LI if (get_quit_at_eof() && eof_displayed() && 1930a5f0fb15SPaul Saab !(ch_getflags() & CH_HELPFILE)) 1931a5f0fb15SPaul Saab quit(QUIT_OK); 1932a5f0fb15SPaul Saab parg.p_string = (number > 1) ? "(N-th) " : ""; 1933a5f0fb15SPaul Saab error("No %snext file", &parg); 1934a5f0fb15SPaul Saab } 1935a5f0fb15SPaul Saab break; 1936a5f0fb15SPaul Saab 1937a5f0fb15SPaul Saab case A_PREV_FILE: 1938a5f0fb15SPaul Saab /* 1939a5f0fb15SPaul Saab * Examine previous file. 1940a5f0fb15SPaul Saab */ 19411ede1615STim J. Robbins #if TAGS 19428fd4165cSPaul Saab if (ntags()) 19438fd4165cSPaul Saab { 19448fd4165cSPaul Saab error("No previous file", NULL_PARG); 19458fd4165cSPaul Saab break; 19468fd4165cSPaul Saab } 19471ede1615STim J. Robbins #endif 1948a5f0fb15SPaul Saab if (number <= 0) 1949a5f0fb15SPaul Saab number = 1; 19501ede1615STim J. Robbins if (edit_prev((int) number)) 1951a5f0fb15SPaul Saab { 1952a5f0fb15SPaul Saab parg.p_string = (number > 1) ? "(N-th) " : ""; 1953a5f0fb15SPaul Saab error("No %sprevious file", &parg); 1954a5f0fb15SPaul Saab } 1955a5f0fb15SPaul Saab break; 1956a5f0fb15SPaul Saab 19578fd4165cSPaul Saab case A_NEXT_TAG: 1958b2ea2440SXin LI /* 1959b2ea2440SXin LI * Jump to the next tag in the current tag list. 1960b2ea2440SXin LI */ 19611ede1615STim J. Robbins #if TAGS 19628fd4165cSPaul Saab if (number <= 0) 19638fd4165cSPaul Saab number = 1; 19641ede1615STim J. Robbins tagfile = nexttag((int) number); 19658fd4165cSPaul Saab if (tagfile == NULL) 19668fd4165cSPaul Saab { 19678fd4165cSPaul Saab error("No next tag", NULL_PARG); 19688fd4165cSPaul Saab break; 19698fd4165cSPaul Saab } 1970b2ea2440SXin LI cmd_exec(); 19718fd4165cSPaul Saab if (edit(tagfile) == 0) 19728fd4165cSPaul Saab { 19738fd4165cSPaul Saab POSITION pos = tagsearch(); 19748fd4165cSPaul Saab if (pos != NULL_POSITION) 19758fd4165cSPaul Saab jump_loc(pos, jump_sline); 19768fd4165cSPaul Saab } 19771ede1615STim J. Robbins #else 19781ede1615STim J. Robbins error("Command not available", NULL_PARG); 19791ede1615STim J. Robbins #endif 19808fd4165cSPaul Saab break; 19818fd4165cSPaul Saab 19828fd4165cSPaul Saab case A_PREV_TAG: 1983b2ea2440SXin LI /* 1984b2ea2440SXin LI * Jump to the previous tag in the current tag list. 1985b2ea2440SXin LI */ 19861ede1615STim J. Robbins #if TAGS 19878fd4165cSPaul Saab if (number <= 0) 19888fd4165cSPaul Saab number = 1; 19891ede1615STim J. Robbins tagfile = prevtag((int) number); 19908fd4165cSPaul Saab if (tagfile == NULL) 19918fd4165cSPaul Saab { 19928fd4165cSPaul Saab error("No previous tag", NULL_PARG); 19938fd4165cSPaul Saab break; 19948fd4165cSPaul Saab } 1995b2ea2440SXin LI cmd_exec(); 19968fd4165cSPaul Saab if (edit(tagfile) == 0) 19978fd4165cSPaul Saab { 19988fd4165cSPaul Saab POSITION pos = tagsearch(); 19998fd4165cSPaul Saab if (pos != NULL_POSITION) 20008fd4165cSPaul Saab jump_loc(pos, jump_sline); 20018fd4165cSPaul Saab } 20021ede1615STim J. Robbins #else 20031ede1615STim J. Robbins error("Command not available", NULL_PARG); 20041ede1615STim J. Robbins #endif 20058fd4165cSPaul Saab break; 20068fd4165cSPaul Saab 2007a5f0fb15SPaul Saab case A_INDEX_FILE: 2008a5f0fb15SPaul Saab /* 2009a5f0fb15SPaul Saab * Examine a particular file. 2010a5f0fb15SPaul Saab */ 2011a5f0fb15SPaul Saab if (number <= 0) 2012a5f0fb15SPaul Saab number = 1; 20131ede1615STim J. Robbins if (edit_index((int) number)) 2014a5f0fb15SPaul Saab error("No such file", NULL_PARG); 2015a5f0fb15SPaul Saab break; 2016a5f0fb15SPaul Saab 2017a5f0fb15SPaul Saab case A_REMOVE_FILE: 2018b2ea2440SXin LI /* 2019b2ea2440SXin LI * Remove a file from the input file list. 2020b2ea2440SXin LI */ 2021a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 2022a5f0fb15SPaul Saab break; 2023a5f0fb15SPaul Saab old_ifile = curr_ifile; 2024a5f0fb15SPaul Saab new_ifile = getoff_ifile(curr_ifile); 2025a5f0fb15SPaul Saab if (new_ifile == NULL_IFILE) 2026a5f0fb15SPaul Saab { 2027a5f0fb15SPaul Saab bell(); 2028a5f0fb15SPaul Saab break; 2029a5f0fb15SPaul Saab } 2030a5f0fb15SPaul Saab if (edit_ifile(new_ifile) != 0) 2031a5f0fb15SPaul Saab { 2032a5f0fb15SPaul Saab reedit_ifile(old_ifile); 2033a5f0fb15SPaul Saab break; 2034a5f0fb15SPaul Saab } 2035a5f0fb15SPaul Saab del_ifile(old_ifile); 2036a5f0fb15SPaul Saab break; 2037a5f0fb15SPaul Saab 2038a5f0fb15SPaul Saab case A_OPT_TOGGLE: 2039b2ea2440SXin LI /* 2040b2ea2440SXin LI * Change the setting of an option. 2041b2ea2440SXin LI */ 2042a5f0fb15SPaul Saab optflag = OPT_TOGGLE; 2043a5f0fb15SPaul Saab optgetname = FALSE; 2044a5f0fb15SPaul Saab mca_opt_toggle(); 2045a5f0fb15SPaul Saab c = getcc(); 2046*c77c4889SXin LI msg = opt_toggle_disallowed(c); 2047*c77c4889SXin LI if (msg != NULL) 20486f26c71dSXin LI { 2049*c77c4889SXin LI error(msg, NULL_PARG); 20506f26c71dSXin LI break; 20516f26c71dSXin LI } 2052a5f0fb15SPaul Saab goto again; 2053a5f0fb15SPaul Saab 2054a5f0fb15SPaul Saab case A_DISP_OPTION: 2055a5f0fb15SPaul Saab /* 2056b2ea2440SXin LI * Report the setting of an option. 2057a5f0fb15SPaul Saab */ 2058a5f0fb15SPaul Saab optflag = OPT_NO_TOGGLE; 2059a5f0fb15SPaul Saab optgetname = FALSE; 2060a5f0fb15SPaul Saab mca_opt_toggle(); 2061a5f0fb15SPaul Saab c = getcc(); 2062a5f0fb15SPaul Saab goto again; 2063a5f0fb15SPaul Saab 2064a5f0fb15SPaul Saab case A_FIRSTCMD: 2065a5f0fb15SPaul Saab /* 2066a5f0fb15SPaul Saab * Set an initial command for new files. 2067a5f0fb15SPaul Saab */ 2068*c77c4889SXin LI start_mca(A_FIRSTCMD, "+", NULL, 0); 2069a5f0fb15SPaul Saab c = getcc(); 2070a5f0fb15SPaul Saab goto again; 2071a5f0fb15SPaul Saab 2072a5f0fb15SPaul Saab case A_SHELL: 2073d713e089SXin LI case A_PSHELL: 2074a5f0fb15SPaul Saab /* 2075a5f0fb15SPaul Saab * Shell escape. 2076a5f0fb15SPaul Saab */ 2077a5f0fb15SPaul Saab #if SHELL_ESCAPE 2078*c77c4889SXin LI if (secure_allow(SF_SHELL)) 2079a5f0fb15SPaul Saab { 2080d713e089SXin LI start_mca(action, (action == A_SHELL) ? "!" : "#", ml_shell, 0); 2081a5f0fb15SPaul Saab c = getcc(); 2082a5f0fb15SPaul Saab goto again; 2083b2ea2440SXin LI } 2084b2ea2440SXin LI #endif 2085a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 2086a5f0fb15SPaul Saab break; 2087a5f0fb15SPaul Saab 2088a5f0fb15SPaul Saab case A_SETMARK: 2089b2ea2440SXin LI case A_SETMARKBOT: 2090a5f0fb15SPaul Saab /* 2091a5f0fb15SPaul Saab * Set a mark. 2092a5f0fb15SPaul Saab */ 2093a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 2094a5f0fb15SPaul Saab break; 2095*c77c4889SXin LI start_mca(A_SETMARK, "set mark: ", NULL, 0); 2096a5f0fb15SPaul Saab c = getcc(); 2097b2ea2440SXin LI if (is_erase_char(c) || is_newline_char(c)) 2098a5f0fb15SPaul Saab break; 2099b2ea2440SXin LI setmark(c, action == A_SETMARKBOT ? BOTTOM : TOP); 2100b2ea2440SXin LI repaint(); 2101b2ea2440SXin LI break; 2102b2ea2440SXin LI 2103b2ea2440SXin LI case A_CLRMARK: 2104b2ea2440SXin LI /* 2105b2ea2440SXin LI * Clear a mark. 2106b2ea2440SXin LI */ 2107*c77c4889SXin LI start_mca(A_CLRMARK, "clear mark: ", NULL, 0); 2108b2ea2440SXin LI c = getcc(); 2109b2ea2440SXin LI if (is_erase_char(c) || is_newline_char(c)) 2110b2ea2440SXin LI break; 2111b2ea2440SXin LI clrmark(c); 2112b2ea2440SXin LI repaint(); 2113a5f0fb15SPaul Saab break; 2114a5f0fb15SPaul Saab 2115a5f0fb15SPaul Saab case A_GOMARK: 2116a5f0fb15SPaul Saab /* 2117b2ea2440SXin LI * Jump to a marked position. 2118a5f0fb15SPaul Saab */ 2119*c77c4889SXin LI start_mca(A_GOMARK, "goto mark: ", NULL, 0); 2120a5f0fb15SPaul Saab c = getcc(); 2121b2ea2440SXin LI if (is_erase_char(c) || is_newline_char(c)) 2122a5f0fb15SPaul Saab break; 21237374caaaSXin LI cmd_exec(); 2124a5f0fb15SPaul Saab gomark(c); 2125a5f0fb15SPaul Saab break; 2126a5f0fb15SPaul Saab 2127a5f0fb15SPaul Saab case A_PIPE: 2128b2ea2440SXin LI /* 2129b2ea2440SXin LI * Write part of the input to a pipe to a shell command. 2130b2ea2440SXin LI */ 2131a5f0fb15SPaul Saab #if PIPEC 2132*c77c4889SXin LI if (secure_allow(SF_PIPE)) 2133a5f0fb15SPaul Saab { 2134*c77c4889SXin LI start_mca(A_PIPE, "|mark: ", NULL, 0); 2135a5f0fb15SPaul Saab c = getcc(); 2136b2ea2440SXin LI if (is_erase_char(c)) 2137a5f0fb15SPaul Saab break; 2138b2ea2440SXin LI if (is_newline_char(c)) 2139a5f0fb15SPaul Saab c = '.'; 2140a5f0fb15SPaul Saab if (badmark(c)) 2141a5f0fb15SPaul Saab break; 2142a5f0fb15SPaul Saab pipec = c; 2143dd3bd0edSDimitry Andric start_mca(A_PIPE, "!", ml_shell, 0); 2144a5f0fb15SPaul Saab c = getcc(); 2145a5f0fb15SPaul Saab goto again; 2146b2ea2440SXin LI } 2147b2ea2440SXin LI #endif 2148a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 2149a5f0fb15SPaul Saab break; 2150a5f0fb15SPaul Saab 2151a5f0fb15SPaul Saab case A_B_BRACKET: 2152a5f0fb15SPaul Saab case A_F_BRACKET: 2153*c77c4889SXin LI start_mca(action, "Brackets: ", NULL, 0); 2154a5f0fb15SPaul Saab c = getcc(); 2155a5f0fb15SPaul Saab goto again; 2156a5f0fb15SPaul Saab 2157a5f0fb15SPaul Saab case A_LSHIFT: 2158b2ea2440SXin LI /* 2159b2ea2440SXin LI * Shift view left. 2160b2ea2440SXin LI */ 21618fd4165cSPaul Saab if (number > 0) 2162*c77c4889SXin LI shift_count = (int) number; 21638fd4165cSPaul Saab else 2164*c77c4889SXin LI number = (shift_count > 0) ? shift_count : sc_width / 2; 2165a5f0fb15SPaul Saab if (number > hshift) 2166a5f0fb15SPaul Saab number = hshift; 2167*c77c4889SXin LI pos_rehead(); 2168*c77c4889SXin LI hshift -= (int) number; 2169*c77c4889SXin LI screen_trashed(); 2170a5f0fb15SPaul Saab break; 2171a5f0fb15SPaul Saab 2172a5f0fb15SPaul Saab case A_RSHIFT: 2173b2ea2440SXin LI /* 2174b2ea2440SXin LI * Shift view right. 2175b2ea2440SXin LI */ 21768fd4165cSPaul Saab if (number > 0) 2177*c77c4889SXin LI shift_count = (int) number; 21788fd4165cSPaul Saab else 2179*c77c4889SXin LI number = (shift_count > 0) ? shift_count : sc_width / 2; 2180*c77c4889SXin LI pos_rehead(); 2181*c77c4889SXin LI hshift += (int) number; 2182*c77c4889SXin LI screen_trashed(); 2183a5f0fb15SPaul Saab break; 2184a5f0fb15SPaul Saab 2185f6b74a7dSXin LI case A_LLSHIFT: 2186b2ea2440SXin LI /* 2187b2ea2440SXin LI * Shift view left to margin. 2188b2ea2440SXin LI */ 2189*c77c4889SXin LI pos_rehead(); 2190f6b74a7dSXin LI hshift = 0; 2191*c77c4889SXin LI screen_trashed(); 2192f6b74a7dSXin LI break; 2193f6b74a7dSXin LI 2194f6b74a7dSXin LI case A_RRSHIFT: 2195b2ea2440SXin LI /* 2196b2ea2440SXin LI * Shift view right to view rightmost char on screen. 2197b2ea2440SXin LI */ 2198*c77c4889SXin LI pos_rehead(); 2199f6b74a7dSXin LI hshift = rrshift(); 2200*c77c4889SXin LI screen_trashed(); 2201f6b74a7dSXin LI break; 2202f6b74a7dSXin LI 2203a5f0fb15SPaul Saab case A_PREFIX: 2204a5f0fb15SPaul Saab /* 2205a5f0fb15SPaul Saab * The command is incomplete (more chars are needed). 2206a5f0fb15SPaul Saab * Display the current char, so the user knows 2207a5f0fb15SPaul Saab * what's going on, and get another character. 2208a5f0fb15SPaul Saab */ 2209a5f0fb15SPaul Saab if (mca != A_PREFIX) 2210a5f0fb15SPaul Saab { 2211a5f0fb15SPaul Saab cmd_reset(); 2212*c77c4889SXin LI start_mca(A_PREFIX, " ", NULL, CF_QUIT_ON_ERASE); 2213a5f0fb15SPaul Saab (void) cmd_char(c); 2214a5f0fb15SPaul Saab } 2215a5f0fb15SPaul Saab c = getcc(); 2216a5f0fb15SPaul Saab goto again; 2217a5f0fb15SPaul Saab 2218a5f0fb15SPaul Saab case A_NOACTION: 2219a5f0fb15SPaul Saab break; 2220a5f0fb15SPaul Saab 2221a5f0fb15SPaul Saab default: 2222a5f0fb15SPaul Saab bell(); 2223a5f0fb15SPaul Saab break; 2224a5f0fb15SPaul Saab } 2225a5f0fb15SPaul Saab } 2226a5f0fb15SPaul Saab } 2227