Mercurial > vim
changeset 20571:5995db0fe84a v8.2.0839
patch 8.2.0839: dropping modifier when putting a character back in typeahead
Commit: https://github.com/vim/vim/commit/b42c0d54279b1fdb79652db0c84171e213458809
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri May 29 22:41:41 2020 +0200
patch 8.2.0839: dropping modifier when putting a character back in typeahead
Problem: Dropping modifier when putting a character back in typeahead.
Solution: Add modifier to ins_char_typebuf(). (closes https://github.com/vim/vim/issues/6158)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 29 May 2020 22:45:05 +0200 |
parents | c08ee6345092 |
children | 8dd549c6de33 |
files | src/getchar.c src/globals.h src/message.c src/normal.c src/proto/getchar.pro src/terminal.c src/testdir/test_messages.vim src/version.c |
diffstat | 8 files changed, 50 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/src/getchar.c +++ b/src/getchar.c @@ -1101,18 +1101,29 @@ ins_typebuf( * the char. */ void -ins_char_typebuf(int c) +ins_char_typebuf(int c, int modifier) { - char_u buf[MB_MAXBYTES + 1]; - if (IS_SPECIAL(c)) + char_u buf[MB_MAXBYTES + 4]; + int idx = 0; + + if (modifier != 0) { buf[0] = K_SPECIAL; - buf[1] = K_SECOND(c); - buf[2] = K_THIRD(c); + 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)] = NUL; + buf[(*mb_char2bytes)(c, buf + idx) + idx] = NUL; (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); } @@ -1640,8 +1651,11 @@ vgetc(void) } else { - mod_mask = 0x0; + mod_mask = 0; + vgetc_mod_mask = 0; + vgetc_char = 0; last_recorded_len = 0; + for (;;) // this is done twice if there are modifiers { int did_inc = FALSE; @@ -1835,9 +1849,15 @@ vgetc(void) } if (!no_reduce_keys) + { // A modifier was not used for a mapping, apply it to ASCII // keys. Shift would already have been applied. + // Remember the character and mod_mask from before, in some + // cases they are put back in the typeahead buffer. + vgetc_mod_mask = mod_mask; + vgetc_char = c; c = merge_modifyOtherKeys(c); + } break; } @@ -2192,7 +2212,7 @@ parse_queued_messages(void) // If the current window or buffer changed we need to bail out of the // waiting loop. E.g. when a job exit callback closes the terminal window. if (curwin->w_id != old_curwin_id || curbuf->b_fnum != old_curbuf_fnum) - ins_char_typebuf(K_IGNORE); + ins_char_typebuf(K_IGNORE, 0); --entered; }
--- a/src/globals.h +++ b/src/globals.h @@ -120,7 +120,12 @@ EXTERN int screen_Columns INIT(= 0); / * When vgetc() is called, it sets mod_mask to the set of modifiers that are * held down based on the MOD_MASK_* symbols that are read first. */ -EXTERN int mod_mask INIT(= 0x0); // current key modifiers +EXTERN int mod_mask INIT(= 0); // current key modifiers + +// The value of "mod_mask" and the unomdified character before calling +// merge_modifyOtherKeys(). +EXTERN int vgetc_mod_mask INIT(= 0); +EXTERN int vgetc_char INIT(= 0); /* * Cmdline_row is the row where the command line starts, just below the
--- a/src/message.c +++ b/src/message.c @@ -1258,7 +1258,7 @@ wait_return(int redraw) { // Put the character back in the typeahead buffer. Don't use the // stuff buffer, because lmaps wouldn't work. - ins_char_typebuf(c); + ins_char_typebuf(vgetc_char, vgetc_mod_mask); do_redraw = TRUE; // need a redraw even though there is // typeahead } @@ -3712,7 +3712,7 @@ do_dialog( if (c == ':' && ex_cmd) { retval = dfltbutton; - ins_char_typebuf(':'); + ins_char_typebuf(':', 0); break; }
--- a/src/normal.c +++ b/src/normal.c @@ -595,7 +595,7 @@ normal_cmd( // 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(c); + ins_char_typebuf(vgetc_char, vgetc_mod_mask); if (restart_edit != 0) c = 'd'; else
--- a/src/proto/getchar.pro +++ b/src/proto/getchar.pro @@ -25,7 +25,7 @@ int start_redo_ins(void); 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); +void ins_char_typebuf(int c, int modifier); int typebuf_changed(int tb_change_cnt); int typebuf_typed(void); int typebuf_maplen(void);
--- a/src/terminal.c +++ b/src/terminal.c @@ -3467,7 +3467,7 @@ term_channel_closed(channel_T *ch) redraw_statuslines(); // Need to break out of vgetc(). - ins_char_typebuf(K_IGNORE); + ins_char_typebuf(K_IGNORE, 0); typebuf_was_filled = TRUE; term = curbuf->b_term;
--- a/src/testdir/test_messages.vim +++ b/src/testdir/test_messages.vim @@ -2,6 +2,7 @@ source shared.vim source term_util.vim +source view_util.vim func Test_messages() let oldmore = &more @@ -305,4 +306,12 @@ func Test_null() endif endfunc +func Test_mapping_at_hit_return_prompt() + nnoremap <C-B> :echo "hit ctrl-b"<CR> + call feedkeys(":ls\<CR>", "xt") + call feedkeys("\<C-B>", "xt") + call assert_match('hit ctrl-b', Screenline(&lines - 1)) + nunmap <C-B> +endfunc + " vim: shiftwidth=2 sts=2 expandtab