diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-03-29 17:50:55 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-29 17:50:55 +0800 |
commit | fc19ee01acc30bac371f5a56a97a5cdfe8094014 (patch) | |
tree | 8365314e0b46039ac69abb2b7ea5814a966e19ae /src | |
parent | d223a7cbd2a204fffeb220fb18dfede8f4ef3e1f (diff) | |
download | rneovim-fc19ee01acc30bac371f5a56a97a5cdfe8094014.tar.gz rneovim-fc19ee01acc30bac371f5a56a97a5cdfe8094014.tar.bz2 rneovim-fc19ee01acc30bac371f5a56a97a5cdfe8094014.zip |
vim-patch:9.1.0227: Recording may still be wrong in Select mode (#28092)
Problem: Recording may still be wrong in Select mode (after 8.2.3993).
Solution: Make sure a character isn't split between two buffer blocks.
(zeertzjq)
closes: vim/vim#14326
https://github.com/vim/vim/commit/ea95f1a5ad2455c7fd1eee2413ac7a3460ef4f8a
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/getchar.c | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index f68bd7098b..2a5b8b00d4 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1102,27 +1102,59 @@ void del_typebuf(int len, int offset) } /// Write typed characters to script file. -/// If recording is on put the character in the recordbuffer. +/// If recording is on put the character in the record buffer. static void gotchars(const uint8_t *chars, size_t len) FUNC_ATTR_NONNULL_ALL { const uint8_t *s = chars; - static uint8_t buf[4] = { 0 }; + int c = NUL; + static int prev_c = NUL; + static uint8_t buf[MB_MAXBYTES * 3 + 4] = { 0 }; static size_t buflen = 0; + static unsigned pending = 0; + static bool in_special = false; + static bool in_mbyte = false; size_t todo = len; - while (todo--) { - buf[buflen++] = *s++; + for (; todo--; prev_c = c) { + c = buf[buflen++] = *s++; + if (pending > 0) { + pending--; + } - // When receiving a special key sequence, store it until we have all - // the bytes and we can decide what to do with it. - if (buflen == 1 && buf[0] == K_SPECIAL) { - continue; + if ((pending == 0 || in_mbyte) && c == K_SPECIAL) { + pending += 2; + if (!in_mbyte) { + in_special = true; + } } - if (buflen == 2) { + + if (pending > 0) { continue; } + if (!in_mbyte) { + if (in_special) { + in_special = false; + if (prev_c == KS_MODIFIER) { + // When receiving a modifier, wait for the modified key. + continue; + } + c = TO_SPECIAL(prev_c, c); + } + // When receiving a multibyte character, store it until we have all + // the bytes, so that it won't be split between two buffer blocks, + // and delete_buff_tail() will work properly. + pending = MB_BYTE2LEN_CHECK(c) - 1; + if (pending > 0) { + in_mbyte = true; + continue; + } + } else { + // Stored all bytes of a multibyte character. + in_mbyte = false; + } + // Handle one byte at a time; no translation to be done. for (size_t i = 0; i < buflen; i++) { updatescript(buf[i]); |