summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-06-06 22:36:24 +0200
committerBram Moolenaar <Bram@vim.org>2020-06-06 22:36:24 +0200
commit975a880a1389e8ce6dea8d66a7c109140b2f94ec (patch)
tree64e2a6019a20c05e2b399f73e2f29f7cb20c0d49
parentadc17a5f9d207fd1623fd923457a46efc9214777 (diff)
patch 8.2.0916: mapping with partly modifyOtherKeys code does not workv8.2.0916
Problem: Mapping with partly modifyOtherKeys code does not work. Solution: If there is no mapping with a separate modifier include the modifier in the key and then try mapping again. (closes #6200)
-rw-r--r--src/edit.c2
-rw-r--r--src/getchar.c57
-rw-r--r--src/proto/getchar.pro2
-rw-r--r--src/proto/term.pro1
-rw-r--r--src/term.c4
-rw-r--r--src/testdir/test_termcodes.vim17
-rw-r--r--src/version.c2
7 files changed, 74 insertions, 11 deletions
diff --git a/src/edit.c b/src/edit.c
index 5252334ce5..dc0b45082d 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -1609,7 +1609,7 @@ decodeModifyOtherKeys(int c)
#endif
mod_mask = decode_modifiers(arg[!form]);
- c = merge_modifyOtherKeys(arg[form]);
+ c = merge_modifyOtherKeys(arg[form], &mod_mask);
}
}
diff --git a/src/getchar.c b/src/getchar.c
index fcfad9dc0f..de814ccc68 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1582,15 +1582,15 @@ updatescript(int c)
}
/*
- * Convert "c" plus "mod_mask" to merge the effect of modifyOtherKeys into the
+ * Convert "c" plus "modifiers" to merge the effect of modifyOtherKeys into the
* character.
*/
int
-merge_modifyOtherKeys(int c_arg)
+merge_modifyOtherKeys(int c_arg, int *modifiers)
{
int c = c_arg;
- if (mod_mask & MOD_MASK_CTRL)
+ if (*modifiers & MOD_MASK_CTRL)
{
if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_'))
c &= 0x1f;
@@ -1612,13 +1612,13 @@ merge_modifyOtherKeys(int c_arg)
c = DEL;
#endif
if (c != c_arg)
- mod_mask &= ~MOD_MASK_CTRL;
+ *modifiers &= ~MOD_MASK_CTRL;
}
- if ((mod_mask & (MOD_MASK_META | MOD_MASK_ALT))
+ if ((*modifiers & (MOD_MASK_META | MOD_MASK_ALT))
&& c >= 0 && c <= 127)
{
c += 0x80;
- mod_mask &= ~(MOD_MASK_META|MOD_MASK_ALT);
+ *modifiers &= ~(MOD_MASK_META|MOD_MASK_ALT);
}
return c;
}
@@ -1866,7 +1866,7 @@ vgetc(void)
// cases they are put back in the typeahead buffer.
vgetc_mod_mask = mod_mask;
vgetc_char = c;
- c = merge_modifyOtherKeys(c);
+ c = merge_modifyOtherKeys(c, &mod_mask);
}
break;
@@ -2255,6 +2255,44 @@ at_ctrl_x_key(void)
}
/*
+ * Check if typebuf.tb_buf[] contains a modifer plus key that can be changed
+ * into just a key, apply that.
+ * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off
+ * + "max_offset"].
+ * Return the length of the replaced bytes, zero if nothing changed.
+ */
+ static int
+check_simplify_modifier(int max_offset)
+{
+ int offset;
+ char_u *tp;
+
+ for (offset = 0; offset < max_offset; ++offset)
+ {
+ if (offset + 3 >= typebuf.tb_len)
+ break;
+ tp = typebuf.tb_buf + typebuf.tb_off + offset;
+ if (tp[0] == K_SPECIAL && tp[1] == KS_MODIFIER)
+ {
+ int modifier = tp[2];
+ int new_c = merge_modifyOtherKeys(tp[3], &modifier);
+
+ if (new_c != tp[3] && modifier == 0)
+ {
+ char_u new_string[MB_MAXBYTES];
+ int len = mb_char2bytes(new_c, new_string);
+
+ if (put_string_in_typebuf(offset, 4, new_string, len,
+ NULL, 0, 0) == FAIL)
+ return -1;
+ return len;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
* Handle mappings in the typeahead buffer.
* - When something was mapped, return map_result_retry for recursive mappings.
* - When nothing mapped and typeahead has a character: return map_result_get.
@@ -2519,6 +2557,11 @@ handle_mapping(
if (keylen == 0 && save_keylen == KEYLEN_PART_KEY)
keylen = KEYLEN_PART_KEY;
+ // If no termcode matched, try to include the modifier into the
+ // key. This for when modifyOtherKeys is working.
+ if (keylen == 0)
+ keylen = check_simplify_modifier(max_mlen + 1);
+
// When getting a partial match, but the last characters were not
// typed, don't wait for a typed character to complete the
// termcode. This helps a lot when a ":normal" command ends in an
diff --git a/src/proto/getchar.pro b/src/proto/getchar.pro
index 57d78b594e..bf131a5ace 100644
--- a/src/proto/getchar.pro
+++ b/src/proto/getchar.pro
@@ -37,7 +37,7 @@ void openscript(char_u *name, int directly);
void close_all_scripts(void);
int using_script(void);
void before_blocking(void);
-int merge_modifyOtherKeys(int c_arg);
+int merge_modifyOtherKeys(int c_arg, int *modifiers);
int vgetc(void);
int safe_vgetc(void);
int plain_vgetc(void);
diff --git a/src/proto/term.pro b/src/proto/term.pro
index d84823cc66..88fdcb89f7 100644
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -68,6 +68,7 @@ int get_termcode_len(int idx);
void del_termcode(char_u *name);
void set_mouse_topline(win_T *wp);
int is_mouse_topline(win_T *wp);
+int put_string_in_typebuf(int offset, int slen, char_u *string, int new_slen, char_u *buf, int bufsize, int *buflen);
int decode_modifiers(int n);
int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen);
void term_get_fg_color(char_u *r, char_u *g, char_u *b);
diff --git a/src/term.c b/src/term.c
index b4b5c091a8..70822195b0 100644
--- a/src/term.c
+++ b/src/term.c
@@ -4251,7 +4251,7 @@ is_mouse_topline(win_T *wp)
* Remove "slen" bytes.
* Returns FAIL for error.
*/
- static int
+ int
put_string_in_typebuf(
int offset,
int slen,
@@ -4342,7 +4342,7 @@ modifiers2keycode(int modifiers, int *key, char_u *string)
/*
* Check if typebuf.tb_buf[] contains a terminal key code.
* Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off
- * + max_offset].
+ * + "max_offset"].
* Return 0 for no match, -1 for partial match, > 0 for full match.
* Return KEYLEN_REMOVED when a key code was deleted.
* With a match, the match is removed, the replacement code is inserted in
diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim
index 49262f529b..86589b28d0 100644
--- a/src/testdir/test_termcodes.vim
+++ b/src/testdir/test_termcodes.vim
@@ -1222,6 +1222,23 @@ func RunTest_mapping_shift(key, func)
endif
endfunc
+func Test_modifyOtherKeys_mapped()
+ set timeoutlen=10
+ imap ' <C-W>
+ imap <C-W><C-A> c-a
+ call setline(1, '')
+
+ " single quote is turned into single byte CTRL-W
+ " CTRL-A is added with a separate modifier, and needs to be simplified before
+ " the mapping can match.
+ call feedkeys("a'" .. GetEscCodeCSI27('A', 5) .. "\<Esc>", 'Lx!')
+ call assert_equal('c-a', getline(1))
+
+ iunmap '
+ iunmap <C-W><C-A>
+ set timeoutlen&
+endfunc
+
func RunTest_mapping_works_with_shift(func)
new
set timeoutlen=10
diff --git a/src/version.c b/src/version.c
index 965877dbf0..6466000f52 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 916,
+/**/
915,
/**/
914,