1
1

tweaks: read keycodes from the keystroke buffer without copying them

Allocating and freeing memory for reading every single keycode
is a waste of time and effort.

This addresses https://savannah.gnu.org/bugs/?58806.
Этот коммит содержится в:
Benno Schulenberg 2020-08-10 07:39:29 +02:00
родитель 96bb8149e9
Коммит bdc856812f

Просмотреть файл

@ -293,27 +293,25 @@ void implant(const char *string)
} }
#endif #endif
/* Try to read the requested number of codes from the keystroke buffer. /* Try to read one code from the keystroke buffer.
* If the buffer is empty and win isn't NULL, try to read in more codes, * If the buffer is empty and win isn't NULL, try to read in more codes,
* and if the buffer is still empty then, return NULL. */ * and if the buffer is still empty then, return NULL. */
int *get_input(WINDOW *win, size_t count) int get_input(WINDOW *win)
{ {
int *input; int input;
if (key_buffer_len == 0 && win != NULL) if (key_buffer_len == 0 && win != NULL)
read_keys_from(win); read_keys_from(win);
if (key_buffer_len == 0) if (key_buffer_len == 0)
return NULL; return ERR;
/* Copy the requested codes from the head of the keystroke buffer. */ /* Take the first code from the head of the keystroke buffer. */
input = (int *)nmalloc(count * sizeof(int)); input = key_buffer[0];
memcpy(input, key_buffer, count * sizeof(int));
key_buffer_len -= count;
/* If the buffer still contains keystrokes, move them to the front. */ /* If the buffer contains more codes, move them to the front. */
if (key_buffer_len > 0) if (--key_buffer_len > 0)
memmove(key_buffer, key_buffer + count, key_buffer_len * sizeof(int)); memmove(key_buffer, key_buffer + 1, key_buffer_len * sizeof(int));
return input; return input;
} }
@ -903,19 +901,13 @@ int convert_to_control(int kbinput)
int parse_kbinput(WINDOW *win) int parse_kbinput(WINDOW *win)
{ {
static int escapes = 0; static int escapes = 0;
int *kbinput, keycode; int keycode;
meta_key = FALSE; meta_key = FALSE;
shift_held = FALSE; shift_held = FALSE;
/* Read in a character. */ /* Get one code from the input stream. */
kbinput = get_input(win, 1); keycode = get_input(win);
if (kbinput == NULL)
return ERR;
keycode = *kbinput;
free(kbinput);
if (keycode == ERR) if (keycode == ERR)
return ERR; return ERR;
@ -963,9 +955,7 @@ int parse_kbinput(WINDOW *win)
('a' <= *key_buffer && *key_buffer <= 'd'))) { ('a' <= *key_buffer && *key_buffer <= 'd'))) {
/* An iTerm2/Eterm/rxvt double-escape sequence: Esc Esc [ X /* An iTerm2/Eterm/rxvt double-escape sequence: Esc Esc [ X
* for Option+arrow, or Esc Esc [ x for Shift+Alt+arrow. */ * for Option+arrow, or Esc Esc [ x for Shift+Alt+arrow. */
kbinput = get_input(win, 1); keycode= get_input(NULL);
keycode = *kbinput;
free(kbinput);
switch (keycode) { switch (keycode) {
case 'A': return KEY_HOME; case 'A': return KEY_HOME;
case 'B': return KEY_END; case 'B': return KEY_END;
@ -1371,69 +1361,67 @@ long assemble_unicode(int symbol)
* multibyte sequence), or 2 (for an iTerm/Eterm/rxvt double Escape). */ * multibyte sequence), or 2 (for an iTerm/Eterm/rxvt double Escape). */
int *parse_verbatim_kbinput(WINDOW *win, size_t *count) int *parse_verbatim_kbinput(WINDOW *win, size_t *count)
{ {
int *kbinput; int keycode, *yield;
reveal_cursor = TRUE; reveal_cursor = TRUE;
linger_after_escape = TRUE; linger_after_escape = TRUE;
/* Read in the first code. */ /* Read in the first code. */
kbinput = get_input(win, 1); keycode = get_input(win);
linger_after_escape = FALSE; linger_after_escape = FALSE;
#ifndef NANO_TINY #ifndef NANO_TINY
/* When the window was resized, abort and return nothing. */ /* When the window was resized, abort and return nothing. */
if (*kbinput == KEY_WINCH) { if (keycode == KEY_WINCH) {
free(kbinput);
*count = 0; *count = 0;
return NULL; return NULL;
} }
#endif #endif
/* Reserve ample space for the possible result. */
yield = (int *)nmalloc(6 * sizeof(int));
*count = 1; *count = 1;
#ifdef ENABLE_UTF8 #ifdef ENABLE_UTF8
if (using_utf8()) { if (using_utf8()) {
/* If the first code is a valid Unicode starter digit (0 or 1), /* If the first code is a valid Unicode starter digit (0 or 1),
* commence Unicode input. Otherwise, put the code back. */ * commence Unicode input. Otherwise, put the code back. */
if (*kbinput == '0' || *kbinput == '1') { if (keycode == '0' || keycode == '1') {
long unicode = assemble_unicode(*kbinput); long unicode = assemble_unicode(keycode);
char *multibyte; char *multibyte;
int onebyte;
reveal_cursor = FALSE; reveal_cursor = FALSE;
while (unicode == PROCEED) { while (unicode == PROCEED) {
free(kbinput); keycode = get_input(win);
kbinput = get_input(win, 1); unicode = assemble_unicode(keycode);
unicode = assemble_unicode(*kbinput);
} }
/* Convert the Unicode value to a multibyte sequence. */ /* Convert the Unicode value to a multibyte sequence. */
multibyte = make_mbchar(unicode, (int *)count); multibyte = make_mbchar(unicode, (int *)count);
/* Insert the multibyte sequence into the input buffer. */ /* Change the multibyte character into a series of integers. */
for (size_t i = *count; i > 0 ; i--) { for (size_t i = 0; i < *count; i++)
onebyte = (unsigned char)multibyte[i - 1]; yield[i] = (int)multibyte[i];
put_back(onebyte);
}
free(multibyte); free(multibyte);
} else
put_back(*kbinput);
} else
#endif /* ENABLE_UTF8 */
/* Put back the first code. */
put_back(*kbinput);
free(kbinput); return yield;
}
}
#endif /* ENABLE_UTF8 */
yield[0] = keycode;
/* In case of an escape, take also a second code, as it might be another /* In case of an escape, take also a second code, as it might be another
* escape (on iTerm2/rxvt) or a control code (for M-Bsp and M-Enter). */ * escape (on iTerm2/rxvt) or a control code (for M-Bsp and M-Enter). */
if (key_buffer_len > 1 && *key_buffer == ESC_CODE) if (keycode == ESC_CODE && key_buffer_len > 0) {
yield[1] = get_input(NULL);
*count = 2; *count = 2;
}
return get_input(NULL, *count); return yield;
} }
/* Read in one control code, one character byte, or the leading escapes of /* Read in one control code, one character byte, or the leading escapes of