To: vim_dev@googlegroups.com Subject: Patch 8.2.3993 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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\gH98765\q", "tx") + call assert_equal("98765", getline(1)) + call assert_equal("cc12345\gH98765\", @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 -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///