Patch 8.2.3993
Problem:    When recording a change in Select mode the first typed character
            appears twice.
Solution:   When putting the character back into typeahead remove it from
            recorded characters. (closes #9462)
Files:      src/getchar.c, src/proto/getchar.pro, src/normal.c,
            src/testdir/test_registers.vim


*** ../vim-8.2.3992/src/getchar.c       2022-01-01 14:19:44.040353857 +0000
--- src/getchar.c       2022-01-03 13:34:38.078133995 +0000
***************
*** 242,247 ****
--- 242,263 ----
  }
  
  /*
+  * Delete "slen" bytes from the end of "buf".
+  * Only works when it was just added.
+  */
+     static void
+ delete_buff_tail(buffheader_T *buf, int slen)
+ {
+     int len = (int)STRLEN(buf->bh_curr->b_str);
+ 
+     if (len >= slen)
+     {
+       buf->bh_curr->b_str[len - slen] = NUL;
+       buf->bh_space += slen;
+     }
+ }
+ 
+ /*
   * Add number "n" to buffer "buf".
   */
      static void
***************
*** 1100,1111 ****
   * Can be used for a character obtained by vgetc() that needs to be put back.
   * Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to
   * the char.
   */
!     void
  ins_char_typebuf(int c, int modifier)
  {
      char_u    buf[MB_MAXBYTES + 4];
!     int               idx = 0;
  
      if (modifier != 0)
      {
--- 1116,1128 ----
   * Can be used for a character obtained by vgetc() that needs to be put back.
   * Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to
   * the char.
+  * Returns the length of what was inserted.
   */
!     int
  ins_char_typebuf(int c, int modifier)
  {
      char_u    buf[MB_MAXBYTES + 4];
!     int               len = 0;
  
      if (modifier != 0)
      {
***************
*** 1113,1131 ****
        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 + idx) + idx] = NUL;
      (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
  }
  
  /*
--- 1130,1152 ----
        buf[1] = KS_MODIFIER;
        buf[2] = modifier;
        buf[3] = NUL;
!       len = 3;
      }
      if (IS_SPECIAL(c))
      {
!       buf[len] = K_SPECIAL;
!       buf[len + 1] = K_SECOND(c);
!       buf[len + 2] = K_THIRD(c);
!       buf[len + 3] = NUL;
!       len += 3;
      }
      else
!     {
!       len += (*mb_char2bytes)(c, buf + len);
!       buf[len] = NUL;
!     }
      (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
+     return len;
  }
  
  /*
***************
*** 1302,1307 ****
--- 1323,1344 ----
  }
  
  /*
+  * Undo the last gotchars() for "len" bytes.  To be used when putting a typed
+  * character back into the typeahead buffer, thus gotchars() will be called
+  * again.
+  * Only affects recorded characters.
+  */
+     void
+ ungetchars(int len)
+ {
+     if (reg_recording != 0)
+     {
+       delete_buff_tail(&recordbuff, len);
+       last_recorded_len -= len;
+     }
+ }
+ 
+ /*
   * Sync undo.  Called when typed characters are obtained from the typeahead
   * buffer, or when a menu is used.
   * Do not sync:
*** ../vim-8.2.3992/src/proto/getchar.pro       2021-08-09 18:59:01.442811242 
+0100
--- src/proto/getchar.pro       2022-01-03 13:34:37.050135970 +0000
***************
*** 24,34 ****
  void stop_redo_ins(void);
  int noremap_keys(void);
  int ins_typebuf(char_u *str, int noremap, int offset, int nottyped, int 
silent);
! void ins_char_typebuf(int c, int modifier);
  int typebuf_changed(int tb_change_cnt);
  int typebuf_typed(void);
  int typebuf_maplen(void);
  void del_typebuf(int len, int offset);
  int save_typebuf(void);
  void save_typeahead(tasave_T *tp);
  void restore_typeahead(tasave_T *tp, int overwrite);
--- 24,35 ----
  void stop_redo_ins(void);
  int noremap_keys(void);
  int ins_typebuf(char_u *str, int noremap, int offset, int nottyped, int 
silent);
! int ins_char_typebuf(int c, int modifier);
  int typebuf_changed(int tb_change_cnt);
  int typebuf_typed(void);
  int typebuf_maplen(void);
  void del_typebuf(int len, int offset);
+ void ungetchars(int len);
  int save_typebuf(void);
  void save_typeahead(tasave_T *tp);
  void restore_typeahead(tasave_T *tp, int overwrite);
*** ../vim-8.2.3992/src/normal.c        2022-01-02 19:25:22.846078499 +0000
--- src/normal.c        2022-01-03 13:46:07.401043973 +0000
***************
*** 592,603 ****
            && VIsual_select
            && (vim_isprintc(c) || c == NL || c == CAR || c == K_KENTER))
      {
        // Fake a "c"hange command.  When "restart_edit" is set (e.g., because
        // 'insertmode' is set) fake a "d"elete command, Insert mode will
        // restart automatically.
        // Insert the typed character in the typeahead buffer, so that it can
        // be mapped in Insert mode.  Required for ":lmap" to work.
!       ins_char_typebuf(vgetc_char, vgetc_mod_mask);
        if (restart_edit != 0)
            c = 'd';
        else
--- 592,610 ----
            && VIsual_select
            && (vim_isprintc(c) || c == NL || c == CAR || c == K_KENTER))
      {
+       int len;
+ 
        // Fake a "c"hange command.  When "restart_edit" is set (e.g., because
        // 'insertmode' is set) fake a "d"elete command, Insert mode will
        // restart automatically.
        // Insert the typed character in the typeahead buffer, so that it can
        // be mapped in Insert mode.  Required for ":lmap" to work.
!       len = ins_char_typebuf(vgetc_char, vgetc_mod_mask);
! 
!       // When recording the character will be recorded again, remove the
!       // previously recording.
!       ungetchars(len);
! 
        if (restart_edit != 0)
            c = 'd';
        else
*** ../vim-8.2.3992/src/testdir/test_registers.vim      2021-09-14 
17:55:47.864129826 +0100
--- src/testdir/test_registers.vim      2022-01-03 13:45:29.945095158 +0000
***************
*** 197,202 ****
--- 197,213 ----
    endif
  endfunc
  
+ func Test_recording_with_select_mode()
+   new
+   call feedkeys("qacc12345\<Esc>gH98765\<Esc>q", "tx")
+   call assert_equal("98765", getline(1))
+   call assert_equal("cc12345\<Esc>gH98765\<Esc>", @a)
+   call setline(1, 'asdf')
+   normal! @a
+   call assert_equal("98765", getline(1))
+   bwipe!
+ endfunc
+ 
  " Test for executing the last used register (@)
  func Test_last_used_exec_reg()
    " Test for the @: command
*** ../vim-8.2.3992/src/version.c       2022-01-03 12:53:20.662699885 +0000
--- src/version.c       2022-01-03 13:30:06.186724806 +0000
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     3993,
  /**/

-- 
panic("Foooooooood fight!");
        -- In the kernel source aha1542.c, after detecting a bad segment list

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            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/20220103134835.91FF91C0A5B%40moolenaar.net.

Raspunde prin e-mail lui