input: snip the recordmacro and runmacro keystrokes in a better way
When recording a macro over a laggy connection or on a slow, overloaded computer, several keystrokes could be recorded in one burst, and if any but the last of those keystrokes was the shortcut for `runmacro`, then running the macro would lead to an infinite loop and nano would hang. This new implementation of snipping the "last keystroke" will, however, snip *too many* keystrokes when several of them were recorded at once and `runmacro` or `recordmacro` was among them, resulting in a cropped and thus misrecorded macro. But... that's better than hanging. In general, though, the user should be slow and deliberate when recording a macro: waiting for nano to have processed the last keystroke before typing the next. This fixes https://savannah.gnu.org/bugs/?65649. The issue was reported by `correctmost`. Problem existed since version 2.9.0, since macros were introduced.
This commit is contained in:
parent
cb02937714
commit
c020d53e23
19
src/winio.c
19
src/winio.c
@ -79,6 +79,8 @@ static int *macro_buffer = NULL;
|
||||
/* A buffer where the recorded key codes are stored. */
|
||||
static size_t macro_length = 0;
|
||||
/* The current length of the macro. */
|
||||
static size_t milestone = 0;
|
||||
/* Where the last burst of recorded keystrokes started. */
|
||||
|
||||
/* Add the given code to the macro buffer. */
|
||||
void add_to_macrobuffer(int code)
|
||||
@ -88,15 +90,6 @@ void add_to_macrobuffer(int code)
|
||||
macro_buffer[macro_length - 1] = code;
|
||||
}
|
||||
|
||||
/* Remove the last key code plus any leading Esc codes from macro buffer. */
|
||||
void snip_last_keystroke(void)
|
||||
{
|
||||
if (macro_length > 0)
|
||||
macro_length--;
|
||||
while (macro_length > 0 && macro_buffer[macro_length - 1] == '\x1b')
|
||||
macro_length--;
|
||||
}
|
||||
|
||||
/* Start or stop the recording of keystrokes. */
|
||||
void record_macro(void)
|
||||
{
|
||||
@ -106,7 +99,8 @@ void record_macro(void)
|
||||
macro_length = 0;
|
||||
statusline(REMARK, _("Recording a macro..."));
|
||||
} else {
|
||||
snip_last_keystroke();
|
||||
/* Snip the keystroke that invoked this function. */
|
||||
macro_length = milestone;
|
||||
statusline(REMARK, _("Stopped recording"));
|
||||
}
|
||||
|
||||
@ -120,7 +114,7 @@ void run_macro(void)
|
||||
{
|
||||
if (recording) {
|
||||
statusline(AHEM, _("Cannot run macro while recording"));
|
||||
snip_last_keystroke();
|
||||
macro_length = milestone;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -280,6 +274,9 @@ void read_keys_from(WINDOW *frame)
|
||||
/* If we got a SIGWINCH, get out as the frame argument is no longer valid. */
|
||||
if (input == KEY_WINCH)
|
||||
return;
|
||||
|
||||
/* Remember where the recording of this keystroke (or burst of them) started. */
|
||||
milestone = macro_length;
|
||||
#endif
|
||||
|
||||
/* Read in any remaining key codes using non-blocking input. */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user