mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
fix(input): put modifiers back into typeahead buffer when needed
This commit is contained in:
parent
7717f38d3f
commit
818456470c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>')
|
||||
|
Loading…
Reference in New Issue
Block a user