nano

nano with my custom patches
git clone git://bsandro.tech/nano
Log | Files | Refs | README | LICENSE

commit d69cd759cb0d2ed77aad6d8aa6bca76fe27981e0
parent f261a8aca51a23fce42e91791ea06d4deda62932
Author: Benno Schulenberg <bensberg@telfort.nl>
Date:   Mon, 24 Jan 2022 18:05:53 +0100

input: instead of moving waiting keycodes, just increment a pointer

When a large piece of text was pasted into nano, then the old way of
repeatedly moving the buffered text one more position toward the head
of the keystroke buffer would waste a lot of time.  With this change,
pasting the current NEWS file into a buffer goes down (on my machine)
from around 30 seconds to just 2.

This addresses https://savannah.gnu.org/bugs/?61822.
Reported-by: Radu Caragea <rcaragea@protonmail.com>

Problem existed in this form since version 1.3.6, commit 7483571f.

Diffstat:
Msrc/winio.c | 63+++++++++++++++++++++++++++++++--------------------------------
1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/src/winio.c b/src/winio.c @@ -44,6 +44,8 @@ static int *key_buffer = NULL; /* A buffer for the keystrokes that haven't been handled yet. */ +static int *nextcodes = NULL; + /* A pointer pointing at the next keycode in the keystroke buffer. */ static size_t waiting_codes = 0; /* The number of key codes waiting in the keystroke buffer. */ static int digit_count = 0; @@ -126,6 +128,7 @@ void run_macro(void) key_buffer[i] = macro_buffer[i]; waiting_codes = macro_length; + nextcodes = key_buffer; mute_modifiers = TRUE; } #endif /* !NANO_TINY */ @@ -244,6 +247,7 @@ void read_keys_from(WINDOW *win) /* Initiate the keystroke buffer, and save the keycode in it. */ key_buffer = nrealloc(key_buffer, sizeof(int)); + nextcodes = key_buffer; key_buffer[0] = input; waiting_codes = 1; @@ -281,6 +285,7 @@ void read_keys_from(WINDOW *win) /* Extend the keystroke buffer, and save the keycode at its end. */ key_buffer = nrealloc(key_buffer, ++waiting_codes * sizeof(int)); key_buffer[waiting_codes - 1] = input; + nextcodes = key_buffer; } /* Restore blocking-input mode. */ @@ -307,15 +312,17 @@ void put_back(int keycode) if (waiting_codes + 1 < waiting_codes) return; - /* Extend the keystroke buffer to make room for the extra keycode. */ - key_buffer = nrealloc(key_buffer, ++waiting_codes * sizeof(int)); - - /* If the keystroke buffer wasn't empty before, move all the - * existing content one step further away. */ - if (waiting_codes > 1) - memmove(key_buffer + 1, key_buffer, (waiting_codes - 1) * sizeof(int)); + /* If there is no room at the head of the keystroke buffer, make room. */ + if (nextcodes == key_buffer) { + key_buffer = nrealloc(key_buffer, (waiting_codes + 1) * sizeof(int)); + if (waiting_codes) + memmove(key_buffer + 1, key_buffer, waiting_codes * sizeof(int)); + nextcodes = key_buffer; + } else + nextcodes--; - *key_buffer = keycode; + *nextcodes = keycode; + waiting_codes++; } #ifdef ENABLE_NANORC @@ -334,22 +341,14 @@ void implant(const char *string) * code, or ERR if the keystroke buffer is still empty. */ int get_input(WINDOW *win) { - int input; - if (waiting_codes == 0 && win != NULL) read_keys_from(win); - if (waiting_codes == 0) + if (waiting_codes > 0) { + waiting_codes--; + return *(nextcodes++); + } else return ERR; - - /* Take the first code from the head of the keystroke buffer. */ - input = key_buffer[0]; - - /* If the buffer contains more codes, move them to the front. */ - if (--waiting_codes > 0) - memmove(key_buffer, key_buffer + 1, waiting_codes * sizeof(int)); - - return input; } /* Return the arrow-key code that corresponds to the given letter. @@ -838,13 +837,13 @@ int parse_escape_sequence(int starter) int keycode = 0; if (starter == 'O') - keycode = convert_SS3_sequence(key_buffer, waiting_codes, &consumed); + keycode = convert_SS3_sequence(nextcodes, waiting_codes, &consumed); else if (starter == '[') - keycode = convert_CSI_sequence(key_buffer, waiting_codes, &consumed); + keycode = convert_CSI_sequence(nextcodes, waiting_codes, &consumed); - /* Remove the consumed sequence bytes from the keystroke buffer. */ + /* Skip the consumed sequence elements. */ waiting_codes -= consumed; - memmove(key_buffer, key_buffer + consumed, waiting_codes * sizeof(int)); + nextcodes += consumed; return keycode; } @@ -962,14 +961,14 @@ int parse_kbinput(WINDOW *win) #endif #ifdef ENABLE_UTF8 else if (0xC0 <= keycode && keycode <= 0xFF && using_utf8()) { - while (waiting_codes && 0x80 <= *key_buffer && *key_buffer <= 0xBF) + while (waiting_codes && 0x80 <= nextcodes[0] && nextcodes[0] <= 0xBF) get_input(NULL); return FOREIGN_SEQUENCE; } #endif else if (keycode < 0x20 && !last_escape_was_alone) meta_key = TRUE; - } else if (waiting_codes == 0 || *key_buffer == ESC_CODE || + } else if (waiting_codes == 0 || nextcodes[0] == ESC_CODE || (keycode != 'O' && keycode != '[')) { if (!shifted_metas) keycode = tolower(keycode); @@ -979,8 +978,8 @@ int parse_kbinput(WINDOW *win) } else { escapes = 0; if (keycode == '[' && waiting_codes && - (('A' <= *key_buffer && *key_buffer <= 'D') || - ('a' <= *key_buffer && *key_buffer <= 'd'))) { + (('A' <= nextcodes[0] && nextcodes[0] <= 'D') || + ('a' <= nextcodes[0] && nextcodes[0] <= 'd'))) { /* An iTerm2/Eterm/rxvt double-escape sequence: Esc Esc [ X * for Option+arrow, or Esc Esc [ x for Shift+Alt+arrow. */ switch (get_input(NULL)) { @@ -995,7 +994,7 @@ int parse_kbinput(WINDOW *win) case 'd': shift_held = TRUE; return KEY_END; #endif } - } else if (waiting_codes && *key_buffer != ESC_CODE && + } else if (waiting_codes && nextcodes[0] != ESC_CODE && (keycode == '[' || keycode == 'O')) { keycode = parse_escape_sequence(keycode); meta_key = TRUE; @@ -1419,12 +1418,12 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *count) if (unicode == INVALID_DIGIT) { if (keycode == ESC_CODE) { get_input(NULL); - while (waiting_codes && 0x1F < *key_buffer && *key_buffer < 0x40) + while (waiting_codes && 0x1F < nextcodes[0] && nextcodes[0] < 0x40) get_input(NULL); - if (waiting_codes && 0x3F < *key_buffer && *key_buffer < 0x7F) + if (waiting_codes && 0x3F < nextcodes[0] && nextcodes[0] < 0x7F) get_input(NULL); } else if (0xC0 <= keycode && keycode <= 0xFF) - while (waiting_codes && 0x7F < *key_buffer && *key_buffer < 0xC0) + while (waiting_codes && 0x7F < nextcodes[0] && nextcodes[0] < 0xC0) get_input(NULL); }