mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge pull request #17185 from zeertzjq/vim-8.2.3993
vim-patch:8.2.{3993,4002}: when recording a change in Select mode char appears twice
			
			
This commit is contained in:
		| @@ -284,9 +284,19 @@ static void add_buff(buffheader_T *const buf, const char *const s, ptrdiff_t sle | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /// Delete "slen" bytes from the end of "buf". | ||||||
|  * Add number "n" to buffer "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 += (size_t)slen; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Add number "n" to buffer "buf". | ||||||
| static void add_num_buff(buffheader_T *buf, long n) | static void add_num_buff(buffheader_T *buf, long n) | ||||||
| { | { | ||||||
|   char number[32]; |   char number[32]; | ||||||
| @@ -967,31 +977,31 @@ int ins_typebuf(char_u *str, int noremap, int offset, bool nottyped, bool silent | |||||||
|   return OK; |   return OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /// Put character "c" back into the typeahead buffer. | ||||||
|  * Put character "c" back into the typeahead buffer. | /// Can be used for a character obtained by vgetc() that needs to be put back. | ||||||
|  * 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 | ||||||
|  * Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to | /// the char. | ||||||
|  * the char. | /// @return the length of what was inserted | ||||||
|  */ | int ins_char_typebuf(int c, int modifier) | ||||||
| void ins_char_typebuf(int c, int modifier) |  | ||||||
| { | { | ||||||
|   char_u buf[MB_MAXBYTES + 4]; |   char_u buf[MB_MAXBYTES * 3 + 4]; | ||||||
|   int idx = 0; |   int len = 0; | ||||||
|   if (modifier != 0) { |   if (modifier != 0) { | ||||||
|     buf[0] = K_SPECIAL; |     buf[0] = K_SPECIAL; | ||||||
|     buf[1] = KS_MODIFIER; |     buf[1] = KS_MODIFIER; | ||||||
|     buf[2] = (char_u)modifier; |     buf[2] = (char_u)modifier; | ||||||
|     buf[3] = NUL; |     buf[3] = NUL; | ||||||
|     idx = 3; |     len = 3; | ||||||
|   } |   } | ||||||
|   if (IS_SPECIAL(c)) { |   if (IS_SPECIAL(c)) { | ||||||
|     buf[idx] = K_SPECIAL; |     buf[len] = K_SPECIAL; | ||||||
|     buf[idx + 1] = (char_u)K_SECOND(c); |     buf[len + 1] = (char_u)K_SECOND(c); | ||||||
|     buf[idx + 2] = (char_u)K_THIRD(c); |     buf[len + 2] = (char_u)K_THIRD(c); | ||||||
|     buf[idx + 3] = NUL; |     buf[len + 3] = NUL; | ||||||
|   } else { |   } else { | ||||||
|     char_u *p = buf + idx; |     char_u *p = buf + len; | ||||||
|     int char_len = utf_char2bytes(c, p); |     int char_len = utf_char2bytes(c, p); | ||||||
|  |     len += char_len; | ||||||
|     // If the character contains K_SPECIAL bytes they need escaping. |     // If the character contains K_SPECIAL bytes they need escaping. | ||||||
|     for (int i = char_len; --i >= 0; p++) { |     for (int i = char_len; --i >= 0; p++) { | ||||||
|       if ((uint8_t)(*p) == K_SPECIAL) { |       if ((uint8_t)(*p) == K_SPECIAL) { | ||||||
| @@ -999,11 +1009,13 @@ void ins_char_typebuf(int c, int modifier) | |||||||
|         *p++ = K_SPECIAL; |         *p++ = K_SPECIAL; | ||||||
|         *p++ = KS_SPECIAL; |         *p++ = KS_SPECIAL; | ||||||
|         *p = KE_FILLER; |         *p = KE_FILLER; | ||||||
|  |         len += 2; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     *p = NUL; |     *p = NUL; | ||||||
|   } |   } | ||||||
|   (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); |   (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); | ||||||
|  |   return len; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Return TRUE if the typeahead buffer was changed (while waiting for a | /// Return TRUE if the typeahead buffer was changed (while waiting for a | ||||||
| @@ -1163,6 +1175,18 @@ static void gotchars(const char_u *chars, size_t len) | |||||||
|   maptick++; |   maptick++; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// 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 -= (size_t)len; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Sync undo.  Called when typed characters are obtained from the typeahead |  * Sync undo.  Called when typed characters are obtained from the typeahead | ||||||
|  * buffer, or when a menu is used. |  * buffer, or when a menu is used. | ||||||
|   | |||||||
| @@ -1011,7 +1011,12 @@ static int normal_execute(VimState *state, int key) | |||||||
|     // restart automatically. |     // restart automatically. | ||||||
|     // Insert the typed character in the typeahead buffer, so that it can |     // Insert the typed character in the typeahead buffer, so that it can | ||||||
|     // be mapped in Insert mode.  Required for ":lmap" to work. |     // be mapped in Insert mode.  Required for ":lmap" to work. | ||||||
|     ins_char_typebuf(s->c, mod_mask); |     int len = ins_char_typebuf(s->c, mod_mask); | ||||||
|  |  | ||||||
|  |     // When recording the character will be recorded again, remove the | ||||||
|  |     // previously recording. | ||||||
|  |     ungetchars(len); | ||||||
|  |  | ||||||
|     if (restart_edit != 0) { |     if (restart_edit != 0) { | ||||||
|       s->c = 'd'; |       s->c = 'd'; | ||||||
|     } else { |     } else { | ||||||
|   | |||||||
| @@ -121,6 +121,17 @@ func Test_recording_esc_sequence() | |||||||
|   endif |   endif | ||||||
| endfunc | 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 (@) | " Test for executing the last used register (@) | ||||||
| func Test_last_used_exec_reg() | func Test_last_used_exec_reg() | ||||||
|   " Test for the @: command |   " Test for the @: command | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| " Tests for Unicode manipulations | " Tests for Unicode manipulations | ||||||
|   |   | ||||||
|  | source check.vim | ||||||
| source view_util.vim | source view_util.vim | ||||||
|  |  | ||||||
| " Visual block Insert adjusts for multi-byte char | " Visual block Insert adjusts for multi-byte char | ||||||
| @@ -148,4 +149,55 @@ func Test_print_overlong() | |||||||
|   bwipe! |   bwipe! | ||||||
| endfunc | 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 | " vim: shiftwidth=2 sts=2 expandtab | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 bfredl
					bfredl