diff src/getchar.c @ 20571:5995db0fe84a v8.2.0839

patch 8.2.0839: dropping modifier when putting a character back in typeahead Commit: https://github.com/vim/vim/commit/b42c0d54279b1fdb79652db0c84171e213458809 Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 29 22:41:41 2020 +0200 patch 8.2.0839: dropping modifier when putting a character back in typeahead Problem: Dropping modifier when putting a character back in typeahead. Solution: Add modifier to ins_char_typebuf(). (closes https://github.com/vim/vim/issues/6158)
author Bram Moolenaar <Bram@vim.org>
date Fri, 29 May 2020 22:45:05 +0200
parents a5a24d688e11
children 3609e842f822
line wrap: on
line diff
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1101,18 +1101,29 @@ ins_typebuf(
  * the char.
  */
     void
-ins_char_typebuf(int c)
+ins_char_typebuf(int c, int modifier)
 {
-    char_u	buf[MB_MAXBYTES + 1];
-    if (IS_SPECIAL(c))
+    char_u	buf[MB_MAXBYTES + 4];
+    int		idx = 0;
+
+    if (modifier != 0)
     {
 	buf[0] = K_SPECIAL;
-	buf[1] = K_SECOND(c);
-	buf[2] = K_THIRD(c);
+	buf[1] = KS_MODIFIER;
+	buf[2] = modifier;
 	buf[3] = NUL;
+	idx = 3;
+    }
+    if (IS_SPECIAL(c))
+    {
+	buf[idx] = K_SPECIAL;
+	buf[idx + 1] = K_SECOND(c);
+	buf[idx + 2] = K_THIRD(c);
+	buf[idx + 3] = NUL;
+	idx += 3;
     }
     else
-	buf[(*mb_char2bytes)(c, buf)] = NUL;
+	buf[(*mb_char2bytes)(c, buf + idx) + idx] = NUL;
     (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
 }
 
@@ -1640,8 +1651,11 @@ vgetc(void)
     }
     else
     {
-	mod_mask = 0x0;
+	mod_mask = 0;
+	vgetc_mod_mask = 0;
+	vgetc_char = 0;
 	last_recorded_len = 0;
+
 	for (;;)		// this is done twice if there are modifiers
 	{
 	    int did_inc = FALSE;
@@ -1835,9 +1849,15 @@ vgetc(void)
 	    }
 
 	    if (!no_reduce_keys)
+	    {
 		// A modifier was not used for a mapping, apply it to ASCII
 		// keys.  Shift would already have been applied.
+		// Remember the character and mod_mask from before, in some
+		// cases they are put back in the typeahead buffer.
+		vgetc_mod_mask = mod_mask;
+		vgetc_char = c;
 		c = merge_modifyOtherKeys(c);
+	    }
 
 	    break;
 	}
@@ -2192,7 +2212,7 @@ parse_queued_messages(void)
     // If the current window or buffer changed we need to bail out of the
     // waiting loop.  E.g. when a job exit callback closes the terminal window.
     if (curwin->w_id != old_curwin_id || curbuf->b_fnum != old_curbuf_fnum)
-	ins_char_typebuf(K_IGNORE);
+	ins_char_typebuf(K_IGNORE, 0);
 
     --entered;
 }