diff options
author | Trygve Aaberge <trygveaa@gmail.com> | 2022-10-14 12:08:24 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-10-14 12:08:24 +0100 |
commit | b9c09c118e951bc6ea2059941101939dc572b4ce (patch) | |
tree | f3b21a7091d0ddb14b735a4ce9a844ba6f1e66a1 /src | |
parent | ba43e76fcd5b2da57dbaa4d9a555793fe8ac344e (diff) | |
download | vim-git-b9c09c118e951bc6ea2059941101939dc572b4ce.tar.gz |
patch 9.0.0748: Kitty may send key without modifiers with CSI u codev9.0.0748
Problem: Kitty may send key without modifiers with CSI u code.
Solution: Handle CSI u code without modifiers. (Trygve Aaberge,
closes #11364)
Diffstat (limited to 'src')
-rw-r--r-- | src/term.c | 68 | ||||
-rw-r--r-- | src/testdir/test_termcodes.vim | 18 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 76 insertions, 12 deletions
diff --git a/src/term.c b/src/term.c index 197af265c..4feeee607 100644 --- a/src/term.c +++ b/src/term.c @@ -4807,6 +4807,28 @@ handle_version_response(int first, int *arg, int argc, char_u *tp) } /* + * Add "key" to "buf" and return the number of bytes used. + * Handles special keys and multi-byte characters. + */ + static int +add_key_to_buf(int key, char_u *buf) +{ + int idx = 0; + + if (IS_SPECIAL(key)) + { + buf[idx++] = K_SPECIAL; + buf[idx++] = KEY2TERMCAP0(key); + buf[idx++] = KEY2TERMCAP1(key); + } + else if (has_mbyte) + idx += (*mb_char2bytes)(key, buf + idx); + else + buf[idx++] = key; + return idx; +} + +/* * Handle a sequence with key and modifier, one of: * {lead}27;{modifier};{key}~ * {lead}{key};{modifier}u @@ -4824,7 +4846,6 @@ handle_key_with_modifier( { int key; int modifiers; - int new_slen; char_u string[MAX_KEY_CODE_LEN + 1]; seenModifyOtherKeys = TRUE; @@ -4842,18 +4863,33 @@ handle_key_with_modifier( modifiers = may_remove_shift_modifier(modifiers, key); // insert modifiers with KS_MODIFIER - new_slen = modifiers2keycode(modifiers, &key, string); + int new_slen = modifiers2keycode(modifiers, &key, string); - if (IS_SPECIAL(key)) - { - string[new_slen++] = K_SPECIAL; - string[new_slen++] = KEY2TERMCAP0(key); - string[new_slen++] = KEY2TERMCAP1(key); - } - else if (has_mbyte) - new_slen += (*mb_char2bytes)(key, string + new_slen); - else - string[new_slen++] = key; + // add the bytes for the key + new_slen += add_key_to_buf(key, string + new_slen); + + if (put_string_in_typebuf(offset, csi_len, string, new_slen, + buf, bufsize, buflen) == FAIL) + return -1; + return new_slen - csi_len + offset; +} + +/* + * Handle a sequence with key without a modifier: + * {lead}{key}u + * Returns the difference in length. + */ + static int +handle_key_without_modifier( + int *arg, + int csi_len, + int offset, + char_u *buf, + int bufsize, + int *buflen) +{ + char_u string[MAX_KEY_CODE_LEN + 1]; + int new_slen = add_key_to_buf(arg[0], string); if (put_string_in_typebuf(offset, csi_len, string, new_slen, buf, bufsize, buflen) == FAIL) @@ -5016,6 +5052,14 @@ handle_csi( csi_len, offset, buf, bufsize, buflen); } + // Key without modifier (bad Kitty may send this): + // {lead}{key}u + else if (argc == 1 && trail == 'u') + { + return len + handle_key_without_modifier(arg, + csi_len, offset, buf, bufsize, buflen); + } + // else: Unknown CSI sequence. We could drop it, but then the // user can't create a map for it. return 0; diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim index 12c5737ae..8bf2fe3c1 100644 --- a/src/testdir/test_termcodes.vim +++ b/src/testdir/test_termcodes.vim @@ -1992,6 +1992,11 @@ func GetEscCodeCSIu(key, modifier) return "\<Esc>[" .. key .. ';' .. mod .. 'u' endfunc +func GetEscCodeCSIuWithoutModifier(key) + let key = printf("%d", char2nr(a:key)) + return "\<Esc>[" .. key .. 'u' +endfunc + " This checks the CSI sequences when in modifyOtherKeys mode. " The mode doesn't need to be enabled, the codes are always detected. func RunTest_modifyOtherKeys(func) @@ -2080,6 +2085,19 @@ func Test_modifyOtherKeys_no_mapping() set timeoutlen& endfunc +func Test_CSIu_keys_without_modifiers() + " Escape sent as `CSI 27 u` should act as normal escape and not undo + call setline(1, 'a') + call feedkeys('a' .. GetEscCodeCSIuWithoutModifier("\e"), 'Lx!') + call assert_equal('n', mode()) + call assert_equal('a', getline(1)) + + " Tab sent as `CSI 9 u` should work + call setline(1, '') + call feedkeys('a' .. GetEscCodeCSIuWithoutModifier("\t") .. "\<Esc>", 'Lx!') + call assert_equal("\t", getline(1)) +endfunc + " Check that when DEC mouse codes are recognized a special key is handled. func Test_ignore_dec_mouse() silent !infocmp gnome >/dev/null 2>&1 diff --git a/src/version.c b/src/version.c index a6e3a5fd6..d09422b83 100644 --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 748, +/**/ 747, /**/ 746, |