1a8f92a7cSPaul Saab /* $FreeBSD$ */ 2a5f0fb15SPaul Saab /* 3*2235c7feSXin LI * Copyright (C) 1984-2021 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; 27a5f0fb15SPaul Saab extern int squished; 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 secure; 38a5f0fb15SPaul Saab extern int hshift; 39a15691bfSXin LI extern int bs_mode; 40a5f0fb15SPaul Saab extern int show_attn; 41720c436cSXin LI extern int less_is_more; 42b2ea2440SXin LI extern int status_col; 4396e55cc7SXin LI extern POSITION highest_hilite; 44b2ea2440SXin LI extern POSITION start_attnpos; 45b2ea2440SXin LI extern POSITION end_attnpos; 46a5f0fb15SPaul Saab extern char *every_first_cmd; 47a5f0fb15SPaul Saab extern char version[]; 48a5f0fb15SPaul Saab extern struct scrpos initial_scrpos; 49a5f0fb15SPaul Saab extern IFILE curr_ifile; 50f6b74a7dSXin LI extern void *ml_search; 51f6b74a7dSXin LI extern void *ml_examine; 52b7780dbeSXin LI extern int wheel_lines; 53a5f0fb15SPaul Saab #if SHELL_ESCAPE || PIPEC 54f6b74a7dSXin LI extern void *ml_shell; 55a5f0fb15SPaul Saab #endif 56a5f0fb15SPaul Saab #if EDITOR 57a5f0fb15SPaul Saab extern char *editor; 58a5f0fb15SPaul Saab extern char *editproto; 59a5f0fb15SPaul Saab #endif 60a5f0fb15SPaul Saab extern int screen_trashed; /* The screen has been overwritten */ 6115596da4SPaul Saab extern int shift_count; 62720c436cSXin LI extern int oldbot; 63720c436cSXin LI extern int forw_prompt; 64*2235c7feSXin LI extern int incr_search; 65b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 66b7780dbeSXin LI extern int utf_mode; 67b7780dbeSXin LI #endif 68a5f0fb15SPaul Saab 69a5f0fb15SPaul Saab #if SHELL_ESCAPE 70a5f0fb15SPaul Saab static char *shellcmd = NULL; /* For holding last shell command for "!!" */ 71a5f0fb15SPaul Saab #endif 72a5f0fb15SPaul Saab static int mca; /* The multicharacter command (action) */ 73a5f0fb15SPaul Saab static int search_type; /* The previous type of search */ 741ede1615STim J. Robbins static LINENUM number; /* The number typed by the user */ 75720c436cSXin LI static long fraction; /* The fractional part of the number */ 7633096f16SXin LI static struct loption *curropt; 7733096f16SXin LI static int opt_lower; 78a5f0fb15SPaul Saab static int optflag; 79a5f0fb15SPaul Saab static int optgetname; 80a5f0fb15SPaul Saab static POSITION bottompos; 8189dd99dcSXin LI static int save_hshift; 82a15691bfSXin LI static int save_bs_mode; 83a5f0fb15SPaul Saab #if PIPEC 84a5f0fb15SPaul Saab static char pipec; 85a5f0fb15SPaul Saab #endif 86a5f0fb15SPaul Saab 87b2ea2440SXin LI /* Stack of ungotten chars (via ungetcc) */ 8833096f16SXin LI struct ungot { 8933096f16SXin LI struct ungot *ug_next; 90b2ea2440SXin LI LWCHAR ug_char; 9133096f16SXin LI }; 9233096f16SXin LI static struct ungot* ungot = NULL; 9333096f16SXin LI 946f26c71dSXin LI static void multi_search LESSPARAMS((char *pattern, int n, int silent)); 95a5f0fb15SPaul Saab 96a5f0fb15SPaul Saab /* 97720c436cSXin LI * Move the cursor to start of prompt line before executing a command. 98a5f0fb15SPaul Saab * This looks nicer if the command takes a long time before 99a5f0fb15SPaul Saab * updating the screen. 100a5f0fb15SPaul Saab */ 101a5f0fb15SPaul Saab static void 102b7780dbeSXin LI cmd_exec(VOID_PARAM) 103a5f0fb15SPaul Saab { 104a5f0fb15SPaul Saab clear_attn(); 105aa22b8b6SXin LI clear_bot(); 106a5f0fb15SPaul Saab flush(); 107a5f0fb15SPaul Saab } 108a5f0fb15SPaul Saab 109a5f0fb15SPaul Saab /* 110b7780dbeSXin LI * Indicate we are reading a multi-character command. 111b7780dbeSXin LI */ 112b7780dbeSXin LI static void 113b7780dbeSXin LI set_mca(action) 114b7780dbeSXin LI int action; 115b7780dbeSXin LI { 116b7780dbeSXin LI mca = action; 117b7780dbeSXin LI clear_bot(); 118b7780dbeSXin LI clear_cmd(); 119b7780dbeSXin LI } 120b7780dbeSXin LI 121b7780dbeSXin LI /* 122b7780dbeSXin LI * Indicate we are not reading a multi-character command. 123b7780dbeSXin LI */ 124b7780dbeSXin LI static void 125b7780dbeSXin LI clear_mca(VOID_PARAM) 126b7780dbeSXin LI { 127b7780dbeSXin LI if (mca == 0) 128b7780dbeSXin LI return; 129b7780dbeSXin LI mca = 0; 130b7780dbeSXin LI } 131b7780dbeSXin LI 132b7780dbeSXin LI /* 133a5f0fb15SPaul Saab * Set up the display to start a new multi-character command. 134a5f0fb15SPaul Saab */ 135a5f0fb15SPaul Saab static void 136f6b74a7dSXin LI start_mca(action, prompt, mlist, cmdflags) 137f6b74a7dSXin LI int action; 138f6b74a7dSXin LI constant char *prompt; 139f6b74a7dSXin LI void *mlist; 140f6b74a7dSXin LI int cmdflags; 141a5f0fb15SPaul Saab { 142b7780dbeSXin LI set_mca(action); 143a5f0fb15SPaul Saab cmd_putstr(prompt); 144a5f0fb15SPaul Saab set_mlist(mlist, cmdflags); 145a5f0fb15SPaul Saab } 146a5f0fb15SPaul Saab 147a5f0fb15SPaul Saab public int 148b7780dbeSXin LI in_mca(VOID_PARAM) 149a5f0fb15SPaul Saab { 150a5f0fb15SPaul Saab return (mca != 0 && mca != A_PREFIX); 151a5f0fb15SPaul Saab } 152a5f0fb15SPaul Saab 153a5f0fb15SPaul Saab /* 154a5f0fb15SPaul Saab * Set up the display to start a new search command. 155a5f0fb15SPaul Saab */ 156a5f0fb15SPaul Saab static void 157b7780dbeSXin LI mca_search(VOID_PARAM) 158a5f0fb15SPaul Saab { 1597374caaaSXin LI #if HILITE_SEARCH 1607374caaaSXin LI if (search_type & SRCH_FILTER) 161b7780dbeSXin LI set_mca(A_FILTER); 1627374caaaSXin LI else 1637374caaaSXin LI #endif 164a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 165b7780dbeSXin LI set_mca(A_F_SEARCH); 166a5f0fb15SPaul Saab else 167b7780dbeSXin LI set_mca(A_B_SEARCH); 168a5f0fb15SPaul Saab 169a5f0fb15SPaul Saab if (search_type & SRCH_NO_MATCH) 170a5f0fb15SPaul Saab cmd_putstr("Non-match "); 171a5f0fb15SPaul Saab if (search_type & SRCH_FIRST_FILE) 172a5f0fb15SPaul Saab cmd_putstr("First-file "); 173a5f0fb15SPaul Saab if (search_type & SRCH_PAST_EOF) 174a5f0fb15SPaul Saab cmd_putstr("EOF-ignore "); 175a5f0fb15SPaul Saab if (search_type & SRCH_NO_MOVE) 176a5f0fb15SPaul Saab cmd_putstr("Keep-pos "); 177a5f0fb15SPaul Saab if (search_type & SRCH_NO_REGEX) 178a5f0fb15SPaul Saab cmd_putstr("Regex-off "); 179*2235c7feSXin LI if (search_type & SRCH_WRAP) 180*2235c7feSXin LI cmd_putstr("Wrap "); 181a5f0fb15SPaul Saab 1827374caaaSXin LI #if HILITE_SEARCH 1837374caaaSXin LI if (search_type & SRCH_FILTER) 1847374caaaSXin LI cmd_putstr("&/"); 1857374caaaSXin LI else 1867374caaaSXin LI #endif 187a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 188a5f0fb15SPaul Saab cmd_putstr("/"); 189a5f0fb15SPaul Saab else 190a5f0fb15SPaul Saab cmd_putstr("?"); 191a15691bfSXin LI forw_prompt = 0; 192a5f0fb15SPaul Saab set_mlist(ml_search, 0); 193a5f0fb15SPaul Saab } 194a5f0fb15SPaul Saab 195a5f0fb15SPaul Saab /* 196a5f0fb15SPaul Saab * Set up the display to start a new toggle-option command. 197a5f0fb15SPaul Saab */ 198a5f0fb15SPaul Saab static void 199b7780dbeSXin LI mca_opt_toggle(VOID_PARAM) 200a5f0fb15SPaul Saab { 201a5f0fb15SPaul Saab int no_prompt; 202a5f0fb15SPaul Saab int flag; 203a5f0fb15SPaul Saab char *dash; 204a5f0fb15SPaul Saab 205a5f0fb15SPaul Saab no_prompt = (optflag & OPT_NO_PROMPT); 206a5f0fb15SPaul Saab flag = (optflag & ~OPT_NO_PROMPT); 207a5f0fb15SPaul Saab dash = (flag == OPT_NO_TOGGLE) ? "_" : "-"; 208a5f0fb15SPaul Saab 209b7780dbeSXin LI set_mca(A_OPT_TOGGLE); 210a5f0fb15SPaul Saab cmd_putstr(dash); 211a5f0fb15SPaul Saab if (optgetname) 212a5f0fb15SPaul Saab cmd_putstr(dash); 213a5f0fb15SPaul Saab if (no_prompt) 214a5f0fb15SPaul Saab cmd_putstr("(P)"); 215a5f0fb15SPaul Saab switch (flag) 216a5f0fb15SPaul Saab { 217a5f0fb15SPaul Saab case OPT_UNSET: 218a5f0fb15SPaul Saab cmd_putstr("+"); 219a5f0fb15SPaul Saab break; 220a5f0fb15SPaul Saab case OPT_SET: 221a5f0fb15SPaul Saab cmd_putstr("!"); 222a5f0fb15SPaul Saab break; 223a5f0fb15SPaul Saab } 224a15691bfSXin LI forw_prompt = 0; 225a5f0fb15SPaul Saab set_mlist(NULL, 0); 226a5f0fb15SPaul Saab } 227a5f0fb15SPaul Saab 228a5f0fb15SPaul Saab /* 229a5f0fb15SPaul Saab * Execute a multicharacter command. 230a5f0fb15SPaul Saab */ 231a5f0fb15SPaul Saab static void 232b7780dbeSXin LI exec_mca(VOID_PARAM) 233a5f0fb15SPaul Saab { 2341ea31627SRobert Watson char *cbuf; 235a5f0fb15SPaul Saab 236a5f0fb15SPaul Saab cmd_exec(); 237a5f0fb15SPaul Saab cbuf = get_cmdbuf(); 238a5f0fb15SPaul Saab 239a5f0fb15SPaul Saab switch (mca) 240a5f0fb15SPaul Saab { 241a5f0fb15SPaul Saab case A_F_SEARCH: 242a5f0fb15SPaul Saab case A_B_SEARCH: 243a15691bfSXin LI multi_search(cbuf, (int) number, 0); 244a5f0fb15SPaul Saab break; 2457374caaaSXin LI #if HILITE_SEARCH 2467374caaaSXin LI case A_FILTER: 2477374caaaSXin LI search_type ^= SRCH_NO_MATCH; 2487374caaaSXin LI set_filter_pattern(cbuf, search_type); 2497374caaaSXin LI break; 2507374caaaSXin LI #endif 251a5f0fb15SPaul Saab case A_FIRSTCMD: 252a5f0fb15SPaul Saab /* 253a5f0fb15SPaul Saab * Skip leading spaces or + signs in the string. 254a5f0fb15SPaul Saab */ 255a5f0fb15SPaul Saab while (*cbuf == '+' || *cbuf == ' ') 256a5f0fb15SPaul Saab cbuf++; 257a5f0fb15SPaul Saab if (every_first_cmd != NULL) 258a5f0fb15SPaul Saab free(every_first_cmd); 259a5f0fb15SPaul Saab if (*cbuf == '\0') 260a5f0fb15SPaul Saab every_first_cmd = NULL; 261a5f0fb15SPaul Saab else 262a5f0fb15SPaul Saab every_first_cmd = save(cbuf); 263a5f0fb15SPaul Saab break; 264a5f0fb15SPaul Saab case A_OPT_TOGGLE: 26533096f16SXin LI toggle_option(curropt, opt_lower, cbuf, optflag); 26633096f16SXin LI curropt = NULL; 267a5f0fb15SPaul Saab break; 268a5f0fb15SPaul Saab case A_F_BRACKET: 2691ede1615STim J. Robbins match_brac(cbuf[0], cbuf[1], 1, (int) number); 270a5f0fb15SPaul Saab break; 271a5f0fb15SPaul Saab case A_B_BRACKET: 2721ede1615STim J. Robbins match_brac(cbuf[1], cbuf[0], 0, (int) number); 273a5f0fb15SPaul Saab break; 274a5f0fb15SPaul Saab #if EXAMINE 275a5f0fb15SPaul Saab case A_EXAMINE: 276a5f0fb15SPaul Saab if (secure) 277a5f0fb15SPaul Saab break; 278a5f0fb15SPaul Saab edit_list(cbuf); 2791ede1615STim J. Robbins #if TAGS 2808fd4165cSPaul Saab /* If tag structure is loaded then clean it up. */ 2818fd4165cSPaul Saab cleantags(); 2821ede1615STim J. Robbins #endif 283a5f0fb15SPaul Saab break; 284a5f0fb15SPaul Saab #endif 285a5f0fb15SPaul Saab #if SHELL_ESCAPE 286a5f0fb15SPaul Saab case A_SHELL: 287a5f0fb15SPaul Saab /* 288a5f0fb15SPaul Saab * !! just uses whatever is in shellcmd. 289a5f0fb15SPaul Saab * Otherwise, copy cmdbuf to shellcmd, 290a5f0fb15SPaul Saab * expanding any special characters ("%" or "#"). 291a5f0fb15SPaul Saab */ 292a5f0fb15SPaul Saab if (*cbuf != '!') 293a5f0fb15SPaul Saab { 294a5f0fb15SPaul Saab if (shellcmd != NULL) 295a5f0fb15SPaul Saab free(shellcmd); 296a5f0fb15SPaul Saab shellcmd = fexpand(cbuf); 297a5f0fb15SPaul Saab } 298a5f0fb15SPaul Saab 299a5f0fb15SPaul Saab if (secure) 300a5f0fb15SPaul Saab break; 301a5f0fb15SPaul Saab if (shellcmd == NULL) 302a5f0fb15SPaul Saab lsystem("", "!done"); 303a5f0fb15SPaul Saab else 304a5f0fb15SPaul Saab lsystem(shellcmd, "!done"); 305a5f0fb15SPaul Saab break; 306a5f0fb15SPaul Saab #endif 307a5f0fb15SPaul Saab #if PIPEC 308a5f0fb15SPaul Saab case A_PIPE: 309a5f0fb15SPaul Saab if (secure) 310a5f0fb15SPaul Saab break; 311a5f0fb15SPaul Saab (void) pipe_mark(pipec, cbuf); 312a5f0fb15SPaul Saab error("|done", NULL_PARG); 313a5f0fb15SPaul Saab break; 314a5f0fb15SPaul Saab #endif 315a5f0fb15SPaul Saab } 316a5f0fb15SPaul Saab } 317a5f0fb15SPaul Saab 318a5f0fb15SPaul Saab /* 31933096f16SXin LI * Is a character an erase or kill char? 320a5f0fb15SPaul Saab */ 321a5f0fb15SPaul Saab static int 322f6b74a7dSXin LI is_erase_char(c) 323f6b74a7dSXin LI int c; 324a5f0fb15SPaul Saab { 32533096f16SXin LI return (c == erase_char || c == erase2_char || c == kill_char); 326a5f0fb15SPaul Saab } 327a5f0fb15SPaul Saab 328a5f0fb15SPaul Saab /* 329b2ea2440SXin LI * Is a character a carriage return or newline? 330b2ea2440SXin LI */ 331b2ea2440SXin LI static int 332b2ea2440SXin LI is_newline_char(c) 333b2ea2440SXin LI int c; 334b2ea2440SXin LI { 335b2ea2440SXin LI return (c == '\n' || c == '\r'); 336b2ea2440SXin LI } 337b2ea2440SXin LI 338b2ea2440SXin LI /* 33933096f16SXin LI * Handle the first char of an option (after the initial dash). 340a5f0fb15SPaul Saab */ 34133096f16SXin LI static int 342f6b74a7dSXin LI mca_opt_first_char(c) 343f6b74a7dSXin LI int c; 344a5f0fb15SPaul Saab { 34533096f16SXin LI int flag = (optflag & ~OPT_NO_PROMPT); 346a5f0fb15SPaul Saab if (flag == OPT_NO_TOGGLE) 347a5f0fb15SPaul Saab { 348a5f0fb15SPaul Saab switch (c) 349a5f0fb15SPaul Saab { 350a5f0fb15SPaul Saab case '_': 351a5f0fb15SPaul Saab /* "__" = long option name. */ 352a5f0fb15SPaul Saab optgetname = TRUE; 353a5f0fb15SPaul Saab mca_opt_toggle(); 354a5f0fb15SPaul Saab return (MCA_MORE); 355a5f0fb15SPaul Saab } 356a5f0fb15SPaul Saab } else 357a5f0fb15SPaul Saab { 358a5f0fb15SPaul Saab switch (c) 359a5f0fb15SPaul Saab { 360a5f0fb15SPaul Saab case '+': 361a5f0fb15SPaul Saab /* "-+" = UNSET. */ 362a5f0fb15SPaul Saab optflag = (flag == OPT_UNSET) ? 363a5f0fb15SPaul Saab OPT_TOGGLE : OPT_UNSET; 364a5f0fb15SPaul Saab mca_opt_toggle(); 365a5f0fb15SPaul Saab return (MCA_MORE); 366a5f0fb15SPaul Saab case '!': 367a5f0fb15SPaul Saab /* "-!" = SET */ 368a5f0fb15SPaul Saab optflag = (flag == OPT_SET) ? 369a5f0fb15SPaul Saab OPT_TOGGLE : OPT_SET; 370a5f0fb15SPaul Saab mca_opt_toggle(); 371a5f0fb15SPaul Saab return (MCA_MORE); 372a5f0fb15SPaul Saab case CONTROL('P'): 373a5f0fb15SPaul Saab optflag ^= OPT_NO_PROMPT; 374a5f0fb15SPaul Saab mca_opt_toggle(); 375a5f0fb15SPaul Saab return (MCA_MORE); 376a5f0fb15SPaul Saab case '-': 377a5f0fb15SPaul Saab /* "--" = long option name. */ 378a5f0fb15SPaul Saab optgetname = TRUE; 379a5f0fb15SPaul Saab mca_opt_toggle(); 380a5f0fb15SPaul Saab return (MCA_MORE); 381a5f0fb15SPaul Saab } 382a5f0fb15SPaul Saab } 38333096f16SXin LI /* Char was not handled here. */ 38433096f16SXin LI return (NO_MCA); 385a5f0fb15SPaul Saab } 38633096f16SXin LI 387a5f0fb15SPaul Saab /* 38833096f16SXin LI * Add a char to a long option name. 38933096f16SXin LI * See if we've got a match for an option name yet. 390a5f0fb15SPaul Saab * If so, display the complete name and stop 391a5f0fb15SPaul Saab * accepting chars until user hits RETURN. 392a5f0fb15SPaul Saab */ 39333096f16SXin LI static int 394f6b74a7dSXin LI mca_opt_nonfirst_char(c) 395f6b74a7dSXin LI int c; 39633096f16SXin LI { 39733096f16SXin LI char *p; 398a5f0fb15SPaul Saab char *oname; 399b7780dbeSXin LI int err; 400a5f0fb15SPaul Saab 40133096f16SXin LI if (curropt != NULL) 402a5f0fb15SPaul Saab { 403a5f0fb15SPaul Saab /* 404a5f0fb15SPaul Saab * Already have a match for the name. 405a5f0fb15SPaul Saab * Don't accept anything but erase/kill. 406a5f0fb15SPaul Saab */ 40733096f16SXin LI if (is_erase_char(c)) 408a5f0fb15SPaul Saab return (MCA_DONE); 409a5f0fb15SPaul Saab return (MCA_MORE); 410a5f0fb15SPaul Saab } 411a5f0fb15SPaul Saab /* 412a5f0fb15SPaul Saab * Add char to cmd buffer and try to match 413a5f0fb15SPaul Saab * the option name. 414a5f0fb15SPaul Saab */ 415a5f0fb15SPaul Saab if (cmd_char(c) == CC_QUIT) 416a5f0fb15SPaul Saab return (MCA_DONE); 417a5f0fb15SPaul Saab p = get_cmdbuf(); 41833096f16SXin LI opt_lower = ASCII_IS_LOWER(p[0]); 419b7780dbeSXin LI err = 0; 420b7780dbeSXin LI curropt = findopt_name(&p, &oname, &err); 42133096f16SXin LI if (curropt != NULL) 422a5f0fb15SPaul Saab { 423a5f0fb15SPaul Saab /* 424a5f0fb15SPaul Saab * Got a match. 42533096f16SXin LI * Remember the option and 426a5f0fb15SPaul Saab * display the full option name. 427a5f0fb15SPaul Saab */ 428a5f0fb15SPaul Saab cmd_reset(); 429a5f0fb15SPaul Saab mca_opt_toggle(); 430a5f0fb15SPaul Saab for (p = oname; *p != '\0'; p++) 431a5f0fb15SPaul Saab { 432a5f0fb15SPaul Saab c = *p; 43333096f16SXin LI if (!opt_lower && ASCII_IS_LOWER(c)) 43489dd99dcSXin LI c = ASCII_TO_UPPER(c); 435a5f0fb15SPaul Saab if (cmd_char(c) != CC_OK) 436a5f0fb15SPaul Saab return (MCA_DONE); 437a5f0fb15SPaul Saab } 438b7780dbeSXin LI } else if (err != OPT_AMBIG) 439b7780dbeSXin LI { 440b7780dbeSXin LI bell(); 441a5f0fb15SPaul Saab } 442a5f0fb15SPaul Saab return (MCA_MORE); 443a5f0fb15SPaul Saab } 44433096f16SXin LI 44533096f16SXin LI /* 44633096f16SXin LI * Handle a char of an option toggle command. 44733096f16SXin LI */ 44833096f16SXin LI static int 449f6b74a7dSXin LI mca_opt_char(c) 450f6b74a7dSXin LI int c; 45133096f16SXin LI { 45233096f16SXin LI PARG parg; 45333096f16SXin LI 45433096f16SXin LI /* 45533096f16SXin LI * This may be a short option (single char), 45633096f16SXin LI * or one char of a long option name, 45733096f16SXin LI * or one char of the option parameter. 45833096f16SXin LI */ 45933096f16SXin LI if (curropt == NULL && len_cmdbuf() == 0) 46033096f16SXin LI { 46133096f16SXin LI int ret = mca_opt_first_char(c); 46233096f16SXin LI if (ret != NO_MCA) 46333096f16SXin LI return (ret); 46433096f16SXin LI } 46533096f16SXin LI if (optgetname) 46633096f16SXin LI { 46733096f16SXin LI /* We're getting a long option name. */ 468b2ea2440SXin LI if (!is_newline_char(c)) 46933096f16SXin LI return (mca_opt_nonfirst_char(c)); 47033096f16SXin LI if (curropt == NULL) 47133096f16SXin LI { 47233096f16SXin LI parg.p_string = get_cmdbuf(); 47333096f16SXin LI error("There is no --%s option", &parg); 47433096f16SXin LI return (MCA_DONE); 47533096f16SXin LI } 47633096f16SXin LI optgetname = FALSE; 47733096f16SXin LI cmd_reset(); 478a5f0fb15SPaul Saab } else 479a5f0fb15SPaul Saab { 48033096f16SXin LI if (is_erase_char(c)) 48133096f16SXin LI return (NO_MCA); 48233096f16SXin LI if (curropt != NULL) 48333096f16SXin LI /* We're getting the option parameter. */ 48433096f16SXin LI return (NO_MCA); 48533096f16SXin LI curropt = findopt(c); 48633096f16SXin LI if (curropt == NULL) 487a5f0fb15SPaul Saab { 48833096f16SXin LI parg.p_string = propt(c); 48933096f16SXin LI error("There is no %s option", &parg); 49033096f16SXin LI return (MCA_DONE); 49133096f16SXin LI } 492b7780dbeSXin LI opt_lower = ASCII_IS_LOWER(c); 49333096f16SXin LI } 49433096f16SXin LI /* 49533096f16SXin LI * If the option which was entered does not take a 49633096f16SXin LI * parameter, toggle the option immediately, 49733096f16SXin LI * so user doesn't have to hit RETURN. 49833096f16SXin LI */ 49933096f16SXin LI if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE || 50033096f16SXin LI !opt_has_param(curropt)) 50133096f16SXin LI { 502b7780dbeSXin LI toggle_option(curropt, opt_lower, "", optflag); 503a5f0fb15SPaul Saab return (MCA_DONE); 504a5f0fb15SPaul Saab } 505a5f0fb15SPaul Saab /* 50633096f16SXin LI * Display a prompt appropriate for the option parameter. 507a5f0fb15SPaul Saab */ 50833096f16SXin LI start_mca(A_OPT_TOGGLE, opt_prompt(curropt), (void*)NULL, 0); 509a5f0fb15SPaul Saab return (MCA_MORE); 51033096f16SXin LI } 511a5f0fb15SPaul Saab 512a5f0fb15SPaul Saab /* 51333096f16SXin LI * Handle a char of a search command. 51433096f16SXin LI */ 51533096f16SXin LI static int 516f6b74a7dSXin LI mca_search_char(c) 517f6b74a7dSXin LI int c; 51833096f16SXin LI { 51933096f16SXin LI int flag = 0; 52033096f16SXin LI 52133096f16SXin LI /* 522a5f0fb15SPaul Saab * Certain characters as the first char of 523a5f0fb15SPaul Saab * the pattern have special meaning: 524a5f0fb15SPaul Saab * ! Toggle the NO_MATCH flag 525a5f0fb15SPaul Saab * * Toggle the PAST_EOF flag 526a5f0fb15SPaul Saab * @ Toggle the FIRST_FILE flag 527a5f0fb15SPaul Saab */ 528a5f0fb15SPaul Saab if (len_cmdbuf() > 0) 52933096f16SXin LI return (NO_MCA); 530a5f0fb15SPaul Saab 531a5f0fb15SPaul Saab switch (c) 532a5f0fb15SPaul Saab { 533a5f0fb15SPaul Saab case '*': 534720c436cSXin LI if (less_is_more) 535a8f92a7cSPaul Saab break; 536a8f92a7cSPaul Saab case CONTROL('E'): /* ignore END of file */ 5377374caaaSXin LI if (mca != A_FILTER) 538a5f0fb15SPaul Saab flag = SRCH_PAST_EOF; 539a5f0fb15SPaul Saab break; 540a5f0fb15SPaul Saab case '@': 541720c436cSXin LI if (less_is_more) 542a8f92a7cSPaul Saab break; 543a8f92a7cSPaul Saab case CONTROL('F'): /* FIRST file */ 5447374caaaSXin LI if (mca != A_FILTER) 545a5f0fb15SPaul Saab flag = SRCH_FIRST_FILE; 546a5f0fb15SPaul Saab break; 547a5f0fb15SPaul Saab case CONTROL('K'): /* KEEP position */ 5487374caaaSXin LI if (mca != A_FILTER) 549a5f0fb15SPaul Saab flag = SRCH_NO_MOVE; 550a5f0fb15SPaul Saab break; 551*2235c7feSXin LI case CONTROL('W'): /* WRAP around */ 552*2235c7feSXin LI if (mca != A_FILTER) 553*2235c7feSXin LI flag = SRCH_WRAP; 554*2235c7feSXin LI break; 555a5f0fb15SPaul Saab case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */ 556a5f0fb15SPaul Saab flag = SRCH_NO_REGEX; 557a5f0fb15SPaul Saab break; 558a5f0fb15SPaul Saab case CONTROL('N'): /* NOT match */ 559a5f0fb15SPaul Saab case '!': 560a5f0fb15SPaul Saab flag = SRCH_NO_MATCH; 561a5f0fb15SPaul Saab break; 562a5f0fb15SPaul Saab } 56333096f16SXin LI 564a5f0fb15SPaul Saab if (flag != 0) 565a5f0fb15SPaul Saab { 566*2235c7feSXin LI /* Toggle flag, but keep PAST_EOF and WRAP mutually exclusive. */ 567*2235c7feSXin LI search_type ^= flag | (search_type & (SRCH_PAST_EOF|SRCH_WRAP)); 568a5f0fb15SPaul Saab mca_search(); 569a5f0fb15SPaul Saab return (MCA_MORE); 570a5f0fb15SPaul Saab } 57133096f16SXin LI return (NO_MCA); 57233096f16SXin LI } 57333096f16SXin LI 57433096f16SXin LI /* 57533096f16SXin LI * Handle a character of a multi-character command. 57633096f16SXin LI */ 57733096f16SXin LI static int 578f6b74a7dSXin LI mca_char(c) 579f6b74a7dSXin LI int c; 58033096f16SXin LI { 58133096f16SXin LI int ret; 58233096f16SXin LI 58333096f16SXin LI switch (mca) 58433096f16SXin LI { 58533096f16SXin LI case 0: 58633096f16SXin LI /* 58733096f16SXin LI * We're not in a multicharacter command. 58833096f16SXin LI */ 58933096f16SXin LI return (NO_MCA); 59033096f16SXin LI 59133096f16SXin LI case A_PREFIX: 59233096f16SXin LI /* 59333096f16SXin LI * In the prefix of a command. 59433096f16SXin LI * This not considered a multichar command 59533096f16SXin LI * (even tho it uses cmdbuf, etc.). 59633096f16SXin LI * It is handled in the commands() switch. 59733096f16SXin LI */ 59833096f16SXin LI return (NO_MCA); 59933096f16SXin LI 60033096f16SXin LI case A_DIGIT: 60133096f16SXin LI /* 60233096f16SXin LI * Entering digits of a number. 60333096f16SXin LI * Terminated by a non-digit. 60433096f16SXin LI */ 605*2235c7feSXin LI if ((c >= '0' && c <= '9') || c == '.') 606*2235c7feSXin LI break; 607*2235c7feSXin LI switch (editchar(c, ECF_PEEK|ECF_NOHISTORY|ECF_NOCOMPLETE|ECF_NORIGHTLEFT)) 60833096f16SXin LI { 609*2235c7feSXin LI case A_NOACTION: 610*2235c7feSXin LI /* 611*2235c7feSXin LI * Ignore this char and get another one. 612*2235c7feSXin LI */ 613*2235c7feSXin LI return (MCA_MORE); 614*2235c7feSXin LI case A_INVALID: 61533096f16SXin LI /* 61633096f16SXin LI * Not part of the number. 61733096f16SXin LI * End the number and treat this char 61833096f16SXin LI * as a normal command character. 61933096f16SXin LI */ 62033096f16SXin LI number = cmd_int(&fraction); 621b7780dbeSXin LI clear_mca(); 62233096f16SXin LI cmd_accept(); 62333096f16SXin LI return (NO_MCA); 62433096f16SXin LI } 62533096f16SXin LI break; 62633096f16SXin LI 62733096f16SXin LI case A_OPT_TOGGLE: 62833096f16SXin LI ret = mca_opt_char(c); 62933096f16SXin LI if (ret != NO_MCA) 63033096f16SXin LI return (ret); 63133096f16SXin LI break; 63233096f16SXin LI 63333096f16SXin LI case A_F_SEARCH: 63433096f16SXin LI case A_B_SEARCH: 63533096f16SXin LI case A_FILTER: 63633096f16SXin LI ret = mca_search_char(c); 63733096f16SXin LI if (ret != NO_MCA) 63833096f16SXin LI return (ret); 63933096f16SXin LI break; 64033096f16SXin LI 64133096f16SXin LI default: 64233096f16SXin LI /* Other multicharacter command. */ 643a5f0fb15SPaul Saab break; 644a5f0fb15SPaul Saab } 645a5f0fb15SPaul Saab 646a5f0fb15SPaul Saab /* 64733096f16SXin LI * The multichar command is terminated by a newline. 648a5f0fb15SPaul Saab */ 649b2ea2440SXin LI if (is_newline_char(c)) 650a5f0fb15SPaul Saab { 651a5f0fb15SPaul Saab /* 652a5f0fb15SPaul Saab * Execute the command. 653a5f0fb15SPaul Saab */ 654a5f0fb15SPaul Saab exec_mca(); 655a5f0fb15SPaul Saab return (MCA_DONE); 656a5f0fb15SPaul Saab } 657a5f0fb15SPaul Saab 658a5f0fb15SPaul Saab /* 659a5f0fb15SPaul Saab * Append the char to the command buffer. 660a5f0fb15SPaul Saab */ 661a5f0fb15SPaul Saab if (cmd_char(c) == CC_QUIT) 662a5f0fb15SPaul Saab /* 663a5f0fb15SPaul Saab * Abort the multi-char command. 664a5f0fb15SPaul Saab */ 665a5f0fb15SPaul Saab return (MCA_DONE); 666a5f0fb15SPaul Saab 667*2235c7feSXin LI switch (mca) 668*2235c7feSXin LI { 669*2235c7feSXin LI case A_F_BRACKET: 670*2235c7feSXin LI case A_B_BRACKET: 671*2235c7feSXin LI if (len_cmdbuf() >= 2) 672a5f0fb15SPaul Saab { 673a5f0fb15SPaul Saab /* 674a5f0fb15SPaul Saab * Special case for the bracket-matching commands. 675a5f0fb15SPaul Saab * Execute the command after getting exactly two 676a5f0fb15SPaul Saab * characters from the user. 677a5f0fb15SPaul Saab */ 678a5f0fb15SPaul Saab exec_mca(); 679a5f0fb15SPaul Saab return (MCA_DONE); 680a5f0fb15SPaul Saab } 681*2235c7feSXin LI break; 682*2235c7feSXin LI case A_F_SEARCH: 683*2235c7feSXin LI case A_B_SEARCH: 684*2235c7feSXin LI if (incr_search) 685*2235c7feSXin LI { 686*2235c7feSXin LI /* Incremental search: do a search after every input char. */ 687*2235c7feSXin LI int st = (search_type & (SRCH_FORW|SRCH_BACK|SRCH_NO_MATCH|SRCH_NO_REGEX|SRCH_NO_MOVE|SRCH_WRAP)); 688*2235c7feSXin LI char *pattern = get_cmdbuf(); 689*2235c7feSXin LI cmd_exec(); 690*2235c7feSXin LI if (*pattern == '\0') 691*2235c7feSXin LI { 692*2235c7feSXin LI /* User has backspaced to an empty pattern. */ 693*2235c7feSXin LI undo_search(1); 694*2235c7feSXin LI } else 695*2235c7feSXin LI { 696*2235c7feSXin LI if (search(st | SRCH_INCR, pattern, 1) != 0) 697*2235c7feSXin LI /* No match, invalid pattern, etc. */ 698*2235c7feSXin LI undo_search(1); 699*2235c7feSXin LI } 700*2235c7feSXin LI /* Redraw the search prompt and search string. */ 701*2235c7feSXin LI mca_search(); 702*2235c7feSXin LI cmd_repaint(NULL); 703*2235c7feSXin LI } 704*2235c7feSXin LI break; 705*2235c7feSXin LI } 706a5f0fb15SPaul Saab 707a5f0fb15SPaul Saab /* 708a5f0fb15SPaul Saab * Need another character. 709a5f0fb15SPaul Saab */ 710a5f0fb15SPaul Saab return (MCA_MORE); 711a5f0fb15SPaul Saab } 712a5f0fb15SPaul Saab 713a5f0fb15SPaul Saab /* 714423c5ce5SXin LI * Discard any buffered file data. 715423c5ce5SXin LI */ 716423c5ce5SXin LI static void 717b7780dbeSXin LI clear_buffers(VOID_PARAM) 718423c5ce5SXin LI { 719423c5ce5SXin LI if (!(ch_getflags() & CH_CANSEEK)) 720423c5ce5SXin LI return; 721423c5ce5SXin LI ch_flush(); 722423c5ce5SXin LI clr_linenum(); 723423c5ce5SXin LI #if HILITE_SEARCH 724423c5ce5SXin LI clr_hilite(); 725423c5ce5SXin LI #endif 726423c5ce5SXin LI } 727423c5ce5SXin LI 728423c5ce5SXin LI /* 729a5f0fb15SPaul Saab * Make sure the screen is displayed. 730a5f0fb15SPaul Saab */ 731a5f0fb15SPaul Saab static void 732b7780dbeSXin LI make_display(VOID_PARAM) 733a5f0fb15SPaul Saab { 734a5f0fb15SPaul Saab /* 735a5f0fb15SPaul Saab * If nothing is displayed yet, display starting from initial_scrpos. 736a5f0fb15SPaul Saab */ 737a5f0fb15SPaul Saab if (empty_screen()) 738a5f0fb15SPaul Saab { 739a5f0fb15SPaul Saab if (initial_scrpos.pos == NULL_POSITION) 740a5f0fb15SPaul Saab jump_loc(ch_zero(), 1); 741a5f0fb15SPaul Saab else 742a5f0fb15SPaul Saab jump_loc(initial_scrpos.pos, initial_scrpos.ln); 743a5f0fb15SPaul Saab } else if (screen_trashed) 744a5f0fb15SPaul Saab { 745423c5ce5SXin LI int save_top_scroll = top_scroll; 746423c5ce5SXin LI int save_ignore_eoi = ignore_eoi; 747a5f0fb15SPaul Saab top_scroll = 1; 748423c5ce5SXin LI ignore_eoi = 0; 749423c5ce5SXin LI if (screen_trashed == 2) 750423c5ce5SXin LI { 751423c5ce5SXin LI /* Special case used by ignore_eoi: re-open the input file 752423c5ce5SXin LI * and jump to the end of the file. */ 753423c5ce5SXin LI reopen_curr_ifile(); 754423c5ce5SXin LI jump_forw(); 755423c5ce5SXin LI } 756a5f0fb15SPaul Saab repaint(); 757a5f0fb15SPaul Saab top_scroll = save_top_scroll; 758423c5ce5SXin LI ignore_eoi = save_ignore_eoi; 759a5f0fb15SPaul Saab } 760a5f0fb15SPaul Saab } 761a5f0fb15SPaul Saab 762a5f0fb15SPaul Saab /* 763a5f0fb15SPaul Saab * Display the appropriate prompt. 764a5f0fb15SPaul Saab */ 765a5f0fb15SPaul Saab static void 766b7780dbeSXin LI prompt(VOID_PARAM) 767a5f0fb15SPaul Saab { 7681ea31627SRobert Watson constant char *p; 769a5f0fb15SPaul Saab 770b2ea2440SXin LI if (ungot != NULL && ungot->ug_char != CHAR_END_COMMAND) 771a5f0fb15SPaul Saab { 772a5f0fb15SPaul Saab /* 773a5f0fb15SPaul Saab * No prompt necessary if commands are from 774a5f0fb15SPaul Saab * ungotten chars rather than from the user. 775a5f0fb15SPaul Saab */ 776a5f0fb15SPaul Saab return; 777a5f0fb15SPaul Saab } 778a5f0fb15SPaul Saab 779a5f0fb15SPaul Saab /* 780a5f0fb15SPaul Saab * Make sure the screen is displayed. 781a5f0fb15SPaul Saab */ 782a5f0fb15SPaul Saab make_display(); 783a5f0fb15SPaul Saab bottompos = position(BOTTOM_PLUS_ONE); 784a5f0fb15SPaul Saab 785a5f0fb15SPaul Saab /* 7867374caaaSXin LI * If we've hit EOF on the last file and the -E flag is set, quit. 787a5f0fb15SPaul Saab */ 7887374caaaSXin LI if (get_quit_at_eof() == OPT_ONPLUS && 7897374caaaSXin LI eof_displayed() && !(ch_getflags() & CH_HELPFILE) && 790a5f0fb15SPaul Saab next_ifile(curr_ifile) == NULL_IFILE) 791a5f0fb15SPaul Saab quit(QUIT_OK); 7927374caaaSXin LI 793a5f0fb15SPaul Saab /* 7947374caaaSXin LI * If the entire file is displayed and the -F flag is set, quit. 795a5f0fb15SPaul Saab */ 7967374caaaSXin LI if (quit_if_one_screen && 7977374caaaSXin LI entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) && 798a5f0fb15SPaul Saab next_ifile(curr_ifile) == NULL_IFILE) 799a5f0fb15SPaul Saab quit(QUIT_OK); 800a5f0fb15SPaul Saab 8018fd4165cSPaul Saab #if MSDOS_COMPILER==WIN32C 8028fd4165cSPaul Saab /* 8038fd4165cSPaul Saab * In Win32, display the file name in the window title. 8048fd4165cSPaul Saab */ 8058fd4165cSPaul Saab if (!(ch_getflags() & CH_HELPFILE)) 806b7780dbeSXin LI { 807b7780dbeSXin LI WCHAR w[MAX_PATH+16]; 808b7780dbeSXin LI p = pr_expand("Less?f - %f.", 0); 809b7780dbeSXin LI MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w)); 810b7780dbeSXin LI SetConsoleTitleW(w); 811b7780dbeSXin LI } 8128fd4165cSPaul Saab #endif 813b7780dbeSXin LI 814a5f0fb15SPaul Saab /* 815a5f0fb15SPaul Saab * Select the proper prompt and display it. 816a5f0fb15SPaul Saab */ 817720c436cSXin LI /* 818720c436cSXin LI * If the previous action was a forward movement, 819720c436cSXin LI * don't clear the bottom line of the display; 820720c436cSXin LI * just print the prompt since the forward movement guarantees 821720c436cSXin LI * that we're in the right position to display the prompt. 822720c436cSXin LI * Clearing the line could cause a problem: for example, if the last 823720c436cSXin LI * line displayed ended at the right screen edge without a newline, 824720c436cSXin LI * then clearing would clear the last displayed line rather than 825720c436cSXin LI * the prompt line. 826720c436cSXin LI */ 827720c436cSXin LI if (!forw_prompt) 828720c436cSXin LI clear_bot(); 829a5f0fb15SPaul Saab clear_cmd(); 830720c436cSXin LI forw_prompt = 0; 831a5f0fb15SPaul Saab p = pr_string(); 832*2235c7feSXin LI #if HILITE_SEARCH 8337374caaaSXin LI if (is_filtering()) 8347374caaaSXin LI putstr("& "); 835*2235c7feSXin LI #endif 83689dd99dcSXin LI if (p == NULL || *p == '\0') 837*2235c7feSXin LI { 838*2235c7feSXin LI at_enter(AT_NORMAL|AT_COLOR_PROMPT); 839a5f0fb15SPaul Saab putchr(':'); 840*2235c7feSXin LI at_exit(); 841*2235c7feSXin LI } else 842a5f0fb15SPaul Saab { 843b7780dbeSXin LI #if MSDOS_COMPILER==WIN32C 844b7780dbeSXin LI WCHAR w[MAX_PATH*2]; 845b7780dbeSXin LI char a[MAX_PATH*2]; 846b7780dbeSXin LI MultiByteToWideChar(CP_ACP, 0, p, -1, w, sizeof(w)/sizeof(*w)); 847b7780dbeSXin LI WideCharToMultiByte(utf_mode ? CP_UTF8 : GetConsoleOutputCP(), 848b7780dbeSXin LI 0, w, -1, a, sizeof(a), NULL, NULL); 849b7780dbeSXin LI p = a; 850b7780dbeSXin LI #endif 851*2235c7feSXin LI at_enter(AT_STANDOUT|AT_COLOR_PROMPT); 852a5f0fb15SPaul Saab putstr(p); 85389dd99dcSXin LI at_exit(); 854a5f0fb15SPaul Saab } 855720c436cSXin LI clear_eol(); 856a5f0fb15SPaul Saab } 857a5f0fb15SPaul Saab 858a5f0fb15SPaul Saab /* 859a5f0fb15SPaul Saab * Display the less version message. 860a5f0fb15SPaul Saab */ 861a5f0fb15SPaul Saab public void 862b7780dbeSXin LI dispversion(VOID_PARAM) 863a5f0fb15SPaul Saab { 864a5f0fb15SPaul Saab PARG parg; 865a5f0fb15SPaul Saab 866a5f0fb15SPaul Saab parg.p_string = version; 867a5f0fb15SPaul Saab error("less %s", &parg); 868a5f0fb15SPaul Saab } 869a5f0fb15SPaul Saab 870a5f0fb15SPaul Saab /* 871b2ea2440SXin LI * Return a character to complete a partial command, if possible. 872b2ea2440SXin LI */ 873b2ea2440SXin LI static LWCHAR 874b7780dbeSXin LI getcc_end_command(VOID_PARAM) 875b2ea2440SXin LI { 876b2ea2440SXin LI switch (mca) 877b2ea2440SXin LI { 878b2ea2440SXin LI case A_DIGIT: 879b2ea2440SXin LI /* We have a number but no command. Treat as #g. */ 880b2ea2440SXin LI return ('g'); 881b2ea2440SXin LI case A_F_SEARCH: 882b2ea2440SXin LI case A_B_SEARCH: 883b2ea2440SXin LI /* We have "/string" but no newline. Add the \n. */ 884b2ea2440SXin LI return ('\n'); 885b2ea2440SXin LI default: 886b2ea2440SXin LI /* Some other incomplete command. Let user complete it. */ 887*2235c7feSXin LI return ((ungot == NULL) ? getchr() : 0); 888b2ea2440SXin LI } 889b2ea2440SXin LI } 890b2ea2440SXin LI 891b2ea2440SXin LI /* 892a5f0fb15SPaul Saab * Get command character. 893a5f0fb15SPaul Saab * The character normally comes from the keyboard, 894a5f0fb15SPaul Saab * but may come from ungotten characters 895a5f0fb15SPaul Saab * (characters previously given to ungetcc or ungetsc). 896a5f0fb15SPaul Saab */ 897b2ea2440SXin LI static LWCHAR 89874709ed0SXin LI getccu(VOID_PARAM) 899a5f0fb15SPaul Saab { 900*2235c7feSXin LI LWCHAR c = 0; 901*2235c7feSXin LI while (c == 0) 902*2235c7feSXin LI { 903a15691bfSXin LI if (ungot == NULL) 90433096f16SXin LI { 905b2ea2440SXin LI /* Normal case: no ungotten chars. 906b2ea2440SXin LI * Get char from the user. */ 907b2ea2440SXin LI c = getchr(); 908b2ea2440SXin LI } else 909a15691bfSXin LI { 910b2ea2440SXin LI /* Ungotten chars available: 911b2ea2440SXin LI * Take the top of stack (most recent). */ 912a15691bfSXin LI struct ungot *ug = ungot; 913b2ea2440SXin LI c = ug->ug_char; 914a15691bfSXin LI ungot = ug->ug_next; 915a15691bfSXin LI free(ug); 916a5f0fb15SPaul Saab 917b2ea2440SXin LI if (c == CHAR_END_COMMAND) 918b2ea2440SXin LI c = getcc_end_command(); 919a5f0fb15SPaul Saab } 920*2235c7feSXin LI } 92133096f16SXin LI return (c); 92233096f16SXin LI } 923b2ea2440SXin LI 924b2ea2440SXin LI /* 925b2ea2440SXin LI * Get a command character, but if we receive the orig sequence, 926b2ea2440SXin LI * convert it to the repl sequence. 927b2ea2440SXin LI */ 928b2ea2440SXin LI static LWCHAR 929b2ea2440SXin LI getcc_repl(orig, repl, gr_getc, gr_ungetc) 930b2ea2440SXin LI char const* orig; 931b2ea2440SXin LI char const* repl; 932b2ea2440SXin LI LWCHAR (*gr_getc)(VOID_PARAM); 933b2ea2440SXin LI void (*gr_ungetc)(LWCHAR); 934b2ea2440SXin LI { 935b2ea2440SXin LI LWCHAR c; 936b2ea2440SXin LI LWCHAR keys[16]; 937b2ea2440SXin LI int ki = 0; 938b2ea2440SXin LI 939b2ea2440SXin LI c = (*gr_getc)(); 940b2ea2440SXin LI if (orig == NULL || orig[0] == '\0') 941b2ea2440SXin LI return c; 942b2ea2440SXin LI for (;;) 943b2ea2440SXin LI { 944b2ea2440SXin LI keys[ki] = c; 945b2ea2440SXin LI if (c != orig[ki] || ki >= sizeof(keys)-1) 946b2ea2440SXin LI { 947b2ea2440SXin LI /* This is not orig we have been receiving. 948b2ea2440SXin LI * If we have stashed chars in keys[], 949b2ea2440SXin LI * unget them and return the first one. */ 950b2ea2440SXin LI while (ki > 0) 951b2ea2440SXin LI (*gr_ungetc)(keys[ki--]); 952b2ea2440SXin LI return keys[0]; 953b2ea2440SXin LI } 954b2ea2440SXin LI if (orig[++ki] == '\0') 955b2ea2440SXin LI { 956b2ea2440SXin LI /* We've received the full orig sequence. 957b2ea2440SXin LI * Return the repl sequence. */ 958b2ea2440SXin LI ki = strlen(repl)-1; 959b2ea2440SXin LI while (ki > 0) 960b2ea2440SXin LI (*gr_ungetc)(repl[ki--]); 961b2ea2440SXin LI return repl[0]; 962b2ea2440SXin LI } 963b2ea2440SXin LI /* We've received a partial orig sequence (ki chars of it). 964b2ea2440SXin LI * Get next char and see if it continues to match orig. */ 965b2ea2440SXin LI c = (*gr_getc)(); 966b2ea2440SXin LI } 967b2ea2440SXin LI } 968b2ea2440SXin LI 969b2ea2440SXin LI /* 970b2ea2440SXin LI * Get command character. 971b2ea2440SXin LI */ 972b2ea2440SXin LI public int 973b7780dbeSXin LI getcc(VOID_PARAM) 974b2ea2440SXin LI { 975b2ea2440SXin LI /* Replace kent (keypad Enter) with a newline. */ 976b2ea2440SXin LI return getcc_repl(kent, "\n", getccu, ungetcc); 97733096f16SXin LI } 97833096f16SXin LI 979a5f0fb15SPaul Saab /* 980a5f0fb15SPaul Saab * "Unget" a command character. 981a5f0fb15SPaul Saab * The next getcc() will return this character. 982a5f0fb15SPaul Saab */ 983a5f0fb15SPaul Saab public void 984f6b74a7dSXin LI ungetcc(c) 985b2ea2440SXin LI LWCHAR c; 986a5f0fb15SPaul Saab { 98733096f16SXin LI struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); 98833096f16SXin LI 989b2ea2440SXin LI ug->ug_char = c; 99033096f16SXin LI ug->ug_next = ungot; 99133096f16SXin LI ungot = ug; 992a5f0fb15SPaul Saab } 993a5f0fb15SPaul Saab 994a5f0fb15SPaul Saab /* 995*2235c7feSXin LI * "Unget" a command character. 996*2235c7feSXin LI * If any other chars are already ungotten, put this one after those. 997*2235c7feSXin LI */ 998*2235c7feSXin LI public void 999*2235c7feSXin LI ungetcc_back(c) 1000*2235c7feSXin LI LWCHAR c; 1001*2235c7feSXin LI { 1002*2235c7feSXin LI struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); 1003*2235c7feSXin LI ug->ug_char = c; 1004*2235c7feSXin LI ug->ug_next = NULL; 1005*2235c7feSXin LI if (ungot == NULL) 1006*2235c7feSXin LI ungot = ug; 1007*2235c7feSXin LI else 1008*2235c7feSXin LI { 1009*2235c7feSXin LI struct ungot *pu; 1010*2235c7feSXin LI for (pu = ungot; pu->ug_next != NULL; pu = pu->ug_next) 1011*2235c7feSXin LI continue; 1012*2235c7feSXin LI pu->ug_next = ug; 1013*2235c7feSXin LI } 1014*2235c7feSXin LI } 1015*2235c7feSXin LI 1016*2235c7feSXin LI /* 1017a5f0fb15SPaul Saab * Unget a whole string of command characters. 1018a5f0fb15SPaul Saab * The next sequence of getcc()'s will return this string. 1019a5f0fb15SPaul Saab */ 1020a5f0fb15SPaul Saab public void 1021f6b74a7dSXin LI ungetsc(s) 1022f6b74a7dSXin LI char *s; 1023a5f0fb15SPaul Saab { 1024*2235c7feSXin LI while (*s != '\0') 1025*2235c7feSXin LI ungetcc_back(*s++); 1026a5f0fb15SPaul Saab } 1027a5f0fb15SPaul Saab 1028a5f0fb15SPaul Saab /* 1029b2ea2440SXin LI * Peek the next command character, without consuming it. 1030b2ea2440SXin LI */ 1031b2ea2440SXin LI public LWCHAR 1032b7780dbeSXin LI peekcc(VOID_PARAM) 1033b2ea2440SXin LI { 1034b2ea2440SXin LI LWCHAR c = getcc(); 1035b2ea2440SXin LI ungetcc(c); 1036b2ea2440SXin LI return c; 1037b2ea2440SXin LI } 1038b2ea2440SXin LI 1039b2ea2440SXin LI /* 1040a5f0fb15SPaul Saab * Search for a pattern, possibly in multiple files. 1041a5f0fb15SPaul Saab * If SRCH_FIRST_FILE is set, begin searching at the first file. 1042a5f0fb15SPaul Saab * If SRCH_PAST_EOF is set, continue the search thru multiple files. 1043a5f0fb15SPaul Saab */ 1044a5f0fb15SPaul Saab static void 1045f6b74a7dSXin LI multi_search(pattern, n, silent) 1046f6b74a7dSXin LI char *pattern; 1047f6b74a7dSXin LI int n; 1048f6b74a7dSXin LI int silent; 1049a5f0fb15SPaul Saab { 10501ea31627SRobert Watson int nomore; 1051a5f0fb15SPaul Saab IFILE save_ifile; 1052a5f0fb15SPaul Saab int changed_file; 1053a5f0fb15SPaul Saab 1054a5f0fb15SPaul Saab changed_file = 0; 1055a5f0fb15SPaul Saab save_ifile = save_curr_ifile(); 1056a5f0fb15SPaul Saab 1057a5f0fb15SPaul Saab if (search_type & SRCH_FIRST_FILE) 1058a5f0fb15SPaul Saab { 1059a5f0fb15SPaul Saab /* 1060a5f0fb15SPaul Saab * Start at the first (or last) file 1061a5f0fb15SPaul Saab * in the command line list. 1062a5f0fb15SPaul Saab */ 1063a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 1064a5f0fb15SPaul Saab nomore = edit_first(); 1065a5f0fb15SPaul Saab else 1066a5f0fb15SPaul Saab nomore = edit_last(); 1067a5f0fb15SPaul Saab if (nomore) 1068a5f0fb15SPaul Saab { 1069a5f0fb15SPaul Saab unsave_ifile(save_ifile); 1070a5f0fb15SPaul Saab return; 1071a5f0fb15SPaul Saab } 1072a5f0fb15SPaul Saab changed_file = 1; 1073a5f0fb15SPaul Saab search_type &= ~SRCH_FIRST_FILE; 1074a5f0fb15SPaul Saab } 1075a5f0fb15SPaul Saab 1076a5f0fb15SPaul Saab for (;;) 1077a5f0fb15SPaul Saab { 1078a5f0fb15SPaul Saab n = search(search_type, pattern, n); 1079a5f0fb15SPaul Saab /* 1080a5f0fb15SPaul Saab * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared 1081a5f0fb15SPaul Saab * after being used once. This allows "n" to work after 1082a5f0fb15SPaul Saab * using a /@@ search. 1083a5f0fb15SPaul Saab */ 1084a5f0fb15SPaul Saab search_type &= ~SRCH_NO_MOVE; 1085a5f0fb15SPaul Saab if (n == 0) 1086a5f0fb15SPaul Saab { 1087a5f0fb15SPaul Saab /* 1088a5f0fb15SPaul Saab * Found it. 1089a5f0fb15SPaul Saab */ 1090a5f0fb15SPaul Saab unsave_ifile(save_ifile); 1091a5f0fb15SPaul Saab return; 1092a5f0fb15SPaul Saab } 1093a5f0fb15SPaul Saab 1094a5f0fb15SPaul Saab if (n < 0) 1095a5f0fb15SPaul Saab /* 1096a5f0fb15SPaul Saab * Some kind of error in the search. 1097a5f0fb15SPaul Saab * Error message has been printed by search(). 1098a5f0fb15SPaul Saab */ 1099a5f0fb15SPaul Saab break; 1100a5f0fb15SPaul Saab 1101a5f0fb15SPaul Saab if ((search_type & SRCH_PAST_EOF) == 0) 1102a5f0fb15SPaul Saab /* 1103a5f0fb15SPaul Saab * We didn't find a match, but we're 1104a5f0fb15SPaul Saab * supposed to search only one file. 1105a5f0fb15SPaul Saab */ 1106a5f0fb15SPaul Saab break; 1107a5f0fb15SPaul Saab /* 1108a5f0fb15SPaul Saab * Move on to the next file. 1109a5f0fb15SPaul Saab */ 1110a5f0fb15SPaul Saab if (search_type & SRCH_FORW) 1111a5f0fb15SPaul Saab nomore = edit_next(1); 1112a5f0fb15SPaul Saab else 1113a5f0fb15SPaul Saab nomore = edit_prev(1); 1114a5f0fb15SPaul Saab if (nomore) 1115a5f0fb15SPaul Saab break; 1116a5f0fb15SPaul Saab changed_file = 1; 1117a5f0fb15SPaul Saab } 1118a5f0fb15SPaul Saab 1119a5f0fb15SPaul Saab /* 1120a5f0fb15SPaul Saab * Didn't find it. 1121a5f0fb15SPaul Saab * Print an error message if we haven't already. 1122a5f0fb15SPaul Saab */ 1123a15691bfSXin LI if (n > 0 && !silent) 1124a5f0fb15SPaul Saab error("Pattern not found", NULL_PARG); 1125a5f0fb15SPaul Saab 1126a5f0fb15SPaul Saab if (changed_file) 1127a5f0fb15SPaul Saab { 1128a5f0fb15SPaul Saab /* 1129a5f0fb15SPaul Saab * Restore the file we were originally viewing. 1130a5f0fb15SPaul Saab */ 1131a5f0fb15SPaul Saab reedit_ifile(save_ifile); 113289dd99dcSXin LI } else 113389dd99dcSXin LI { 113489dd99dcSXin LI unsave_ifile(save_ifile); 1135a5f0fb15SPaul Saab } 1136a5f0fb15SPaul Saab } 1137a5f0fb15SPaul Saab 1138a5f0fb15SPaul Saab /* 113996e55cc7SXin LI * Forward forever, or until a highlighted line appears. 114096e55cc7SXin LI */ 114196e55cc7SXin LI static int 1142f6b74a7dSXin LI forw_loop(until_hilite) 1143f6b74a7dSXin LI int until_hilite; 114496e55cc7SXin LI { 114596e55cc7SXin LI POSITION curr_len; 114696e55cc7SXin LI 114796e55cc7SXin LI if (ch_getflags() & CH_HELPFILE) 114896e55cc7SXin LI return (A_NOACTION); 114996e55cc7SXin LI 115096e55cc7SXin LI cmd_exec(); 1151a15691bfSXin LI jump_forw_buffered(); 115296e55cc7SXin LI curr_len = ch_length(); 115396e55cc7SXin LI highest_hilite = until_hilite ? curr_len : NULL_POSITION; 115496e55cc7SXin LI ignore_eoi = 1; 115596e55cc7SXin LI while (!sigs) 115696e55cc7SXin LI { 115796e55cc7SXin LI if (until_hilite && highest_hilite > curr_len) 115896e55cc7SXin LI { 115996e55cc7SXin LI bell(); 116096e55cc7SXin LI break; 116196e55cc7SXin LI } 116296e55cc7SXin LI make_display(); 116396e55cc7SXin LI forward(1, 0, 0); 116496e55cc7SXin LI } 116596e55cc7SXin LI ignore_eoi = 0; 1166e2449719SXin LI ch_set_eof(); 116796e55cc7SXin LI 116896e55cc7SXin LI /* 116996e55cc7SXin LI * This gets us back in "F mode" after processing 117096e55cc7SXin LI * a non-abort signal (e.g. window-change). 117196e55cc7SXin LI */ 117296e55cc7SXin LI if (sigs && !ABORT_SIGS()) 1173e2449719SXin LI return (until_hilite ? A_F_UNTIL_HILITE : A_F_FOREVER); 1174e2449719SXin LI 117596e55cc7SXin LI return (A_NOACTION); 117696e55cc7SXin LI } 117796e55cc7SXin LI 117896e55cc7SXin LI /* 1179a5f0fb15SPaul Saab * Main command processor. 1180a5f0fb15SPaul Saab * Accept and execute commands until a quit command. 1181a5f0fb15SPaul Saab */ 1182a5f0fb15SPaul Saab public void 1183b7780dbeSXin LI commands(VOID_PARAM) 1184a5f0fb15SPaul Saab { 11851ea31627SRobert Watson int c; 11861ea31627SRobert Watson int action; 11871ea31627SRobert Watson char *cbuf; 1188a5f0fb15SPaul Saab int newaction; 1189*2235c7feSXin LI int save_jump_sline; 1190a5f0fb15SPaul Saab int save_search_type; 1191a5f0fb15SPaul Saab char *extra; 1192a5f0fb15SPaul Saab char tbuf[2]; 1193a5f0fb15SPaul Saab PARG parg; 1194a5f0fb15SPaul Saab IFILE old_ifile; 1195a5f0fb15SPaul Saab IFILE new_ifile; 11968fd4165cSPaul Saab char *tagfile; 1197a5f0fb15SPaul Saab 1198a5f0fb15SPaul Saab search_type = SRCH_FORW; 1199a5f0fb15SPaul Saab wscroll = (sc_height + 1) / 2; 1200a5f0fb15SPaul Saab newaction = A_NOACTION; 1201a5f0fb15SPaul Saab 1202a5f0fb15SPaul Saab for (;;) 1203a5f0fb15SPaul Saab { 1204b7780dbeSXin LI clear_mca(); 1205a5f0fb15SPaul Saab cmd_accept(); 1206a5f0fb15SPaul Saab number = 0; 120733096f16SXin LI curropt = NULL; 1208a5f0fb15SPaul Saab 1209a5f0fb15SPaul Saab /* 1210a5f0fb15SPaul Saab * See if any signals need processing. 1211a5f0fb15SPaul Saab */ 1212a5f0fb15SPaul Saab if (sigs) 1213a5f0fb15SPaul Saab { 1214a5f0fb15SPaul Saab psignals(); 1215a5f0fb15SPaul Saab if (quitting) 1216a5f0fb15SPaul Saab quit(QUIT_SAVED_STATUS); 1217a5f0fb15SPaul Saab } 1218a5f0fb15SPaul Saab 1219a5f0fb15SPaul Saab /* 1220a5f0fb15SPaul Saab * See if window size changed, for systems that don't 1221a5f0fb15SPaul Saab * generate SIGWINCH. 1222a5f0fb15SPaul Saab */ 1223a5f0fb15SPaul Saab check_winch(); 1224a5f0fb15SPaul Saab 1225a5f0fb15SPaul Saab /* 1226a5f0fb15SPaul Saab * Display prompt and accept a character. 1227a5f0fb15SPaul Saab */ 1228a5f0fb15SPaul Saab cmd_reset(); 1229a5f0fb15SPaul Saab prompt(); 1230a5f0fb15SPaul Saab if (sigs) 1231a5f0fb15SPaul Saab continue; 1232a5f0fb15SPaul Saab if (newaction == A_NOACTION) 1233a5f0fb15SPaul Saab c = getcc(); 1234a5f0fb15SPaul Saab 1235a5f0fb15SPaul Saab again: 1236a5f0fb15SPaul Saab if (sigs) 1237a5f0fb15SPaul Saab continue; 1238a5f0fb15SPaul Saab 1239a5f0fb15SPaul Saab if (newaction != A_NOACTION) 1240a5f0fb15SPaul Saab { 1241a5f0fb15SPaul Saab action = newaction; 1242a5f0fb15SPaul Saab newaction = A_NOACTION; 1243a5f0fb15SPaul Saab } else 1244a5f0fb15SPaul Saab { 1245a5f0fb15SPaul Saab /* 1246a5f0fb15SPaul Saab * If we are in a multicharacter command, call mca_char. 1247a5f0fb15SPaul Saab * Otherwise we call fcmd_decode to determine the 1248a5f0fb15SPaul Saab * action to be performed. 1249a5f0fb15SPaul Saab */ 1250a5f0fb15SPaul Saab if (mca) 1251a5f0fb15SPaul Saab switch (mca_char(c)) 1252a5f0fb15SPaul Saab { 1253a5f0fb15SPaul Saab case MCA_MORE: 1254a5f0fb15SPaul Saab /* 1255a5f0fb15SPaul Saab * Need another character. 1256a5f0fb15SPaul Saab */ 1257a5f0fb15SPaul Saab c = getcc(); 1258a5f0fb15SPaul Saab goto again; 1259a5f0fb15SPaul Saab case MCA_DONE: 1260a5f0fb15SPaul Saab /* 1261a5f0fb15SPaul Saab * Command has been handled by mca_char. 1262a5f0fb15SPaul Saab * Start clean with a prompt. 1263a5f0fb15SPaul Saab */ 1264a5f0fb15SPaul Saab continue; 1265a5f0fb15SPaul Saab case NO_MCA: 1266a5f0fb15SPaul Saab /* 1267a5f0fb15SPaul Saab * Not a multi-char command 1268a5f0fb15SPaul Saab * (at least, not anymore). 1269a5f0fb15SPaul Saab */ 1270a5f0fb15SPaul Saab break; 1271a5f0fb15SPaul Saab } 1272a5f0fb15SPaul Saab 1273a5f0fb15SPaul Saab /* 1274a5f0fb15SPaul Saab * Decode the command character and decide what to do. 1275a5f0fb15SPaul Saab */ 1276a5f0fb15SPaul Saab if (mca) 1277a5f0fb15SPaul Saab { 1278a5f0fb15SPaul Saab /* 1279a5f0fb15SPaul Saab * We're in a multichar command. 1280a5f0fb15SPaul Saab * Add the character to the command buffer 1281a5f0fb15SPaul Saab * and display it on the screen. 1282a5f0fb15SPaul Saab * If the user backspaces past the start 1283a5f0fb15SPaul Saab * of the line, abort the command. 1284a5f0fb15SPaul Saab */ 1285a5f0fb15SPaul Saab if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0) 1286a5f0fb15SPaul Saab continue; 1287a5f0fb15SPaul Saab cbuf = get_cmdbuf(); 1288a5f0fb15SPaul Saab } else 1289a5f0fb15SPaul Saab { 1290a5f0fb15SPaul Saab /* 1291a5f0fb15SPaul Saab * Don't use cmd_char if we're starting fresh 1292a5f0fb15SPaul Saab * at the beginning of a command, because we 1293a5f0fb15SPaul Saab * don't want to echo the command until we know 1294a5f0fb15SPaul Saab * it is a multichar command. We also don't 1295a5f0fb15SPaul Saab * want erase_char/kill_char to be treated 1296a5f0fb15SPaul Saab * as line editing characters. 1297a5f0fb15SPaul Saab */ 1298a5f0fb15SPaul Saab tbuf[0] = c; 1299a5f0fb15SPaul Saab tbuf[1] = '\0'; 1300a5f0fb15SPaul Saab cbuf = tbuf; 1301a5f0fb15SPaul Saab } 1302a5f0fb15SPaul Saab extra = NULL; 1303a5f0fb15SPaul Saab action = fcmd_decode(cbuf, &extra); 1304a5f0fb15SPaul Saab /* 1305a5f0fb15SPaul Saab * If an "extra" string was returned, 1306a5f0fb15SPaul Saab * process it as a string of command characters. 1307a5f0fb15SPaul Saab */ 1308a5f0fb15SPaul Saab if (extra != NULL) 1309a5f0fb15SPaul Saab ungetsc(extra); 1310a5f0fb15SPaul Saab } 1311a5f0fb15SPaul Saab /* 1312a5f0fb15SPaul Saab * Clear the cmdbuf string. 1313a5f0fb15SPaul Saab * (But not if we're in the prefix of a command, 1314a5f0fb15SPaul Saab * because the partial command string is kept there.) 1315a5f0fb15SPaul Saab */ 1316a5f0fb15SPaul Saab if (action != A_PREFIX) 1317a5f0fb15SPaul Saab cmd_reset(); 1318a5f0fb15SPaul Saab 1319a5f0fb15SPaul Saab switch (action) 1320a5f0fb15SPaul Saab { 1321a5f0fb15SPaul Saab case A_DIGIT: 1322a5f0fb15SPaul Saab /* 1323a5f0fb15SPaul Saab * First digit of a number. 1324a5f0fb15SPaul Saab */ 1325a5f0fb15SPaul Saab start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE); 1326a5f0fb15SPaul Saab goto again; 1327a5f0fb15SPaul Saab 1328a5f0fb15SPaul Saab case A_F_WINDOW: 1329a5f0fb15SPaul Saab /* 1330a5f0fb15SPaul Saab * Forward one window (and set the window size). 1331a5f0fb15SPaul Saab */ 1332a5f0fb15SPaul Saab if (number > 0) 13331ede1615STim J. Robbins swindow = (int) number; 1334a5f0fb15SPaul Saab /* FALLTHRU */ 1335a5f0fb15SPaul Saab case A_F_SCREEN: 1336a5f0fb15SPaul Saab /* 1337a5f0fb15SPaul Saab * Forward one screen. 1338a5f0fb15SPaul Saab */ 1339a5f0fb15SPaul Saab if (number <= 0) 1340a5f0fb15SPaul Saab number = get_swindow(); 1341a5f0fb15SPaul Saab cmd_exec(); 1342a5f0fb15SPaul Saab if (show_attn) 1343a5f0fb15SPaul Saab set_attnpos(bottompos); 13441ede1615STim J. Robbins forward((int) number, 0, 1); 1345a5f0fb15SPaul Saab break; 1346a5f0fb15SPaul Saab 1347a5f0fb15SPaul Saab case A_B_WINDOW: 1348a5f0fb15SPaul Saab /* 1349a5f0fb15SPaul Saab * Backward one window (and set the window size). 1350a5f0fb15SPaul Saab */ 1351a5f0fb15SPaul Saab if (number > 0) 13521ede1615STim J. Robbins swindow = (int) number; 1353a5f0fb15SPaul Saab /* FALLTHRU */ 1354a5f0fb15SPaul Saab case A_B_SCREEN: 1355a5f0fb15SPaul Saab /* 1356a5f0fb15SPaul Saab * Backward one screen. 1357a5f0fb15SPaul Saab */ 1358a5f0fb15SPaul Saab if (number <= 0) 1359a5f0fb15SPaul Saab number = get_swindow(); 1360a5f0fb15SPaul Saab cmd_exec(); 13611ede1615STim J. Robbins backward((int) number, 0, 1); 1362a5f0fb15SPaul Saab break; 1363a5f0fb15SPaul Saab 1364a5f0fb15SPaul Saab case A_F_LINE: 1365a5f0fb15SPaul Saab /* 1366a5f0fb15SPaul Saab * Forward N (default 1) line. 1367a5f0fb15SPaul Saab */ 1368a5f0fb15SPaul Saab if (number <= 0) 1369a5f0fb15SPaul Saab number = 1; 1370a5f0fb15SPaul Saab cmd_exec(); 1371a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS && number > 1) 1372a5f0fb15SPaul Saab set_attnpos(bottompos); 13731ede1615STim J. Robbins forward((int) number, 0, 0); 1374a5f0fb15SPaul Saab break; 1375a5f0fb15SPaul Saab 1376a5f0fb15SPaul Saab case A_B_LINE: 1377a5f0fb15SPaul Saab /* 1378a5f0fb15SPaul Saab * Backward N (default 1) line. 1379a5f0fb15SPaul Saab */ 1380a5f0fb15SPaul Saab if (number <= 0) 1381a5f0fb15SPaul Saab number = 1; 1382a5f0fb15SPaul Saab cmd_exec(); 13831ede1615STim J. Robbins backward((int) number, 0, 0); 1384a5f0fb15SPaul Saab break; 1385a5f0fb15SPaul Saab 1386b7780dbeSXin LI case A_F_MOUSE: 1387b7780dbeSXin LI /* 1388b7780dbeSXin LI * Forward wheel_lines lines. 1389b7780dbeSXin LI */ 1390b7780dbeSXin LI cmd_exec(); 1391b7780dbeSXin LI forward(wheel_lines, 0, 0); 1392b7780dbeSXin LI break; 1393b7780dbeSXin LI 1394b7780dbeSXin LI case A_B_MOUSE: 1395b7780dbeSXin LI /* 1396b7780dbeSXin LI * Backward wheel_lines lines. 1397b7780dbeSXin LI */ 1398b7780dbeSXin LI cmd_exec(); 1399b7780dbeSXin LI backward(wheel_lines, 0, 0); 1400b7780dbeSXin LI break; 1401b7780dbeSXin LI 1402a5f0fb15SPaul Saab case A_FF_LINE: 1403a5f0fb15SPaul Saab /* 1404a5f0fb15SPaul Saab * Force forward N (default 1) line. 1405a5f0fb15SPaul Saab */ 1406a5f0fb15SPaul Saab if (number <= 0) 1407a5f0fb15SPaul Saab number = 1; 1408a5f0fb15SPaul Saab cmd_exec(); 1409a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS && number > 1) 1410a5f0fb15SPaul Saab set_attnpos(bottompos); 14111ede1615STim J. Robbins forward((int) number, 1, 0); 1412a5f0fb15SPaul Saab break; 1413a5f0fb15SPaul Saab 1414a5f0fb15SPaul Saab case A_BF_LINE: 1415a5f0fb15SPaul Saab /* 1416a5f0fb15SPaul Saab * Force backward N (default 1) line. 1417a5f0fb15SPaul Saab */ 1418a5f0fb15SPaul Saab if (number <= 0) 1419a5f0fb15SPaul Saab number = 1; 1420a5f0fb15SPaul Saab cmd_exec(); 14211ede1615STim J. Robbins backward((int) number, 1, 0); 1422a5f0fb15SPaul Saab break; 1423a5f0fb15SPaul Saab 1424a5f0fb15SPaul Saab case A_FF_SCREEN: 1425a5f0fb15SPaul Saab /* 1426a5f0fb15SPaul Saab * Force forward one screen. 1427a5f0fb15SPaul Saab */ 1428a5f0fb15SPaul Saab if (number <= 0) 1429a5f0fb15SPaul Saab number = get_swindow(); 1430a5f0fb15SPaul Saab cmd_exec(); 1431a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS) 1432a5f0fb15SPaul Saab set_attnpos(bottompos); 14331ede1615STim J. Robbins forward((int) number, 1, 0); 1434a5f0fb15SPaul Saab break; 1435a5f0fb15SPaul Saab 1436a5f0fb15SPaul Saab case A_F_FOREVER: 1437a5f0fb15SPaul Saab /* 1438a5f0fb15SPaul Saab * Forward forever, ignoring EOF. 1439a5f0fb15SPaul Saab */ 1440a15691bfSXin LI if (show_attn) 1441a15691bfSXin LI set_attnpos(bottompos); 144296e55cc7SXin LI newaction = forw_loop(0); 1443a5f0fb15SPaul Saab break; 144496e55cc7SXin LI 144596e55cc7SXin LI case A_F_UNTIL_HILITE: 144696e55cc7SXin LI newaction = forw_loop(1); 1447a5f0fb15SPaul Saab break; 1448a5f0fb15SPaul Saab 1449a5f0fb15SPaul Saab case A_F_SCROLL: 1450a5f0fb15SPaul Saab /* 1451a5f0fb15SPaul Saab * Forward N lines 1452a5f0fb15SPaul Saab * (default same as last 'd' or 'u' command). 1453a5f0fb15SPaul Saab */ 1454a5f0fb15SPaul Saab if (number > 0) 14551ede1615STim J. Robbins wscroll = (int) number; 1456a5f0fb15SPaul Saab cmd_exec(); 1457a5f0fb15SPaul Saab if (show_attn == OPT_ONPLUS) 1458a5f0fb15SPaul Saab set_attnpos(bottompos); 1459a5f0fb15SPaul Saab forward(wscroll, 0, 0); 1460a5f0fb15SPaul Saab break; 1461a5f0fb15SPaul Saab 1462a5f0fb15SPaul Saab case A_B_SCROLL: 1463a5f0fb15SPaul Saab /* 1464a5f0fb15SPaul Saab * Forward N lines 1465a5f0fb15SPaul Saab * (default same as last 'd' or 'u' command). 1466a5f0fb15SPaul Saab */ 1467a5f0fb15SPaul Saab if (number > 0) 14681ede1615STim J. Robbins wscroll = (int) number; 1469a5f0fb15SPaul Saab cmd_exec(); 1470a5f0fb15SPaul Saab backward(wscroll, 0, 0); 1471a5f0fb15SPaul Saab break; 1472a5f0fb15SPaul Saab 1473a5f0fb15SPaul Saab case A_FREPAINT: 1474a5f0fb15SPaul Saab /* 1475a5f0fb15SPaul Saab * Flush buffers, then repaint screen. 1476a5f0fb15SPaul Saab * Don't flush the buffers on a pipe! 1477a5f0fb15SPaul Saab */ 1478423c5ce5SXin LI clear_buffers(); 1479a5f0fb15SPaul Saab /* FALLTHRU */ 1480a5f0fb15SPaul Saab case A_REPAINT: 1481a5f0fb15SPaul Saab /* 1482a5f0fb15SPaul Saab * Repaint screen. 1483a5f0fb15SPaul Saab */ 1484a5f0fb15SPaul Saab cmd_exec(); 1485a5f0fb15SPaul Saab repaint(); 1486a5f0fb15SPaul Saab break; 1487a5f0fb15SPaul Saab 1488a5f0fb15SPaul Saab case A_GOLINE: 1489a5f0fb15SPaul Saab /* 1490a5f0fb15SPaul Saab * Go to line N, default beginning of file. 1491*2235c7feSXin LI * If N <= 0, ignore jump_sline in order to avoid 1492*2235c7feSXin LI * empty lines before the beginning of the file. 1493a5f0fb15SPaul Saab */ 1494*2235c7feSXin LI save_jump_sline = jump_sline; 1495a5f0fb15SPaul Saab if (number <= 0) 1496*2235c7feSXin LI { 1497a5f0fb15SPaul Saab number = 1; 1498*2235c7feSXin LI jump_sline = 0; 1499*2235c7feSXin LI } 1500a5f0fb15SPaul Saab cmd_exec(); 1501a5f0fb15SPaul Saab jump_back(number); 1502*2235c7feSXin LI jump_sline = save_jump_sline; 1503a5f0fb15SPaul Saab break; 1504a5f0fb15SPaul Saab 1505a5f0fb15SPaul Saab case A_PERCENT: 1506a5f0fb15SPaul Saab /* 1507a5f0fb15SPaul Saab * Go to a specified percentage into the file. 1508a5f0fb15SPaul Saab */ 1509a5f0fb15SPaul Saab if (number < 0) 1510720c436cSXin LI { 1511a5f0fb15SPaul Saab number = 0; 1512720c436cSXin LI fraction = 0; 1513720c436cSXin LI } 1514b7780dbeSXin LI if (number > 100 || (number == 100 && fraction != 0)) 1515720c436cSXin LI { 1516a5f0fb15SPaul Saab number = 100; 1517720c436cSXin LI fraction = 0; 1518720c436cSXin LI } 1519a5f0fb15SPaul Saab cmd_exec(); 1520720c436cSXin LI jump_percent((int) number, fraction); 1521a5f0fb15SPaul Saab break; 1522a5f0fb15SPaul Saab 1523a5f0fb15SPaul Saab case A_GOEND: 1524a5f0fb15SPaul Saab /* 1525a5f0fb15SPaul Saab * Go to line N, default end of file. 1526a5f0fb15SPaul Saab */ 1527a5f0fb15SPaul Saab cmd_exec(); 1528a5f0fb15SPaul Saab if (number <= 0) 1529a5f0fb15SPaul Saab jump_forw(); 1530a5f0fb15SPaul Saab else 1531a5f0fb15SPaul Saab jump_back(number); 1532a5f0fb15SPaul Saab break; 1533a5f0fb15SPaul Saab 1534a15691bfSXin LI case A_GOEND_BUF: 1535a15691bfSXin LI /* 1536a15691bfSXin LI * Go to line N, default last buffered byte. 1537a15691bfSXin LI */ 1538a15691bfSXin LI cmd_exec(); 1539a15691bfSXin LI if (number <= 0) 1540a15691bfSXin LI jump_forw_buffered(); 1541a15691bfSXin LI else 1542a15691bfSXin LI jump_back(number); 1543a15691bfSXin LI break; 1544a15691bfSXin LI 1545a5f0fb15SPaul Saab case A_GOPOS: 1546a5f0fb15SPaul Saab /* 1547a5f0fb15SPaul Saab * Go to a specified byte position in the file. 1548a5f0fb15SPaul Saab */ 1549a5f0fb15SPaul Saab cmd_exec(); 1550a5f0fb15SPaul Saab if (number < 0) 1551a5f0fb15SPaul Saab number = 0; 1552a5f0fb15SPaul Saab jump_line_loc((POSITION) number, jump_sline); 1553a5f0fb15SPaul Saab break; 1554a5f0fb15SPaul Saab 1555a5f0fb15SPaul Saab case A_STAT: 1556a5f0fb15SPaul Saab /* 1557a5f0fb15SPaul Saab * Print file name, etc. 1558a5f0fb15SPaul Saab */ 1559a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1560a5f0fb15SPaul Saab break; 1561a5f0fb15SPaul Saab cmd_exec(); 1562a5f0fb15SPaul Saab parg.p_string = eq_message(); 1563a5f0fb15SPaul Saab error("%s", &parg); 1564a5f0fb15SPaul Saab break; 1565a5f0fb15SPaul Saab 1566a5f0fb15SPaul Saab case A_VERSION: 1567a5f0fb15SPaul Saab /* 1568*2235c7feSXin LI * Print version number. 1569a5f0fb15SPaul Saab */ 1570a5f0fb15SPaul Saab cmd_exec(); 1571a5f0fb15SPaul Saab dispversion(); 1572a5f0fb15SPaul Saab break; 1573a5f0fb15SPaul Saab 1574a5f0fb15SPaul Saab case A_QUIT: 1575a5f0fb15SPaul Saab /* 1576a5f0fb15SPaul Saab * Exit. 1577a5f0fb15SPaul Saab */ 1578a5f0fb15SPaul Saab if (curr_ifile != NULL_IFILE && 1579a5f0fb15SPaul Saab ch_getflags() & CH_HELPFILE) 1580a5f0fb15SPaul Saab { 1581a5f0fb15SPaul Saab /* 1582a5f0fb15SPaul Saab * Quit while viewing the help file 1583a5f0fb15SPaul Saab * just means return to viewing the 1584a5f0fb15SPaul Saab * previous file. 1585a5f0fb15SPaul Saab */ 158689dd99dcSXin LI hshift = save_hshift; 1587a15691bfSXin LI bs_mode = save_bs_mode; 1588a5f0fb15SPaul Saab if (edit_prev(1) == 0) 1589a5f0fb15SPaul Saab break; 1590a5f0fb15SPaul Saab } 1591a5f0fb15SPaul Saab if (extra != NULL) 1592a5f0fb15SPaul Saab quit(*extra); 1593a5f0fb15SPaul Saab quit(QUIT_OK); 1594a5f0fb15SPaul Saab break; 1595a5f0fb15SPaul Saab 1596a5f0fb15SPaul Saab /* 1597a5f0fb15SPaul Saab * Define abbreviation for a commonly used sequence below. 1598a5f0fb15SPaul Saab */ 1599423c5ce5SXin LI #define DO_SEARCH() \ 1600423c5ce5SXin LI if (number <= 0) number = 1; \ 1601a5f0fb15SPaul Saab mca_search(); \ 1602a5f0fb15SPaul Saab cmd_exec(); \ 1603a15691bfSXin LI multi_search((char *)NULL, (int) number, 0); 1604a5f0fb15SPaul Saab 1605a5f0fb15SPaul Saab 1606a5f0fb15SPaul Saab case A_F_SEARCH: 1607a5f0fb15SPaul Saab /* 1608a5f0fb15SPaul Saab * Search forward for a pattern. 1609a5f0fb15SPaul Saab * Get the first char of the pattern. 1610a5f0fb15SPaul Saab */ 1611a5f0fb15SPaul Saab search_type = SRCH_FORW; 1612a5f0fb15SPaul Saab if (number <= 0) 1613a5f0fb15SPaul Saab number = 1; 1614a5f0fb15SPaul Saab mca_search(); 1615a5f0fb15SPaul Saab c = getcc(); 1616a5f0fb15SPaul Saab goto again; 1617a5f0fb15SPaul Saab 1618a5f0fb15SPaul Saab case A_B_SEARCH: 1619a5f0fb15SPaul Saab /* 1620a5f0fb15SPaul Saab * Search backward for a pattern. 1621a5f0fb15SPaul Saab * Get the first char of the pattern. 1622a5f0fb15SPaul Saab */ 1623a5f0fb15SPaul Saab search_type = SRCH_BACK; 1624a5f0fb15SPaul Saab if (number <= 0) 1625a5f0fb15SPaul Saab number = 1; 1626a5f0fb15SPaul Saab mca_search(); 1627a5f0fb15SPaul Saab c = getcc(); 1628a5f0fb15SPaul Saab goto again; 1629a5f0fb15SPaul Saab 16307374caaaSXin LI case A_FILTER: 16317374caaaSXin LI #if HILITE_SEARCH 16327374caaaSXin LI search_type = SRCH_FORW | SRCH_FILTER; 16337374caaaSXin LI mca_search(); 16347374caaaSXin LI c = getcc(); 16357374caaaSXin LI goto again; 16367374caaaSXin LI #else 16377374caaaSXin LI error("Command not available", NULL_PARG); 16387374caaaSXin LI break; 16397374caaaSXin LI #endif 16407374caaaSXin LI 1641a5f0fb15SPaul Saab case A_AGAIN_SEARCH: 1642a5f0fb15SPaul Saab /* 1643a5f0fb15SPaul Saab * Repeat previous search. 1644a5f0fb15SPaul Saab */ 1645a5f0fb15SPaul Saab DO_SEARCH(); 1646a5f0fb15SPaul Saab break; 1647a5f0fb15SPaul Saab 1648a5f0fb15SPaul Saab case A_T_AGAIN_SEARCH: 1649a5f0fb15SPaul Saab /* 1650a5f0fb15SPaul Saab * Repeat previous search, multiple files. 1651a5f0fb15SPaul Saab */ 1652a5f0fb15SPaul Saab search_type |= SRCH_PAST_EOF; 1653a5f0fb15SPaul Saab DO_SEARCH(); 1654a5f0fb15SPaul Saab break; 1655a5f0fb15SPaul Saab 1656a5f0fb15SPaul Saab case A_REVERSE_SEARCH: 1657a5f0fb15SPaul Saab /* 1658a5f0fb15SPaul Saab * Repeat previous search, in reverse direction. 1659a5f0fb15SPaul Saab */ 1660a5f0fb15SPaul Saab save_search_type = search_type; 1661a5f0fb15SPaul Saab search_type = SRCH_REVERSE(search_type); 1662a5f0fb15SPaul Saab DO_SEARCH(); 1663a5f0fb15SPaul Saab search_type = save_search_type; 1664a5f0fb15SPaul Saab break; 1665a5f0fb15SPaul Saab 1666a5f0fb15SPaul Saab case A_T_REVERSE_SEARCH: 1667a5f0fb15SPaul Saab /* 1668a5f0fb15SPaul Saab * Repeat previous search, 1669a5f0fb15SPaul Saab * multiple files in reverse direction. 1670a5f0fb15SPaul Saab */ 1671a5f0fb15SPaul Saab save_search_type = search_type; 1672a5f0fb15SPaul Saab search_type = SRCH_REVERSE(search_type); 1673a5f0fb15SPaul Saab search_type |= SRCH_PAST_EOF; 1674a5f0fb15SPaul Saab DO_SEARCH(); 1675a5f0fb15SPaul Saab search_type = save_search_type; 1676a5f0fb15SPaul Saab break; 1677a5f0fb15SPaul Saab 1678a5f0fb15SPaul Saab case A_UNDO_SEARCH: 1679*2235c7feSXin LI case A_CLR_SEARCH: 1680b2ea2440SXin LI /* 1681b2ea2440SXin LI * Clear search string highlighting. 1682b2ea2440SXin LI */ 1683*2235c7feSXin LI undo_search(action == A_CLR_SEARCH); 1684a5f0fb15SPaul Saab break; 1685a5f0fb15SPaul Saab 1686a5f0fb15SPaul Saab case A_HELP: 1687a5f0fb15SPaul Saab /* 1688a5f0fb15SPaul Saab * Help. 1689a5f0fb15SPaul Saab */ 1690a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1691a5f0fb15SPaul Saab break; 1692a5f0fb15SPaul Saab cmd_exec(); 169389dd99dcSXin LI save_hshift = hshift; 169489dd99dcSXin LI hshift = 0; 1695a15691bfSXin LI save_bs_mode = bs_mode; 1696a15691bfSXin LI bs_mode = BS_SPECIAL; 1697a5f0fb15SPaul Saab (void) edit(FAKE_HELPFILE); 1698a5f0fb15SPaul Saab break; 1699a5f0fb15SPaul Saab 1700a5f0fb15SPaul Saab case A_EXAMINE: 1701a5f0fb15SPaul Saab /* 1702a5f0fb15SPaul Saab * Edit a new file. Get the filename. 1703a5f0fb15SPaul Saab */ 1704b2ea2440SXin LI #if EXAMINE 1705b2ea2440SXin LI if (!secure) 1706a5f0fb15SPaul Saab { 1707dd3bd0edSDimitry Andric start_mca(A_EXAMINE, "Examine: ", ml_examine, 0); 1708a5f0fb15SPaul Saab c = getcc(); 1709a5f0fb15SPaul Saab goto again; 1710b2ea2440SXin LI } 1711b2ea2440SXin LI #endif 1712a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 1713a5f0fb15SPaul Saab break; 1714a5f0fb15SPaul Saab 1715a5f0fb15SPaul Saab case A_VISUAL: 1716a5f0fb15SPaul Saab /* 1717a5f0fb15SPaul Saab * Invoke an editor on the input file. 1718a5f0fb15SPaul Saab */ 1719a5f0fb15SPaul Saab #if EDITOR 1720b2ea2440SXin LI if (!secure) 1721a5f0fb15SPaul Saab { 1722a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1723a5f0fb15SPaul Saab break; 1724a5f0fb15SPaul Saab if (strcmp(get_filename(curr_ifile), "-") == 0) 1725a5f0fb15SPaul Saab { 1726a5f0fb15SPaul Saab error("Cannot edit standard input", NULL_PARG); 1727a5f0fb15SPaul Saab break; 1728a5f0fb15SPaul Saab } 1729b2ea2440SXin LI if (get_altfilename(curr_ifile) != NULL) 1730a5f0fb15SPaul Saab { 173189dd99dcSXin LI error("WARNING: This file was viewed via LESSOPEN", 1732a5f0fb15SPaul Saab NULL_PARG); 1733a5f0fb15SPaul Saab } 1734dd3bd0edSDimitry Andric start_mca(A_SHELL, "!", ml_shell, 0); 1735a5f0fb15SPaul Saab /* 1736a5f0fb15SPaul Saab * Expand the editor prototype string 1737a5f0fb15SPaul Saab * and pass it to the system to execute. 1738a5f0fb15SPaul Saab * (Make sure the screen is displayed so the 1739a5f0fb15SPaul Saab * expansion of "+%lm" works.) 1740a5f0fb15SPaul Saab */ 1741a5f0fb15SPaul Saab make_display(); 1742a5f0fb15SPaul Saab cmd_exec(); 1743a5f0fb15SPaul Saab lsystem(pr_expand(editproto, 0), (char*)NULL); 1744a5f0fb15SPaul Saab break; 1745b2ea2440SXin LI } 1746b2ea2440SXin LI #endif 1747a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 1748a5f0fb15SPaul Saab break; 1749a5f0fb15SPaul Saab 1750a5f0fb15SPaul Saab case A_NEXT_FILE: 1751a5f0fb15SPaul Saab /* 1752a5f0fb15SPaul Saab * Examine next file. 1753a5f0fb15SPaul Saab */ 17541ede1615STim J. Robbins #if TAGS 17558fd4165cSPaul Saab if (ntags()) 17568fd4165cSPaul Saab { 17578fd4165cSPaul Saab error("No next file", NULL_PARG); 17588fd4165cSPaul Saab break; 17598fd4165cSPaul Saab } 17601ede1615STim J. Robbins #endif 1761a5f0fb15SPaul Saab if (number <= 0) 1762a5f0fb15SPaul Saab number = 1; 17631ede1615STim J. Robbins if (edit_next((int) number)) 1764a5f0fb15SPaul Saab { 17657374caaaSXin LI if (get_quit_at_eof() && eof_displayed() && 1766a5f0fb15SPaul Saab !(ch_getflags() & CH_HELPFILE)) 1767a5f0fb15SPaul Saab quit(QUIT_OK); 1768a5f0fb15SPaul Saab parg.p_string = (number > 1) ? "(N-th) " : ""; 1769a5f0fb15SPaul Saab error("No %snext file", &parg); 1770a5f0fb15SPaul Saab } 1771a5f0fb15SPaul Saab break; 1772a5f0fb15SPaul Saab 1773a5f0fb15SPaul Saab case A_PREV_FILE: 1774a5f0fb15SPaul Saab /* 1775a5f0fb15SPaul Saab * Examine previous file. 1776a5f0fb15SPaul Saab */ 17771ede1615STim J. Robbins #if TAGS 17788fd4165cSPaul Saab if (ntags()) 17798fd4165cSPaul Saab { 17808fd4165cSPaul Saab error("No previous file", NULL_PARG); 17818fd4165cSPaul Saab break; 17828fd4165cSPaul Saab } 17831ede1615STim J. Robbins #endif 1784a5f0fb15SPaul Saab if (number <= 0) 1785a5f0fb15SPaul Saab number = 1; 17861ede1615STim J. Robbins if (edit_prev((int) number)) 1787a5f0fb15SPaul Saab { 1788a5f0fb15SPaul Saab parg.p_string = (number > 1) ? "(N-th) " : ""; 1789a5f0fb15SPaul Saab error("No %sprevious file", &parg); 1790a5f0fb15SPaul Saab } 1791a5f0fb15SPaul Saab break; 1792a5f0fb15SPaul Saab 17938fd4165cSPaul Saab case A_NEXT_TAG: 1794b2ea2440SXin LI /* 1795b2ea2440SXin LI * Jump to the next tag in the current tag list. 1796b2ea2440SXin LI */ 17971ede1615STim J. Robbins #if TAGS 17988fd4165cSPaul Saab if (number <= 0) 17998fd4165cSPaul Saab number = 1; 18001ede1615STim J. Robbins tagfile = nexttag((int) number); 18018fd4165cSPaul Saab if (tagfile == NULL) 18028fd4165cSPaul Saab { 18038fd4165cSPaul Saab error("No next tag", NULL_PARG); 18048fd4165cSPaul Saab break; 18058fd4165cSPaul Saab } 1806b2ea2440SXin LI cmd_exec(); 18078fd4165cSPaul Saab if (edit(tagfile) == 0) 18088fd4165cSPaul Saab { 18098fd4165cSPaul Saab POSITION pos = tagsearch(); 18108fd4165cSPaul Saab if (pos != NULL_POSITION) 18118fd4165cSPaul Saab jump_loc(pos, jump_sline); 18128fd4165cSPaul Saab } 18131ede1615STim J. Robbins #else 18141ede1615STim J. Robbins error("Command not available", NULL_PARG); 18151ede1615STim J. Robbins #endif 18168fd4165cSPaul Saab break; 18178fd4165cSPaul Saab 18188fd4165cSPaul Saab case A_PREV_TAG: 1819b2ea2440SXin LI /* 1820b2ea2440SXin LI * Jump to the previous tag in the current tag list. 1821b2ea2440SXin LI */ 18221ede1615STim J. Robbins #if TAGS 18238fd4165cSPaul Saab if (number <= 0) 18248fd4165cSPaul Saab number = 1; 18251ede1615STim J. Robbins tagfile = prevtag((int) number); 18268fd4165cSPaul Saab if (tagfile == NULL) 18278fd4165cSPaul Saab { 18288fd4165cSPaul Saab error("No previous tag", NULL_PARG); 18298fd4165cSPaul Saab break; 18308fd4165cSPaul Saab } 1831b2ea2440SXin LI cmd_exec(); 18328fd4165cSPaul Saab if (edit(tagfile) == 0) 18338fd4165cSPaul Saab { 18348fd4165cSPaul Saab POSITION pos = tagsearch(); 18358fd4165cSPaul Saab if (pos != NULL_POSITION) 18368fd4165cSPaul Saab jump_loc(pos, jump_sline); 18378fd4165cSPaul Saab } 18381ede1615STim J. Robbins #else 18391ede1615STim J. Robbins error("Command not available", NULL_PARG); 18401ede1615STim J. Robbins #endif 18418fd4165cSPaul Saab break; 18428fd4165cSPaul Saab 1843a5f0fb15SPaul Saab case A_INDEX_FILE: 1844a5f0fb15SPaul Saab /* 1845a5f0fb15SPaul Saab * Examine a particular file. 1846a5f0fb15SPaul Saab */ 1847a5f0fb15SPaul Saab if (number <= 0) 1848a5f0fb15SPaul Saab number = 1; 18491ede1615STim J. Robbins if (edit_index((int) number)) 1850a5f0fb15SPaul Saab error("No such file", NULL_PARG); 1851a5f0fb15SPaul Saab break; 1852a5f0fb15SPaul Saab 1853a5f0fb15SPaul Saab case A_REMOVE_FILE: 1854b2ea2440SXin LI /* 1855b2ea2440SXin LI * Remove a file from the input file list. 1856b2ea2440SXin LI */ 1857a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1858a5f0fb15SPaul Saab break; 1859a5f0fb15SPaul Saab old_ifile = curr_ifile; 1860a5f0fb15SPaul Saab new_ifile = getoff_ifile(curr_ifile); 1861a5f0fb15SPaul Saab if (new_ifile == NULL_IFILE) 1862a5f0fb15SPaul Saab { 1863a5f0fb15SPaul Saab bell(); 1864a5f0fb15SPaul Saab break; 1865a5f0fb15SPaul Saab } 1866a5f0fb15SPaul Saab if (edit_ifile(new_ifile) != 0) 1867a5f0fb15SPaul Saab { 1868a5f0fb15SPaul Saab reedit_ifile(old_ifile); 1869a5f0fb15SPaul Saab break; 1870a5f0fb15SPaul Saab } 1871a5f0fb15SPaul Saab del_ifile(old_ifile); 1872a5f0fb15SPaul Saab break; 1873a5f0fb15SPaul Saab 1874a5f0fb15SPaul Saab case A_OPT_TOGGLE: 1875b2ea2440SXin LI /* 1876b2ea2440SXin LI * Change the setting of an option. 1877b2ea2440SXin LI */ 1878a5f0fb15SPaul Saab optflag = OPT_TOGGLE; 1879a5f0fb15SPaul Saab optgetname = FALSE; 1880a5f0fb15SPaul Saab mca_opt_toggle(); 1881a5f0fb15SPaul Saab c = getcc(); 18826f26c71dSXin LI cbuf = opt_toggle_disallowed(c); 18836f26c71dSXin LI if (cbuf != NULL) 18846f26c71dSXin LI { 18856f26c71dSXin LI error(cbuf, NULL_PARG); 18866f26c71dSXin LI break; 18876f26c71dSXin LI } 1888a5f0fb15SPaul Saab goto again; 1889a5f0fb15SPaul Saab 1890a5f0fb15SPaul Saab case A_DISP_OPTION: 1891a5f0fb15SPaul Saab /* 1892b2ea2440SXin LI * Report the setting of an option. 1893a5f0fb15SPaul Saab */ 1894a5f0fb15SPaul Saab optflag = OPT_NO_TOGGLE; 1895a5f0fb15SPaul Saab optgetname = FALSE; 1896a5f0fb15SPaul Saab mca_opt_toggle(); 1897a5f0fb15SPaul Saab c = getcc(); 1898a5f0fb15SPaul Saab goto again; 1899a5f0fb15SPaul Saab 1900a5f0fb15SPaul Saab case A_FIRSTCMD: 1901a5f0fb15SPaul Saab /* 1902a5f0fb15SPaul Saab * Set an initial command for new files. 1903a5f0fb15SPaul Saab */ 1904a5f0fb15SPaul Saab start_mca(A_FIRSTCMD, "+", (void*)NULL, 0); 1905a5f0fb15SPaul Saab c = getcc(); 1906a5f0fb15SPaul Saab goto again; 1907a5f0fb15SPaul Saab 1908a5f0fb15SPaul Saab case A_SHELL: 1909a5f0fb15SPaul Saab /* 1910a5f0fb15SPaul Saab * Shell escape. 1911a5f0fb15SPaul Saab */ 1912a5f0fb15SPaul Saab #if SHELL_ESCAPE 1913b2ea2440SXin LI if (!secure) 1914a5f0fb15SPaul Saab { 1915dd3bd0edSDimitry Andric start_mca(A_SHELL, "!", ml_shell, 0); 1916a5f0fb15SPaul Saab c = getcc(); 1917a5f0fb15SPaul Saab goto again; 1918b2ea2440SXin LI } 1919b2ea2440SXin LI #endif 1920a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 1921a5f0fb15SPaul Saab break; 1922a5f0fb15SPaul Saab 1923a5f0fb15SPaul Saab case A_SETMARK: 1924b2ea2440SXin LI case A_SETMARKBOT: 1925a5f0fb15SPaul Saab /* 1926a5f0fb15SPaul Saab * Set a mark. 1927a5f0fb15SPaul Saab */ 1928a5f0fb15SPaul Saab if (ch_getflags() & CH_HELPFILE) 1929a5f0fb15SPaul Saab break; 1930b2ea2440SXin LI start_mca(A_SETMARK, "set mark: ", (void*)NULL, 0); 1931a5f0fb15SPaul Saab c = getcc(); 1932b2ea2440SXin LI if (is_erase_char(c) || is_newline_char(c)) 1933a5f0fb15SPaul Saab break; 1934b2ea2440SXin LI setmark(c, action == A_SETMARKBOT ? BOTTOM : TOP); 1935b2ea2440SXin LI repaint(); 1936b2ea2440SXin LI break; 1937b2ea2440SXin LI 1938b2ea2440SXin LI case A_CLRMARK: 1939b2ea2440SXin LI /* 1940b2ea2440SXin LI * Clear a mark. 1941b2ea2440SXin LI */ 1942b2ea2440SXin LI start_mca(A_CLRMARK, "clear mark: ", (void*)NULL, 0); 1943b2ea2440SXin LI c = getcc(); 1944b2ea2440SXin LI if (is_erase_char(c) || is_newline_char(c)) 1945b2ea2440SXin LI break; 1946b2ea2440SXin LI clrmark(c); 1947b2ea2440SXin LI repaint(); 1948a5f0fb15SPaul Saab break; 1949a5f0fb15SPaul Saab 1950a5f0fb15SPaul Saab case A_GOMARK: 1951a5f0fb15SPaul Saab /* 1952b2ea2440SXin LI * Jump to a marked position. 1953a5f0fb15SPaul Saab */ 1954a5f0fb15SPaul Saab start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0); 1955a5f0fb15SPaul Saab c = getcc(); 1956b2ea2440SXin LI if (is_erase_char(c) || is_newline_char(c)) 1957a5f0fb15SPaul Saab break; 19587374caaaSXin LI cmd_exec(); 1959a5f0fb15SPaul Saab gomark(c); 1960a5f0fb15SPaul Saab break; 1961a5f0fb15SPaul Saab 1962a5f0fb15SPaul Saab case A_PIPE: 1963b2ea2440SXin LI /* 1964b2ea2440SXin LI * Write part of the input to a pipe to a shell command. 1965b2ea2440SXin LI */ 1966a5f0fb15SPaul Saab #if PIPEC 1967b2ea2440SXin LI if (!secure) 1968a5f0fb15SPaul Saab { 1969a5f0fb15SPaul Saab start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); 1970a5f0fb15SPaul Saab c = getcc(); 1971b2ea2440SXin LI if (is_erase_char(c)) 1972a5f0fb15SPaul Saab break; 1973b2ea2440SXin LI if (is_newline_char(c)) 1974a5f0fb15SPaul Saab c = '.'; 1975a5f0fb15SPaul Saab if (badmark(c)) 1976a5f0fb15SPaul Saab break; 1977a5f0fb15SPaul Saab pipec = c; 1978dd3bd0edSDimitry Andric start_mca(A_PIPE, "!", ml_shell, 0); 1979a5f0fb15SPaul Saab c = getcc(); 1980a5f0fb15SPaul Saab goto again; 1981b2ea2440SXin LI } 1982b2ea2440SXin LI #endif 1983a5f0fb15SPaul Saab error("Command not available", NULL_PARG); 1984a5f0fb15SPaul Saab break; 1985a5f0fb15SPaul Saab 1986a5f0fb15SPaul Saab case A_B_BRACKET: 1987a5f0fb15SPaul Saab case A_F_BRACKET: 1988a5f0fb15SPaul Saab start_mca(action, "Brackets: ", (void*)NULL, 0); 1989a5f0fb15SPaul Saab c = getcc(); 1990a5f0fb15SPaul Saab goto again; 1991a5f0fb15SPaul Saab 1992a5f0fb15SPaul Saab case A_LSHIFT: 1993b2ea2440SXin LI /* 1994b2ea2440SXin LI * Shift view left. 1995b2ea2440SXin LI */ 19968fd4165cSPaul Saab if (number > 0) 19978fd4165cSPaul Saab shift_count = number; 19988fd4165cSPaul Saab else 199915596da4SPaul Saab number = (shift_count > 0) ? 200015596da4SPaul Saab shift_count : sc_width / 2; 2001a5f0fb15SPaul Saab if (number > hshift) 2002a5f0fb15SPaul Saab number = hshift; 2003a5f0fb15SPaul Saab hshift -= number; 2004a5f0fb15SPaul Saab screen_trashed = 1; 2005a5f0fb15SPaul Saab break; 2006a5f0fb15SPaul Saab 2007a5f0fb15SPaul Saab case A_RSHIFT: 2008b2ea2440SXin LI /* 2009b2ea2440SXin LI * Shift view right. 2010b2ea2440SXin LI */ 20118fd4165cSPaul Saab if (number > 0) 20128fd4165cSPaul Saab shift_count = number; 20138fd4165cSPaul Saab else 201415596da4SPaul Saab number = (shift_count > 0) ? 201515596da4SPaul Saab shift_count : sc_width / 2; 2016a5f0fb15SPaul Saab hshift += number; 2017a5f0fb15SPaul Saab screen_trashed = 1; 2018a5f0fb15SPaul Saab break; 2019a5f0fb15SPaul Saab 2020f6b74a7dSXin LI case A_LLSHIFT: 2021b2ea2440SXin LI /* 2022b2ea2440SXin LI * Shift view left to margin. 2023b2ea2440SXin LI */ 2024f6b74a7dSXin LI hshift = 0; 2025f6b74a7dSXin LI screen_trashed = 1; 2026f6b74a7dSXin LI break; 2027f6b74a7dSXin LI 2028f6b74a7dSXin LI case A_RRSHIFT: 2029b2ea2440SXin LI /* 2030b2ea2440SXin LI * Shift view right to view rightmost char on screen. 2031b2ea2440SXin LI */ 2032f6b74a7dSXin LI hshift = rrshift(); 2033f6b74a7dSXin LI screen_trashed = 1; 2034f6b74a7dSXin LI break; 2035f6b74a7dSXin LI 2036a5f0fb15SPaul Saab case A_PREFIX: 2037a5f0fb15SPaul Saab /* 2038a5f0fb15SPaul Saab * The command is incomplete (more chars are needed). 2039a5f0fb15SPaul Saab * Display the current char, so the user knows 2040a5f0fb15SPaul Saab * what's going on, and get another character. 2041a5f0fb15SPaul Saab */ 2042a5f0fb15SPaul Saab if (mca != A_PREFIX) 2043a5f0fb15SPaul Saab { 2044a5f0fb15SPaul Saab cmd_reset(); 2045a5f0fb15SPaul Saab start_mca(A_PREFIX, " ", (void*)NULL, 2046a5f0fb15SPaul Saab CF_QUIT_ON_ERASE); 2047a5f0fb15SPaul Saab (void) cmd_char(c); 2048a5f0fb15SPaul Saab } 2049a5f0fb15SPaul Saab c = getcc(); 2050a5f0fb15SPaul Saab goto again; 2051a5f0fb15SPaul Saab 2052a5f0fb15SPaul Saab case A_NOACTION: 2053a5f0fb15SPaul Saab break; 2054a5f0fb15SPaul Saab 2055a5f0fb15SPaul Saab default: 2056a5f0fb15SPaul Saab bell(); 2057a5f0fb15SPaul Saab break; 2058a5f0fb15SPaul Saab } 2059a5f0fb15SPaul Saab } 2060a5f0fb15SPaul Saab } 2061