diff src/getchar.c @ 20727:5ffe112b1afd v8.2.0916

patch 8.2.0916: mapping with partly modifyOtherKeys code does not work Commit: https://github.com/vim/vim/commit/975a880a1389e8ce6dea8d66a7c109140b2f94ec Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jun 6 22:36:24 2020 +0200 patch 8.2.0916: mapping with partly modifyOtherKeys code does not work 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)
author Bram Moolenaar <Bram@vim.org>
date Sat, 06 Jun 2020 22:45:04 +0200
parents fbee68c6aab1
children e3078150144d
line wrap: on
line diff
--- 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