# HG changeset patch # User Bram Moolenaar # Date 1602080104 -7200 # Node ID 6c7e4db139a362c4030719833c5aedf94f0f066b # Parent 3ab7a6685179096a19b102d0c7d71d634d9181ca patch 8.2.1809: mapping some keys with Ctrl does not work properly Commit: https://github.com/vim/vim/commit/4e2114e988f5d8635f2ad748be3cafcc44289138 Author: Bram Moolenaar Date: Wed Oct 7 16:12:37 2020 +0200 patch 8.2.1809: mapping some keys with Ctrl does not work properly Problem: Mapping some keys with Ctrl does not work properly. Solution: For terminal, GTK and Motif handle "@", "^" and "_" codes. diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -1236,11 +1236,10 @@ key_press_event(GtkWidget *widget UNUSED } else { - // and mean the same thing, always use "H" - if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) - key = TOUPPER_ASC(key); - - // May remove the shift modifier if it's included in the key. + // Some keys need adjustment when the Ctrl modifier is used. + key = may_adjust_key_for_ctrl(modifiers, key); + + // May remove the Shift modifier if it's included in the key. modifiers = may_remove_shift_modifier(modifiers, key); len = mb_char2bytes(key, string); diff --git a/src/gui_x11.c b/src/gui_x11.c --- a/src/gui_x11.c +++ b/src/gui_x11.c @@ -956,6 +956,9 @@ gui_x11_key_hit_cb( { len = mb_char2bytes(key, string); + // Some keys need adjustment when the Ctrl modifier is used. + key = may_adjust_key_for_ctrl(modifiers, key); + // Remove the SHIFT modifier for keys where it's already included, // e.g., '(', '!' and '*'. modifiers = may_remove_shift_modifier(modifiers, key); diff --git a/src/misc2.c b/src/misc2.c --- a/src/misc2.c +++ b/src/misc2.c @@ -2947,6 +2947,32 @@ find_special_key( /* + * Some keys are used with Ctrl without Shift and are still expected to be + * mapped as if Shift was pressed: + * CTRL-2 is CTRL-@ + * CTRL-6 is CTRL-^ + * CTRL-- is CTRL-_ + * Also, and mean the same thing, always use "H". + * Returns the possibly adjusted key. + */ + int +may_adjust_key_for_ctrl(int modifiers, int key) +{ + if (modifiers & MOD_MASK_CTRL) + { + if (ASCII_ISALPHA(key)) + return TOUPPER_ASC(key); + if (key == '2') + return '@'; + if (key == '6') + return '^'; + if (key == '-') + return '_'; + } + return key; +} + +/* * Some keys already have Shift included, pass them as normal keys. * Not when Ctrl is also used, because and are different. * Also for and . diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -72,6 +72,7 @@ char_u *get_special_key_name(int c, int int trans_special(char_u **srcp, char_u *dst, int flags, int *did_simplify); int special_to_buf(int key, int modifiers, int keycode, char_u *dst); int find_special_key(char_u **srcp, int *modp, int flags, int *did_simplify); +int may_adjust_key_for_ctrl(int modifiers, int key); int may_remove_shift_modifier(int modifiers, int key); int extract_modifiers(int key, int *modp, int simplify, int *did_simplify); int find_special_key_in_table(int c); diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -4784,15 +4784,12 @@ handle_key_with_modifier( modifiers = decode_modifiers(arg[1]); + // Some keys need adjustment when the Ctrl modifier is used. + key = may_adjust_key_for_ctrl(modifiers, key); + // May remove the shift modifier if it's already included in the key. modifiers = may_remove_shift_modifier(modifiers, key); - // When used with Ctrl we always make a letter upper case, - // so that mapping and are the same. Typing - // also uses "H" but modifier is different. - if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) - key = TOUPPER_ASC(key); - // insert modifiers with KS_MODIFIER new_slen = modifiers2keycode(modifiers, &key, string); diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim --- a/src/testdir/test_termcodes.vim +++ b/src/testdir/test_termcodes.vim @@ -2103,6 +2103,24 @@ endfunc func Test_mapping_works_with_ctrl() call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5) call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5) + + new + set timeoutlen=10 + + " CTRL-@ actually produces the code for CTRL-2, which is converted + call RunTest_mapping_mods('', '2', function('GetEscCodeCSI27'), 5) + call RunTest_mapping_mods('', '2', function('GetEscCodeCSIu'), 5) + + " CTRL-^ actually produces the code for CTRL-6, which is converted + call RunTest_mapping_mods('', '6', function('GetEscCodeCSI27'), 5) + call RunTest_mapping_mods('', '6', function('GetEscCodeCSIu'), 5) + + " CTRL-_ actually produces the code for CTRL--, which is converted + call RunTest_mapping_mods('', '-', function('GetEscCodeCSI27'), 5) + call RunTest_mapping_mods('', '-', function('GetEscCodeCSIu'), 5) + + bwipe! + set timeoutlen& endfunc func Test_mapping_works_with_shift_ctrl() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1809, +/**/ 1808, /**/ 1807,