# HG changeset patch # User Bram Moolenaar # Date 1641320104 -3600 # Node ID 8d4b44cc324e4b0ce410dc3d0bbe4e9f4bb2431a # Parent 69550041276ca3142c4790ff9d5b03596c17f55a patch 8.2.4002: first char typed in Select mode can be wrong Commit: https://github.com/vim/vim/commit/6cac77016b1636e04073e8348b7cee02259ef928 Author: zeertzjq Date: Tue Jan 4 18:01:21 2022 +0000 patch 8.2.4002: first char typed in Select mode can be wrong Problem: First char typed in Select mode can be wrong. Solution: Escape special bytes in the input buffer. (closes https://github.com/vim/vim/issues/9469) diff --git a/src/getchar.c b/src/getchar.c --- a/src/getchar.c +++ b/src/getchar.c @@ -1121,7 +1121,7 @@ ins_typebuf( int ins_char_typebuf(int c, int modifier) { - char_u buf[MB_MAXBYTES + 4]; + char_u buf[MB_MAXBYTES * 3 + 4]; int len = 0; if (modifier != 0) @@ -1142,8 +1142,18 @@ ins_char_typebuf(int c, int modifier) } else { - len += (*mb_char2bytes)(c, buf + len); - buf[len] = NUL; + char_u *p = buf + len; + int char_len = (*mb_char2bytes)(c, p); +#ifdef FEAT_GUI + int save_gui_in_use = gui.in_use; + + gui.in_use = FALSE; +#endif + // if the character contains CSI or K_SPECIAL bytes they need escaping + len += fix_input_buffer(p, char_len); +#ifdef FEAT_GUI + gui.in_use = save_gui_in_use; +#endif } (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); return len; @@ -3644,7 +3654,6 @@ fix_input_buffer(char_u *buf, int len) p += 2; i -= 2; } -# ifndef MSWIN // When the GUI is not used CSI needs to be escaped. else if (!gui.in_use && p[0] == CSI) { @@ -3654,7 +3663,6 @@ fix_input_buffer(char_u *buf, int len) *p = (int)KE_CSI; len += 2; } -# endif else #endif if (p[0] == NUL || (p[0] == K_SPECIAL diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim --- a/src/testdir/test_utf8.vim +++ b/src/testdir/test_utf8.vim @@ -1,5 +1,6 @@ " Tests for Unicode manipulations +source check.vim source view_util.vim " Visual block Insert adjusts for multi-byte char @@ -206,4 +207,55 @@ 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\gH哦\q", "tx") + call assert_equal("哦", getline(1)) + call assert_equal("cc12345\gH哦\", @a) + call setline(1, 'asdf') + normal! @a + call assert_equal("哦", getline(1)) + + " 固 is 0xE5 0x9B 0xBA where 0x9B is CSI + call feedkeys("qacc12345\gH固\q", "tx") + call assert_equal("固", getline(1)) + call assert_equal("cc12345\gH固\", @a) + call setline(1, 'asdf') + normal! @a + call assert_equal("固", getline(1)) + + " 四 is 0xE5 0x9B 0x9B where 0x9B is CSI + call feedkeys("qacc12345\gH四\q", "tx") + call assert_equal("四", getline(1)) + call assert_equal("cc12345\gH四\", @a) + call setline(1, 'asdf') + normal! @a + call assert_equal("四", getline(1)) + + " 倒 is 0xE5 0x80 0x92 where 0x80 is K_SPECIAL + call feedkeys("qacc12345\gH倒\q", "tx") + call assert_equal("倒", getline(1)) + call assert_equal("cc12345\gH倒\", @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 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4002, +/**/ 4001, /**/ 4000,