diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/getchar.c | 16 | ||||
-rw-r--r-- | src/nvim/normal.c | 9 | ||||
-rw-r--r-- | src/nvim/regexp.c | 11 | ||||
-rw-r--r-- | src/nvim/testdir/test_mapping.vim | 34 |
4 files changed, 62 insertions, 8 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 669d181364..eddd5ccd14 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1253,7 +1253,14 @@ static int old_mod_mask; // mod_mask for ungotten character static int old_mouse_grid; // mouse_grid related to old_char static int old_mouse_row; // mouse_row related to old_char static int old_mouse_col; // mouse_col related to old_char +static int old_KeyStuffed; // whether old_char was stuffed +static bool can_get_old_char(void) +{ + // If the old character was not stuffed and characters have been added to + // the stuff buffer, need to first get the stuffed characters instead. + return old_char != -1 && (old_KeyStuffed || stuff_empty()); +} /* * Save all three kinds of typeahead, so that the user must type at a prompt. @@ -1454,7 +1461,7 @@ int vgetc(void) * If a character was put back with vungetc, it was already processed. * Return it directly. */ - if (old_char != -1) { + if (can_get_old_char()) { c = old_char; old_char = -1; mod_mask = old_mod_mask; @@ -1660,7 +1667,7 @@ int plain_vgetc(void) */ int vpeekc(void) { - if (old_char != -1) { + if (can_get_old_char()) { return old_char; } return vgetorpeek(false); @@ -2052,7 +2059,9 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth) return map_result_nomatch; } -// unget one character (can only be done once!) +/// unget one character (can only be done once!) +/// If the character was stuffed, vgetc() will get it next time it was called. +/// Otherwise vgetc() will only get it when the stuff buffer is empty. void vungetc(int c) { old_char = c; @@ -2060,6 +2069,7 @@ void vungetc(int c) old_mouse_grid = mouse_grid; old_mouse_row = mouse_row; old_mouse_col = mouse_col; + old_KeyStuffed = KeyStuffed; } /// Gets a byte: diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 5e46bd468d..9cee2de0c5 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1517,9 +1517,12 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) for (;;) { which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag); if (is_drag) { - /* If the next character is the same mouse event then use that - * one. Speeds up dragging the status line. */ - if (vpeekc() != NUL) { + // If the next character is the same mouse event then use that + // one. Speeds up dragging the status line. + // Note: Since characters added to the stuff buffer in the code + // below need to come before the next character, do not do this + // when the current character was stuffed. + if (!KeyStuffed && vpeekc() != NUL) { int nc; int save_mouse_grid = mouse_grid; int save_mouse_row = mouse_row; diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 9a04cc428a..b61c9a2cf5 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -2504,7 +2504,8 @@ long vim_regexec_multi( char_u *pat = vim_strsave(((nfa_regprog_T *)rmp->regprog)->pattern); p_re = BACKTRACKING_ENGINE; - vim_regfree(rmp->regprog); + regprog_T *prev_prog = rmp->regprog; + report_re_switch(pat); // checking for \z misuse was already done when compiling for NFA, // allow all here @@ -2512,7 +2513,13 @@ long vim_regexec_multi( rmp->regprog = vim_regcomp(pat, re_flags); reg_do_extmatch = 0; - if (rmp->regprog != NULL) { + if (rmp->regprog == NULL) { + // Somehow compiling the pattern failed now, put back the + // previous one to avoid "regprog" becoming NULL. + rmp->regprog = prev_prog; + } else { + vim_regfree(prev_prog); + rmp->regprog->re_in_use = true; result = rmp->regprog->engine->regexec_multi(rmp, win, buf, lnum, col, tm, timed_out); diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim index 98440ccdd7..a8dd0ca286 100644 --- a/src/nvim/testdir/test_mapping.vim +++ b/src/nvim/testdir/test_mapping.vim @@ -676,4 +676,38 @@ func Test_plug_remap() %bw! endfunc +" Test for mapping <LeftDrag> in Insert mode +func Test_mouse_drag_insert_map() + CheckFunction test_setmouse + set mouse=a + func ClickExpr() + call test_setmouse(1, 1) + return "\<LeftMouse>" + endfunc + func DragExpr() + call test_setmouse(1, 2) + return "\<LeftDrag>" + endfunc + inoremap <expr> <F2> ClickExpr() + imap <expr> <F3> DragExpr() + + inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR> + exe "normal i\<F2>\<F3>" + call assert_equal(1, g:dragged) + call assert_equal('v', mode()) + exe "normal! \<C-\>\<C-N>" + unlet g:dragged + + inoremap <LeftDrag> <LeftDrag><C-\><C-N> + exe "normal i\<F2>\<F3>" + call assert_equal('n', mode()) + + iunmap <LeftDrag> + iunmap <F2> + iunmap <F3> + delfunc ClickExpr + delfunc DragExpr + set mouse& +endfunc + " vim: shiftwidth=2 sts=2 expandtab |