diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-09-08 22:06:44 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-09-08 22:06:44 +0200 |
commit | 6defa7bf0a8935cc44f3dc12e9c87bbb40f190b7 (patch) | |
tree | ac60098e2e1b3730bd44818242b45959b5b90ebe /src/popupwin.c | |
parent | 57ad94c5a9ee6f3626e1ec728519a8558a4346c8 (diff) | |
download | vim-git-6defa7bf0a8935cc44f3dc12e9c87bbb40f190b7.tar.gz |
patch 8.2.1636: get stuck if a popup filter causes an errorv8.2.1636
Problem: Get stuck if a popup filter causes an error.
Solution: Check whether the function can be called and does not cause an
error. (closes #6902)
Diffstat (limited to 'src/popupwin.c')
-rw-r--r-- | src/popupwin.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/src/popupwin.c b/src/popupwin.c index 953e76cc7..23f8efc8e 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -3126,6 +3126,7 @@ invoke_popup_filter(win_T *wp, int c) typval_T argv[3]; char_u buf[NUMBUFLEN]; linenr_T old_lnum = wp->w_cursor.lnum; + int prev_called_emsg = called_emsg; // Emergency exit: CTRL-C closes the popup. if (c == Ctrl_C) @@ -3151,10 +3152,35 @@ invoke_popup_filter(win_T *wp, int c) argv[2].v_type = VAR_UNKNOWN; // NOTE: The callback might close the popup and make "wp" invalid. - call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv); + if (call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv) == FAIL) + { + // Cannot call the function, close the popup to avoid that the filter + // eats keys and the user can't get out. + popup_close_with_retval(wp, -1); + return 1; + } + if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum) popup_highlight_curline(wp); - res = tv_get_bool(&rettv); + + // If an error was given always return FALSE, so that keys are not + // consumed and the user can type something. + // If we get three errors in a row then close the popup. Decrement the + // error count by 1/10 if there are no errors, thus allowing up to 1 in + // 10 calls to cause an error. + if (win_valid_popup(wp) && called_emsg > prev_called_emsg) + { + wp->w_filter_errors += 10; + if (wp->w_filter_errors >= 30) + popup_close_with_retval(wp, -1); + res = FALSE; + } + else + { + if (win_valid_popup(wp) && wp->w_filter_errors > 0) + --wp->w_filter_errors; + res = tv_get_bool(&rettv); + } vim_free(argv[1].vval.v_string); clear_tv(&rettv); |