diff options
Diffstat (limited to 'command.c')
| -rw-r--r-- | command.c | 205 |
1 files changed, 150 insertions, 55 deletions
diff --git a/command.c b/command.c index 974185d6f044..327e3930f09b 100644 --- a/command.c +++ b/command.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2024 Mark Nudelman + * Copyright (C) 1984-2025 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -29,7 +29,7 @@ extern int sc_height; extern char *kent; extern int swindow; extern int jump_sline; -extern int quitting; +extern lbool quitting; extern int wscroll; extern int top_scroll; extern int ignore_eoi; @@ -37,6 +37,7 @@ extern int hshift; extern int bs_mode; extern int proc_backspace; extern int show_attn; +extern int chopline; extern POSITION highest_hilite; extern char *every_first_cmd; extern char version[]; @@ -47,6 +48,10 @@ extern void *ml_examine; extern int wheel_lines; extern int def_search_type; extern lbool search_wrapped; +extern int no_paste; +extern lbool pasting; +extern int no_edit_warn; +extern POSITION soft_eof; #if SHELL_ESCAPE || PIPEC extern void *ml_shell; #endif @@ -74,7 +79,7 @@ static int last_search_type; /* Type of last executed search */ static LINENUM number; /* The number typed by the user */ static long fraction; /* The fractional part of the number */ static struct loption *curropt; -static int opt_lower; +static lbool opt_lower; static int optflag; static lbool optgetname; static POSITION bottompos; @@ -83,6 +88,10 @@ static int save_bs_mode; static int save_proc_backspace; static int screen_trashed_value = 0; static lbool literal_char = FALSE; +static lbool ignoring_input = FALSE; +#if HAVE_TIME +static time_type ignoring_input_time; +#endif #if PIPEC static char pipec; #endif @@ -102,7 +111,7 @@ static void multi_search(constant char *pattern, int n, int silent); * This looks nicer if the command takes a long time before * updating the screen. */ -static void cmd_exec(void) +public void cmd_exec(void) { clear_attn(); clear_bot(); @@ -228,7 +237,7 @@ static void mca_opt_toggle(void) break; } forw_prompt = 0; - set_mlist(NULL, 0); + set_mlist(NULL, CF_OPTION); } /* @@ -237,7 +246,6 @@ static void mca_opt_toggle(void) static void exec_mca(void) { constant char *cbuf; - char *p; cmd_exec(); cbuf = get_cmdbuf(); @@ -254,6 +262,7 @@ static void exec_mca(void) case A_FILTER: search_type ^= SRCH_NO_MATCH; set_filter_pattern(cbuf, search_type); + soft_eof = NULL_POSITION; break; #endif case A_FIRSTCMD: @@ -280,7 +289,8 @@ static void exec_mca(void) match_brac(cbuf[1], cbuf[0], 0, (int) number); break; #if EXAMINE - case A_EXAMINE: + case A_EXAMINE: { + char *p; if (!secure_allow(SF_EXAMINE)) break; p = save(cbuf); @@ -290,7 +300,7 @@ static void exec_mca(void) /* If tag structure is loaded then clean it up. */ cleantags(); #endif - break; + break; } #endif #if SHELL_ESCAPE case A_SHELL: { @@ -413,16 +423,18 @@ static int mca_opt_nonfirst_char(char c) constant char *p; constant char *oname; lbool ambig; + struct loption *was_curropt; if (curropt != NULL) { - /* - * Already have a match for the name. - * Don't accept anything but erase/kill. - */ + /* Already have a match for the name. */ if (is_erase_char(c)) return (MCA_DONE); - return (MCA_MORE); + /* {{ Checking for TAB here is ugly. + * Also doesn't extend well -- can't do BACKTAB this way + * because it's a multichar sequence. }} */ + if (c != '\t') + return (MCA_MORE); } /* * Add char to cmd buffer and try to match @@ -431,26 +443,23 @@ static int mca_opt_nonfirst_char(char c) if (cmd_char(c) == CC_QUIT) return (MCA_DONE); p = get_cmdbuf(); - if (p == NULL) + if (p == NULL || p[0] == '\0') return (MCA_MORE); opt_lower = ASCII_IS_LOWER(p[0]); + was_curropt = curropt; curropt = findopt_name(&p, &oname, &ambig); if (curropt != NULL) { - /* - * Got a match. - * Remember the option and - * display the full option name. - */ - cmd_reset(); - mca_opt_toggle(); - for (p = oname; *p != '\0'; p++) + if (was_curropt == NULL) { - c = *p; - if (!opt_lower && ASCII_IS_LOWER(c)) - c = ASCII_TO_UPPER(c); - if (cmd_char(c) != CC_OK) - return (MCA_DONE); + /* + * Got a match. + * Remember the option and + * display the full option name. + */ + cmd_reset(); + mca_opt_toggle(); + cmd_setstring(oname, !opt_lower); } } else if (!ambig) { @@ -471,7 +480,7 @@ static int mca_opt_char(char c) * or one char of a long option name, * or one char of the option parameter. */ - if (curropt == NULL && len_cmdbuf() == 0) + if (curropt == NULL && cmdbuf_empty()) { int ret = mca_opt_first_char(c); if (ret != NO_MCA) @@ -522,7 +531,7 @@ static int mca_opt_char(char c) /* * Display a prompt appropriate for the option parameter. */ - start_mca(A_OPT_TOGGLE, opt_prompt(curropt), NULL, 0); + start_mca(A_OPT_TOGGLE, opt_prompt(curropt), NULL, CF_OPTION); return (MCA_MORE); } @@ -551,7 +560,7 @@ static int mca_search_char(char c) * * Toggle the PAST_EOF flag * @ Toggle the FIRST_FILE flag */ - if (len_cmdbuf() > 0 || literal_char) + if (!cmdbuf_empty() || literal_char) { literal_char = FALSE; return (NO_MCA); @@ -688,9 +697,13 @@ static int mca_char(char c) */ if (is_newline_char(c)) { - /* - * Execute the command. - */ + if (pasting && no_paste) + { + /* Ignore pasted input after (and including) the first newline */ + start_ignoring_input(); + return (MCA_MORE); + } + /* Execute the command. */ exec_mca(); return (MCA_DONE); } @@ -859,7 +872,7 @@ static void prompt(void) * If we've hit EOF on the last file and the -E flag is set, quit. */ if (get_quit_at_eof() == OPT_ONPLUS && - eof_displayed() && !(ch_getflags() & CH_HELPFILE) && + eof_displayed(FALSE) && !(ch_getflags() & CH_HELPFILE) && next_ifile(curr_ifile) == NULL_IFILE) quit(QUIT_OK); @@ -941,7 +954,7 @@ static void prompt(void) p = a; #endif load_line(p); - put_line(); + put_line(FALSE); } clear_eol(); } @@ -1015,14 +1028,14 @@ public void getcc_clear(void) static char getccu(void) { int c = 0; - while (c == 0 && !ABORT_SIGS()) + while (c == 0 && sigs == 0) { if (ungot == NULL) { /* Normal case: no ungotten chars. * Get char from the user. */ c = getchr(); - if (c < 0) return ('\0'); + if (c < 0) c = '\0'; } else { /* Ungotten chars available: @@ -1270,7 +1283,7 @@ static int forw_loop(int until_hilite) break; } make_display(); - forward(1, 0, 0); + forward(1, FALSE, FALSE, FALSE); } ignore_eoi = 0; ch_set_eof(); @@ -1286,6 +1299,46 @@ static int forw_loop(int until_hilite) } /* + * Ignore subsequent (pasted) input chars. + */ +public void start_ignoring_input() +{ + ignoring_input = TRUE; +#if HAVE_TIME + ignoring_input_time = get_time(); +#endif +} + +/* + * Stop ignoring input chars. + */ +public void stop_ignoring_input() +{ + ignoring_input = FALSE; + pasting = FALSE; +} + +/* + * Are we ignoring input chars? + */ +public lbool is_ignoring_input(int action) +{ + if (!ignoring_input) + return FALSE; + if (action == A_END_PASTE) + stop_ignoring_input(); +#if HAVE_TIME + if (get_time() >= ignoring_input_time + MAX_PASTE_IGNORE_SEC) + stop_ignoring_input(); +#endif + /* + * Don't ignore prefix chars so we can parse a full command + * (which might be A_END_PASTE). + */ + return (action != A_PREFIX); +} + +/* * Main command processor. * Accept and execute commands until a quit command. */ @@ -1302,7 +1355,9 @@ public void commands(void) PARG parg; IFILE old_ifile; IFILE new_ifile; +#if TAGS constant char *tagfile; +#endif search_type = SRCH_FORW; wscroll = (sc_height + 1) / 2; @@ -1392,11 +1447,14 @@ public void commands(void) * If the user backspaces past the start * of the line, abort the command. */ - if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0) + if (cmd_char(c) == CC_QUIT || cmdbuf_empty()) continue; cbuf = get_cmdbuf(); if (cbuf == NULL) - continue; + { + c = getcc(); + goto again; + } action = fcmd_decode(cbuf, &extra); } else { @@ -1426,8 +1484,16 @@ public void commands(void) if (action != A_PREFIX) cmd_reset(); + if (is_ignoring_input(action)) + continue; + switch (action) { + case A_START_PASTE: + if (no_paste) + start_ignoring_input(); + break; + case A_DIGIT: /* * First digit of a number. @@ -1451,7 +1517,7 @@ public void commands(void) cmd_exec(); if (show_attn) set_attnpos(bottompos); - forward((int) number, 0, 1); + forward((int) number, FALSE, TRUE, FALSE); break; case A_B_WINDOW: @@ -1468,10 +1534,12 @@ public void commands(void) if (number <= 0) number = get_swindow(); cmd_exec(); - backward((int) number, 0, 1); + backward((int) number, FALSE, TRUE, FALSE); break; case A_F_LINE: + case A_F_NEWLINE: + /* * Forward N (default 1) line. */ @@ -1480,17 +1548,18 @@ public void commands(void) cmd_exec(); if (show_attn == OPT_ONPLUS && number > 1) set_attnpos(bottompos); - forward((int) number, 0, 0); + forward((int) number, FALSE, FALSE, action == A_F_NEWLINE && !chopline); break; case A_B_LINE: + case A_B_NEWLINE: /* * Backward N (default 1) line. */ if (number <= 0) number = 1; cmd_exec(); - backward((int) number, 0, 0); + backward((int) number, FALSE, FALSE, action == A_B_NEWLINE && !chopline); break; case A_F_MOUSE: @@ -1498,7 +1567,7 @@ public void commands(void) * Forward wheel_lines lines. */ cmd_exec(); - forward(wheel_lines, 0, 0); + forward(wheel_lines, FALSE, FALSE, FALSE); break; case A_B_MOUSE: @@ -1506,7 +1575,7 @@ public void commands(void) * Backward wheel_lines lines. */ cmd_exec(); - backward(wheel_lines, 0, 0); + backward(wheel_lines, FALSE, FALSE, FALSE); break; case A_FF_LINE: @@ -1518,7 +1587,7 @@ public void commands(void) cmd_exec(); if (show_attn == OPT_ONPLUS && number > 1) set_attnpos(bottompos); - forward((int) number, 1, 0); + forward((int) number, TRUE, FALSE, FALSE); break; case A_BF_LINE: @@ -1528,7 +1597,7 @@ public void commands(void) if (number <= 0) number = 1; cmd_exec(); - backward((int) number, 1, 0); + backward((int) number, TRUE, FALSE, FALSE); break; case A_FF_SCREEN: @@ -1540,13 +1609,25 @@ public void commands(void) cmd_exec(); if (show_attn == OPT_ONPLUS) set_attnpos(bottompos); - forward((int) number, 1, 0); + forward((int) number, TRUE, FALSE, FALSE); + break; + + case A_BF_SCREEN: + /* + * Force backward one screen. + */ + if (number <= 0) + number = get_swindow(); + cmd_exec(); + backward((int) number, TRUE, FALSE, FALSE); break; case A_F_FOREVER: /* * Forward forever, ignoring EOF. */ + if (get_altfilename(curr_ifile) != NULL) + error("Warning: command may not work correctly when file is viewed via LESSOPEN", NULL_PARG); if (show_attn) set_attnpos(bottompos); newaction = forw_loop(0); @@ -1566,7 +1647,7 @@ public void commands(void) cmd_exec(); if (show_attn == OPT_ONPLUS) set_attnpos(bottompos); - forward(wscroll, 0, 0); + forward(wscroll, FALSE, FALSE, FALSE); break; case A_B_SCROLL: @@ -1577,7 +1658,7 @@ public void commands(void) if (number > 0) wscroll = (int) number; cmd_exec(); - backward(wscroll, 0, 0); + backward(wscroll, FALSE, FALSE, FALSE); break; case A_FREPAINT: @@ -1884,10 +1965,9 @@ public void commands(void) error("Cannot edit standard input", NULL_PARG); break; } - if (get_altfilename(curr_ifile) != NULL) + if (!no_edit_warn && get_altfilename(curr_ifile) != NULL) { - error("WARNING: This file was viewed via LESSOPEN", - NULL_PARG); + error("WARNING: This file was viewed via LESSOPEN", NULL_PARG); } start_mca(A_SHELL, "!", ml_shell, 0); /* @@ -1918,9 +1998,10 @@ public void commands(void) #endif if (number <= 0) number = 1; + cmd_exec(); if (edit_next((int) number)) { - if (get_quit_at_eof() && eof_displayed() && + if (get_quit_at_eof() && eof_displayed(FALSE) && !(ch_getflags() & CH_HELPFILE)) quit(QUIT_OK); parg.p_string = (number > 1) ? "(N-th) " : ""; @@ -1941,6 +2022,7 @@ public void commands(void) #endif if (number <= 0) number = 1; + cmd_exec(); if (edit_prev((int) number)) { parg.p_string = (number > 1) ? "(N-th) " : ""; @@ -2004,6 +2086,7 @@ public void commands(void) */ if (number <= 0) number = 1; + cmd_exec(); if (edit_index((int) number)) error("No such file", NULL_PARG); break; @@ -2016,6 +2099,7 @@ public void commands(void) break; old_ifile = curr_ifile; new_ifile = getoff_ifile(curr_ifile); + cmd_exec(); if (new_ifile == NULL_IFILE) { bell(); @@ -2085,7 +2169,18 @@ public void commands(void) * Set a mark. */ if (ch_getflags() & CH_HELPFILE) + { + if (ungot != NULL) + { + /* + * Probably from a lesskey file, in which case there + * is probably an ungotten letter from the "extra" string. + * Eat it so it is not interpreted as a command. + */ + (void) getcc(); + } break; + } start_mca(A_SETMARK, "set mark: ", NULL, 0); c = getcc(); if (is_erase_char(c) || is_newline_char(c)) |
