patch 9.1.0227: Recording may still be wrong in Select mode

Commit: 
https://github.com/vim/vim/commit/ea95f1a5ad2455c7fd1eee2413ac7a3460ef4f8a
Author: zeertzjq <zeert...@outlook.com>
Date:   Fri Mar 29 10:11:42 2024 +0100

    patch 9.1.0227: Recording may still be wrong in Select mode
    
    Problem:  Recording may still be wrong in Select mode (after 8.2.3993).
    Solution: Make sure a character isn't split between two buffer blocks.
              (zeertzjq)
    
    closes: #14326
    
    Signed-off-by: zeertzjq <zeert...@outlook.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/getchar.c b/src/getchar.c
index 49a24f08b..179c50c8f 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1283,35 +1283,72 @@ del_typebuf(int len, int offset)
 
 /*
  * Write typed characters to script file.
- * If recording is on put the character in the recordbuffer.
+ * If recording is on put the character in the record buffer.
  */
     static void
 gotchars(char_u *chars, int len)
 {
     char_u             *s = chars;
-    int                        i;
-    static char_u      buf[4];
-    static int         buflen = 0;
+    size_t             i;
+    int                        c = NUL;
+    static int         prev_c = NUL;
+    static char_u      buf[MB_MAXBYTES * 3 + 4];
+    static size_t      buflen = 0;
+    static unsigned    pending = 0;
+    static int         in_special = FALSE;
+    static int         in_mbyte = FALSE;
     int                        todo = len;
 
-    while (todo--)
+    for (; todo--; prev_c = c)
     {
-       buf[buflen++] = *s++;
+       c = buf[buflen++] = *s++;
+       if (pending > 0)
+           pending--;
 
        // When receiving a special key sequence, store it until we have all
        // the bytes and we can decide what to do with it.
-       if (buflen == 1 && buf[0] == K_SPECIAL)
-           continue;
-       if (buflen == 2)
-           continue;
-       if (buflen == 3 && buf[1] == KS_EXTRA
-                      && (buf[2] == KE_FOCUSGAINED || buf[2] == KE_FOCUSLOST))
+       if ((pending == 0 || in_mbyte)
+               && (c == K_SPECIAL
+#ifdef FEAT_GUI
+                   || c == CSI
+#endif
+                  ))
        {
-           // Drop K_FOCUSGAINED and K_FOCUSLOST, they are not useful in a
-           // recording.
-           buflen = 0;
+           pending += 2;
+           if (!in_mbyte)
+               in_special = TRUE;
+       }
+
+       if (pending > 0)
            continue;
+
+       if (!in_mbyte)
+       {
+           if (in_special)
+           {
+               in_special = FALSE;
+               if (prev_c == KS_MODIFIER)
+                   // When receiving a modifier, wait for the modified key.
+                   continue;
+               c = TO_SPECIAL(prev_c, c);
+               if (c == K_FOCUSGAINED || c == K_FOCUSLOST)
+                   // Drop K_FOCUSGAINED and K_FOCUSLOST, they are not useful
+                   // in a recording.
+                   buflen = 0;
+           }
+           // When receiving a multibyte character, store it until we have all
+           // the bytes, so that it won't be split between two buffer blocks,
+           // and delete_buff_tail() will work properly.
+           pending = MB_BYTE2LEN_CHECK(c) - 1;
+           if (pending > 0)
+           {
+               in_mbyte = TRUE;
+               continue;
+           }
        }
+       else
+           // Stored all bytes of a multibyte character.
+           in_mbyte = FALSE;
 
        // Handle one byte at a time; no translation to be done.
        for (i = 0; i < buflen; ++i)
@@ -1326,6 +1363,7 @@ gotchars(char_u *chars, int len)
        }
        buflen = 0;
     }
+
     may_sync_undo();
 
 #ifdef FEAT_EVAL
diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim
index cb4cee7d9..cbe6fa680 100644
--- a/src/testdir/test_registers.vim
+++ b/src/testdir/test_registers.vim
@@ -209,6 +209,58 @@ func Test_recording_with_select_mode()
   bwipe!
 endfunc
 
+func Run_test_recording_with_select_mode_utf8()
+  new
+
+  " Test with different text lengths: 5, 7, 9, 11, 13, 15, to check that
+  " a character isn't split between two buffer blocks.
+  for s in ['12345', '口=口', '口口口', '口=口=口', '口口=口口', '口口口口口']
+    " 0x80 is K_SPECIAL
+    " 0x9B is CSI
+    " 哦: 0xE5 0x93 0xA6
+    " 洛: 0xE6 0xB4 0x9B
+    " 固: 0xE5 0x9B 0xBA
+    " 四: 0xE5 0x9B 0x9B
+    " 最: 0xE6 0x9C 0x80
+    " 倒: 0xE5 0x80 0x92
+    " 倀: 0xE5 0x80 0x80
+    for c in ['哦', '洛', '固', '四', '最', '倒', '倀']
+      call setline(1, 'asdf')
+      call feedkeys($"qacc{s}\<Esc>gH{c}\<Esc>q", "tx")
+      call assert_equal(c, getline(1))
+      call assert_equal($"cc{s}\<Esc>gH{c}\<Esc>", @a)
+      call setline(1, 'asdf')
+      normal! @a
+      call assert_equal(c, getline(1))
+
+      " Test with Shift modifier.
+      let shift_c = eval($'"\<S-{c}>"')
+      call setline(1, 'asdf')
+      call feedkeys($"qacc{s}\<Esc>gH{shift_c}\<Esc>q", "tx")
+      call assert_equal(c, getline(1))
+      call assert_equal($"cc{s}\<Esc>gH{shift_c}\<Esc>", @a)
+      call setline(1, 'asdf')
+      normal! @a
+      call assert_equal(c, getline(1))
+    endfor
+  endfor
+
+  bwipe!
+endfunc
+
+func Test_recording_with_select_mode_utf8()
+  call Run_test_recording_with_select_mode_utf8()
+endfunc
+
+" This must be done as one of the last tests, because it starts the GUI, which
+" cannot be undone.
+func Test_zz_recording_with_select_mode_utf8_gui()
+  CheckCanRunGui
+
+  gui -f
+  call Run_test_recording_with_select_mode_utf8()
+endfunc
+
 " Test for executing the last used register (@)
 func Test_last_used_exec_reg()
   " Test for the @: command
diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim
index 3bb745979..112b5a6e9 100644
--- a/src/testdir/test_utf8.vim
+++ b/src/testdir/test_utf8.vim
@@ -292,55 +292,4 @@ func Test_print_overlong()
   bwipe!
 endfunc
 
-func Test_recording_with_select_mode_utf8()
-  call Run_test_recording_with_select_mode_utf8()
-endfunc
-
-func Run_test_recording_with_select_mode_utf8()
-  new
-
-  " No escaping
-  call feedkeys("qacc12345\<Esc>gH哦\<Esc>q", "tx")
-  call assert_equal("哦", getline(1))
-  call assert_equal("cc12345\<Esc>gH哦\<Esc>", @a)
-  call setline(1, 'asdf')
-  normal! @a
-  call assert_equal("哦", getline(1))
-
-  " 固 is 0xE5 0x9B 0xBA where 0x9B is CSI
-  call feedkeys("qacc12345\<Esc>gH固\<Esc>q", "tx")
-  call assert_equal("固", getline(1))
-  call assert_equal("cc12345\<Esc>gH固\<Esc>", @a)
-  call setline(1, 'asdf')
-  normal! @a
-  call assert_equal("固", getline(1))
-
-  " 四 is 0xE5 0x9B 0x9B where 0x9B is CSI
-  call feedkeys("qacc12345\<Esc>gH四\<Esc>q", "tx")
-  call assert_equal("四", getline(1))
-  call assert_equal("cc12345\<Esc>gH四\<Esc>", @a)
-  call setline(1, 'asdf')
-  normal! @a
-  call assert_equal("四", getline(1))
-
-  " 倒 is 0xE5 0x80 0x92 where 0x80 is K_SPECIAL
-  call feedkeys("qacc12345\<Esc>gH倒\<Esc>q", "tx")
-  call assert_equal("倒", getline(1))
-  call assert_equal("cc12345\<Esc>gH倒\<Esc>", @a)
-  call setline(1, 'asdf')
-  normal! @a
-  call assert_equal("倒", getline(1))
-
-  bwipe!
-endfunc
-
-" This must be done as one of the last tests, because it starts the GUI, which
-" cannot be undone.
-func Test_zz_recording_with_select_mode_utf8_gui()
-  CheckCanRunGui
-
-  gui -f
-  call Run_test_recording_with_select_mode_utf8()
-endfunc
-
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index b56b6d38d..7acc24d0d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    227,
 /**/
     226,
 /**/

-- 
-- 
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 vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1rq8KK-00DM7O-Op%40256bit.org.

Raspunde prin e-mail lui