diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-01-23 05:58:32 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2022-01-23 05:58:32 +0800 |
commit | 818456470c0ce0d463b0be82e9c35eb77cc65f19 (patch) | |
tree | 93eb2d32451041504585adf4189a692141c8aa1b | |
parent | 7717f38d3f81cc739ef2b37829558d3d9eba9591 (diff) | |
download | rneovim-818456470c0ce0d463b0be82e9c35eb77cc65f19.tar.gz rneovim-818456470c0ce0d463b0be82e9c35eb77cc65f19.tar.bz2 rneovim-818456470c0ce0d463b0be82e9c35eb77cc65f19.zip |
fix(input): put modifiers back into typeahead buffer when needed
-rw-r--r-- | src/nvim/getchar.c | 39 | ||||
-rw-r--r-- | src/nvim/globals.h | 2 | ||||
-rw-r--r-- | src/nvim/message.c | 4 | ||||
-rw-r--r-- | src/nvim/normal.c | 2 | ||||
-rw-r--r-- | src/nvim/terminal.c | 2 | ||||
-rw-r--r-- | test/functional/terminal/mouse_spec.lua | 30 |
6 files changed, 54 insertions, 25 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index f2b0b9a8a9..ef590adb3a 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -973,27 +973,35 @@ int ins_typebuf(char_u *str, int noremap, int offset, bool nottyped, bool silent * Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to * the char. */ -void ins_char_typebuf(int c) +void 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] = (char_u)K_SECOND(c); - buf[2] = (char_u)K_THIRD(c); + buf[1] = KS_MODIFIER; + buf[2] = (char_u)modifier; buf[3] = NUL; + idx = 3; + } + if (IS_SPECIAL(c)) { + buf[idx] = K_SPECIAL; + buf[idx + 1] = (char_u)K_SECOND(c); + buf[idx + 2] = (char_u)K_THIRD(c); + buf[idx + 3] = NUL; } else { - buf[utf_char2bytes(c, buf)] = NUL; - char_u *p = buf; - while (*p) { + char_u *p = buf + idx; + int char_len = utf_char2bytes(c, p); + // If the character contains K_SPECIAL bytes they need escaping. + for (int i = char_len; --i >= 0; p++) { if ((uint8_t)(*p) == K_SPECIAL) { - memmove(p + 3, p + 1, STRLEN(p + 1) + 1); + memmove(p + 3, p + 1, (size_t)i); *p++ = K_SPECIAL; *p++ = KS_SPECIAL; - *p++ = KE_FILLER; - } else { - p++; + *p = KE_FILLER; } } + *p = NUL; } (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); } @@ -1433,8 +1441,9 @@ int vgetc(void) mouse_row = old_mouse_row; mouse_col = old_mouse_col; } else { - mod_mask = 0x0; + mod_mask = 0; last_recorded_len = 0; + for (;;) { // this is done twice if there are modifiers bool did_inc = false; if (mod_mask) { // no mapping after modifier has been read @@ -1560,8 +1569,8 @@ int vgetc(void) if (!no_mapping && KeyTyped && !(State & TERM_FOCUS) && (mod_mask == MOD_MASK_ALT || mod_mask == MOD_MASK_META)) { mod_mask = 0; - ins_char_typebuf(c); - ins_char_typebuf(ESC); + ins_char_typebuf(c, 0); + ins_char_typebuf(ESC, 0); continue; } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 40c61d01b5..31a09b3969 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -127,7 +127,7 @@ typedef off_t off_T; // 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 // Cmdline_row is the row where the command line starts, just below the diff --git a/src/nvim/message.c b/src/nvim/message.c index 39b023132e..17ccef37f1 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1215,7 +1215,7 @@ void wait_return(int redraw) } else if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C) { // 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(c, mod_mask); do_redraw = true; // need a redraw even though there is // typeahead } @@ -3497,7 +3497,7 @@ int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfl } if (c == ':' && ex_cmd) { retval = dfltbutton; - ins_char_typebuf(':'); + ins_char_typebuf(':', 0); break; } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 2b5b47c0b3..c3b7e81d17 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1010,7 +1010,7 @@ static int normal_execute(VimState *state, int key) // 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(s->c); + ins_char_typebuf(s->c, mod_mask); if (restart_edit != 0) { s->c = 'd'; } else { diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 70a5c7aa08..a2d855244c 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1299,7 +1299,7 @@ static bool send_mouse_event(Terminal *term, int c) } end: - ins_char_typebuf(c); + ins_char_typebuf(c, mod_mask); return true; } diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua index 780a0b9b5a..6e2c851df7 100644 --- a/test/functional/terminal/mouse_spec.lua +++ b/test/functional/terminal/mouse_spec.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear, eq, eval = helpers.clear, helpers.eq, helpers.eval -local feed, nvim = helpers.feed, helpers.nvim +local feed, nvim, command = helpers.feed, helpers.nvim, helpers.command local feed_data = thelpers.feed_data describe(':terminal mouse', function() @@ -10,9 +10,9 @@ describe(':terminal mouse', function() before_each(function() clear() nvim('set_option', 'statusline', '==========') - nvim('command', 'highlight StatusLine cterm=NONE') - nvim('command', 'highlight StatusLineNC cterm=NONE') - nvim('command', 'highlight VertSplit cterm=NONE') + command('highlight StatusLine cterm=NONE') + command('highlight StatusLineNC cterm=NONE') + command('highlight VertSplit cterm=NONE') screen = thelpers.screen_setup() local lines = {} for i = 1, 30 do @@ -38,6 +38,26 @@ describe(':terminal mouse', function() eq('nt', eval('mode(1)')) end) + it('will exit focus and trigger Normal mode mapping on mouse click', function() + command('let g:got_leftmouse = 0') + command('nnoremap <LeftMouse> <Cmd>let g:got_leftmouse = 1<CR>') + eq('t', eval('mode(1)')) + eq(0, eval('g:got_leftmouse')) + feed('<LeftMouse>') + eq('nt', eval('mode(1)')) + eq(1, eval('g:got_leftmouse')) + end) + + it('will exit focus and trigger Normal mode mapping on mouse click with modifier', function() + command('let g:got_ctrl_leftmouse = 0') + command('nnoremap <C-LeftMouse> <Cmd>let g:got_ctrl_leftmouse = 1<CR>') + eq('t', eval('mode(1)')) + eq(0, eval('g:got_ctrl_leftmouse')) + feed('<C-LeftMouse>') + eq('nt', eval('mode(1)')) + eq(1, eval('g:got_ctrl_leftmouse')) + end) + it('will exit focus on <C-\\> + mouse-scroll', function() eq('t', eval('mode(1)')) feed('<C-\\>') @@ -180,7 +200,7 @@ describe(':terminal mouse', function() it('will forward mouse clicks to the program with the correct even if set nu', function() if helpers.pending_win32(pending) then return end - nvim('command', 'set number') + command('set number') -- When the display area such as a number is clicked, it returns to the -- normal mode. feed('<LeftMouse><3,0>') |