diff src/edit.c @ 18717:14d2a210fab1 v8.1.2350

patch 8.1.2350: other text for CTRL-V in Insert mode with modifyOtherKeys Commit: https://github.com/vim/vim/commit/fc4ea2a72d36de1196a3ce17352e72f8fe90f4bb Author: Bram Moolenaar <Bram@vim.org> Date: Tue Nov 26 19:33:22 2019 +0100 patch 8.1.2350: other text for CTRL-V in Insert mode with modifyOtherKeys Problem: Other text for CTRL-V in Insert mode with modifyOtherKeys. Solution: Convert the Escape sequence back to key as if modifyOtherKeys is not set, and use CTRL-SHIFT-V to get the Escape sequence itself. (closes #5254)
author Bram Moolenaar <Bram@vim.org>
date Tue, 26 Nov 2019 19:45:04 +0100
parents ac08c7ad9d37
children 49b78d6465e5
line wrap: on
line diff
--- a/src/edit.c
+++ b/src/edit.c
@@ -1531,6 +1531,7 @@ ins_ctrl_v(void)
 {
     int		c;
     int		did_putchar = FALSE;
+    int		prev_mod_mask = mod_mask;
 
     /* may need to redraw when no more chars available now */
     ins_redraw(FALSE);
@@ -1554,6 +1555,12 @@ ins_ctrl_v(void)
 #ifdef FEAT_CMDL_INFO
     clear_showcmd();
 #endif
+
+    if ((c == ESC || c == CSI) && !(prev_mod_mask & MOD_MASK_SHIFT))
+	// Using CTRL-V: Change any modifyOtherKeys ESC sequence to a normal
+	// key.  Don't do this for CTRL-SHIFT-V.
+	c = decodeModifyOtherKeys(c);
+
     insert_special(c, FALSE, TRUE);
 #ifdef FEAT_RIGHTLEFT
     revins_chars++;
@@ -1562,6 +1569,59 @@ ins_ctrl_v(void)
 }
 
 /*
+ * After getting an ESC or CSI for a literal key: If the typeahead buffer
+ * contains a modifyOtherKeys sequence then decode it and return the result.
+ * Otherwise return "c".
+ * Note that this doesn't wait for characters, they must be in the typeahead
+ * buffer already.
+ */
+    int
+decodeModifyOtherKeys(int c)
+{
+    char_u  *p = typebuf.tb_buf + typebuf.tb_off;
+    int	    idx;
+    int	    form = 0;
+    int	    argidx = 0;
+    int	    arg[2] = {0, 0};
+
+    // Recognize:
+    // form 0: {lead}{key};{modifier}u
+    // form 1: {lead}27;{modifier};{key}~
+    if ((c == CSI || (c == ESC && *p == '[')) && typebuf.tb_len >= 4)
+    {
+	idx = (*p == '[');
+	if (p[idx] == '2' && p[idx + 1] == '7' && p[idx + 2] == ';')
+	{
+	    form = 1;
+	    idx += 3;
+	}
+	while (idx < typebuf.tb_len && argidx < 2)
+	{
+	    if (p[idx] == ';')
+		++argidx;
+	    else if (VIM_ISDIGIT(p[idx]))
+		arg[argidx] = arg[argidx] * 10 + (p[idx] - '0');
+	    else
+		break;
+	    ++idx;
+	}
+	if (idx < typebuf.tb_len
+		&& p[idx] == (form == 1 ? '~' : 'u')
+		&& argidx == 1)
+	{
+	    // Match, consume the code.
+	    typebuf.tb_off += idx + 1;
+	    typebuf.tb_len -= idx + 1;
+
+	    mod_mask = decode_modifiers(arg[!form]);
+	    c = merge_modifyOtherKeys(arg[form]);
+	}
+    }
+
+    return c;
+}
+
+/*
  * Put a character directly onto the screen.  It's not stored in a buffer.
  * Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
  */