aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/getchar.c50
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]);