Patch 8.1.2350
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)
Files:      runtime/doc/insert.txt, runtime/doc/cmdline.txt, src/edit.c,
            src/proto/edit.pro, src/term.c, src/proto/term.pro, src/getchar.c,
            src/proto/getchar.pro, src/testdir/test_termcodes.vim,
            src/ex_getln.c


*** ../vim-8.1.2349/runtime/doc/insert.txt      2019-10-20 18:17:08.367431701 
+0200
--- runtime/doc/insert.txt      2019-11-26 19:28:14.541539868 +0100
***************
*** 194,202 ****
                decimal, octal or hexadecimal value of a character
                |i_CTRL-V_digit|.
                The characters typed right after CTRL-V are not considered for
!               mapping.  {Vi: no decimal byte entry}
                Note: When CTRL-V is mapped (e.g., to paste text) you can
                often use CTRL-Q instead |i_CTRL-Q|.
  
                                                *i_CTRL-Q*
  CTRL-Q                Same as CTRL-V.
--- 193,208 ----
                decimal, octal or hexadecimal value of a character
                |i_CTRL-V_digit|.
                The characters typed right after CTRL-V are not considered for
!               mapping.
                Note: When CTRL-V is mapped (e.g., to paste text) you can
                often use CTRL-Q instead |i_CTRL-Q|.
+               When |modifyOtherKeys| is enabled then special Escape sequence
+               is converted back to what it was without |modifyOtherKeys|,
+               unless the Shift key is also pressed.
+ 
+                                               *i_CTRL-SHIFT-V*
+ CTRL-SHIFT-V  Works just like CTRL-V, unless |modifyOtherKeys| is active,
+               then it inserts the Escape sequence for a key with modifiers.
  
                                                *i_CTRL-Q*
  CTRL-Q                Same as CTRL-V.
*** ../vim-8.1.2349/runtime/doc/cmdline.txt     2019-09-09 18:35:28.119252725 
+0200
--- runtime/doc/cmdline.txt     2019-11-26 19:27:57.641739370 +0100
***************
*** 77,86 ****
--- 77,93 ----
                way as in Insert mode (see above, |i_CTRL-V|).
                Note: Under Windows CTRL-V is often mapped to paste text.
                Use CTRL-Q instead then.
+               When |modifyOtherKeys| is enabled then special Escape sequence
+               is converted back to what it was without |modifyOtherKeys|,
+               unless the Shift key is also pressed.
                                                        *c_CTRL-Q*
  CTRL-Q                Same as CTRL-V.  But with some terminals it is used for
                control flow, it doesn't work then.
  
+ CTRL-SHIFT-V                          *c_CTRL-SHIFT-V* *c_CTRL-SHIFT-Q*
+ CTRL-SHIFT-Q  Works just like CTRL-V, unless |modifyOtherKeys| is active,
+               then it inserts the Escape sequence for a key with modifiers.
+ 
                                                        *c_<Left>* *c_Left*
  <Left>                cursor left
                                                        *c_<Right>* *c_Right*
*** ../vim-8.1.2349/src/edit.c  2019-11-26 14:28:11.781313275 +0100
--- src/edit.c  2019-11-26 19:02:23.741606074 +0100
***************
*** 1531,1536 ****
--- 1531,1537 ----
  {
      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,1559 ****
--- 1555,1566 ----
  #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,1567 ****
--- 1569,1627 ----
  }
  
  /*
+  * 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.
   */
*** ../vim-8.1.2349/src/proto/edit.pro  2019-10-09 22:52:49.000043746 +0200
--- src/proto/edit.pro  2019-11-26 18:46:12.734060440 +0100
***************
*** 2,7 ****
--- 2,8 ----
  int edit(int cmdchar, int startln, long count);
  int ins_need_undo_get(void);
  void ins_redraw(int ready);
+ int decodeModifyOtherKeys(int c);
  void edit_putchar(int c, int highlight);
  char_u *prompt_text(void);
  int prompt_curpos_editable(void);
*** ../vim-8.1.2349/src/term.c  2019-11-21 22:14:14.357810945 +0100
--- src/term.c  2019-11-26 18:57:34.625375262 +0100
***************
*** 4277,4283 ****
  /*
   * Decode a modifier number as xterm provides it into MOD_MASK bits.
   */
!     static int
  decode_modifiers(int n)
  {
      int           code = n - 1;
--- 4277,4283 ----
  /*
   * Decode a modifier number as xterm provides it into MOD_MASK bits.
   */
!     int
  decode_modifiers(int n)
  {
      int           code = n - 1;
*** ../vim-8.1.2349/src/proto/term.pro  2019-11-21 22:14:14.357810945 +0100
--- src/proto/term.pro  2019-11-26 18:54:58.233056654 +0100
***************
*** 65,70 ****
--- 65,71 ----
  void del_termcode(char_u *name);
  void set_mouse_topline(win_T *wp);
  int is_mouse_topline(win_T *wp);
+ 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);
  void term_get_bg_color(char_u *r, char_u *g, char_u *b);
*** ../vim-8.1.2349/src/getchar.c       2019-11-22 20:55:22.403621863 +0100
--- src/getchar.c       2019-11-26 19:00:05.013542417 +0100
***************
*** 1525,1530 ****
--- 1525,1562 ----
  }
  
  /*
+  * Convert "c" plus "mod_mask" to merge the effect of modifyOtherKeys into the
+  * character.
+  */
+     int
+ merge_modifyOtherKeys(int c_arg)
+ {
+     int c = c_arg;
+ 
+     if (mod_mask & MOD_MASK_CTRL)
+     {
+       if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_'))
+       {
+           c &= 0x1f;
+           mod_mask &= ~MOD_MASK_CTRL;
+       }
+       else if (c == '6')
+       {
+           // CTRL-6 is equivalent to CTRL-^
+           c = 0x1e;
+           mod_mask &= ~MOD_MASK_CTRL;
+       }
+     }
+     if ((mod_mask & (MOD_MASK_META | MOD_MASK_ALT))
+           && c >= 0 && c <= 127)
+     {
+       c += 0x80;
+       mod_mask &= ~(MOD_MASK_META|MOD_MASK_ALT);
+     }
+     return c;
+ }
+ 
+ /*
   * Get the next input character.
   * Can return a special key or a multi-byte character.
   * Can return NUL when called recursively, use safe_vgetc() if that's not
***************
*** 1765,1794 ****
            }
  
            if (!no_reduce_keys)
-           {
                // A modifier was not used for a mapping, apply it to ASCII
                // keys.  Shift would already have been applied.
!               if (mod_mask & MOD_MASK_CTRL)
!               {
!                   if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_'))
!                   {
!                       c &= 0x1f;
!                       mod_mask &= ~MOD_MASK_CTRL;
!                   }
!                   else if (c == '6')
!                   {
!                       // CTRL-6 is equivalent to CTRL-^
!                       c = 0x1e;
!                       mod_mask &= ~MOD_MASK_CTRL;
!                   }
!               }
!               if ((mod_mask & (MOD_MASK_META | MOD_MASK_ALT))
!                       && c >= 0 && c <= 127)
!               {
!                   c += 0x80;
!                   mod_mask &= ~(MOD_MASK_META|MOD_MASK_ALT);
!               }
!           }
  
            break;
        }
--- 1797,1805 ----
            }
  
            if (!no_reduce_keys)
                // A modifier was not used for a mapping, apply it to ASCII
                // keys.  Shift would already have been applied.
!               c = merge_modifyOtherKeys(c);
  
            break;
        }
*** ../vim-8.1.2349/src/proto/getchar.pro       2019-09-15 21:00:51.362604284 
+0200
--- src/proto/getchar.pro       2019-11-26 18:59:10.113494756 +0100
***************
*** 37,42 ****
--- 37,43 ----
  void close_all_scripts(void);
  int using_script(void);
  void before_blocking(void);
+ int merge_modifyOtherKeys(int c_arg);
  int vgetc(void);
  int safe_vgetc(void);
  int plain_vgetc(void);
*** ../vim-8.1.2349/src/testdir/test_termcodes.vim      2019-11-26 
14:28:11.785313279 +0100
--- src/testdir/test_termcodes.vim      2019-11-26 19:21:32.395606616 +0100
***************
*** 1349,1351 ****
--- 1349,1396 ----
    call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 
8)
    call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
  endfunc
+ 
+ func Test_insert_literal()
+   set timeoutlen=10
+   new
+   " CTRL-V CTRL-X inserts a ^X
+   call feedkeys('a' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('X', '5') 
.. "\<Esc>", 'Lx!')
+   call assert_equal("\<C-X>", getline(1))
+ 
+   call setline(1, '')
+   call feedkeys('a' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('X', '5') 
.. "\<Esc>", 'Lx!')
+   call assert_equal("\<C-X>", getline(1))
+ 
+   " CTRL-SHIFT-V CTRL-X inserts escape sequencd
+   call setline(1, '')
+   call feedkeys('a' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('X', '5') 
.. "\<Esc>", 'Lx!')
+   call assert_equal("\<Esc>[88;5u", getline(1))
+ 
+   call setline(1, '')
+   call feedkeys('a' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('X', '5') 
.. "\<Esc>", 'Lx!')
+   call assert_equal("\<Esc>[27;5;88~", getline(1))
+ 
+   bwipe!
+   set timeoutlen&
+ endfunc
+ 
+ func Test_cmdline_literal()
+   set timeoutlen=10
+ 
+   " CTRL-V CTRL-Y inserts a ^Y
+   call feedkeys(':' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('Y', '5') 
.. "\<C-B>\"\<CR>", 'Lx!')
+   call assert_equal("\"\<C-Y>", @:)
+ 
+   call feedkeys(':' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('Y', '5') 
.. "\<C-B>\"\<CR>", 'Lx!')
+   call assert_equal("\"\<C-Y>", @:)
+ 
+   " CTRL-SHIFT-V CTRL-Y inserts escape sequencd
+   call feedkeys(':' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('Y', '5') 
.. "\<C-B>\"\<CR>", 'Lx!')
+   call assert_equal("\"\<Esc>[89;5u", @:)
+ 
+   call setline(1, '')
+   call feedkeys(':' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('Y', '5') 
.. "\<C-B>\"\<CR>", 'Lx!')
+   call assert_equal("\"\<Esc>[27;5;89~", @:)
+ 
+   set timeoutlen&
+ endfunc
*** ../vim-8.1.2349/src/ex_getln.c      2019-11-26 14:28:11.781313275 +0100
--- src/ex_getln.c      2019-11-26 19:13:29.857230642 +0100
***************
*** 2208,2225 ****
  
        case Ctrl_V:
        case Ctrl_Q:
-               ignore_drag_release = TRUE;
-               putcmdline('^', TRUE);
-               c = get_literal();          /* get next (two) character(s) */
-               do_abbr = FALSE;            /* don't do abbreviation now */
-               extra_char = NUL;
-               /* may need to remove ^ when composing char was typed */
-               if (enc_utf8 && utf_iscomposing(c) && !cmd_silent)
                {
!                   draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos);
!                   msg_putchar(' ');
!                   cursorcmd();
                }
                break;
  
  #ifdef FEAT_DIGRAPHS
--- 2208,2238 ----
  
        case Ctrl_V:
        case Ctrl_Q:
                {
!                   int  prev_mod_mask = mod_mask;
! 
!                   ignore_drag_release = TRUE;
!                   putcmdline('^', TRUE);
!                   c = get_literal();      // get next (two) character(s)
!                   do_abbr = FALSE;        // don't do abbreviation now
!                   extra_char = NUL;
!                   // may need to remove ^ when composing char was typed
!                   if (enc_utf8 && utf_iscomposing(c) && !cmd_silent)
!                   {
!                       draw_cmdline(ccline.cmdpos,
!                                               ccline.cmdlen - ccline.cmdpos);
!                       msg_putchar(' ');
!                       cursorcmd();
!                   }
! 
!                   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);
                }
+ 
                break;
  
  #ifdef FEAT_DIGRAPHS
*** ../vim-8.1.2349/src/version.c       2019-11-26 17:04:53.445152907 +0100
--- src/version.c       2019-11-26 19:28:26.545400388 +0100
***************
*** 739,740 ****
--- 739,742 ----
  {   /* Add new patch number below this line */
+ /**/
+     2350,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
126. You brag to all of your friends about your date Saturday night...but
     you don't tell them it was only in a chat room.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201911261833.xAQIXpmF019490%40masaka.moolenaar.net.

Raspunde prin e-mail lui