]> granicus.if.org Git - vim/commitdiff
patch 9.0.0748: Kitty may send key without modifiers with CSI u code v9.0.0748
authorTrygve Aaberge <trygveaa@gmail.com>
Fri, 14 Oct 2022 11:08:24 +0000 (12:08 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 14 Oct 2022 11:08:24 +0000 (12:08 +0100)
Problem:    Kitty may send key without modifiers with CSI u code.
Solution:   Handle CSI u code without modifiers. (Trygve Aaberge,
            closes #11364)

src/term.c
src/testdir/test_termcodes.vim
src/version.c

index 197af265cd661fef59fffbc4456f575c96ce9944..4feeee6077248fef6784d27c7a8efafac4fdc035 100644 (file)
@@ -4806,6 +4806,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}~
@@ -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;
index 12c5737ae4b338735c112833858bbfa23f9ec65c..8bf2fe3c1160975c2eee3c47cd088faa677c9a72 100644 (file)
@@ -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
index a6e3a5fd61e0758f7464c73b9114a4996b5d3393..d09422b83c9e8b87c0918b7ed718090f4b2705ab 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    748,
 /**/
     747,
 /**/