summaryrefslogtreecommitdiff
path: root/src/popupwin.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-09-08 22:06:44 +0200
committerBram Moolenaar <Bram@vim.org>2020-09-08 22:06:44 +0200
commit6defa7bf0a8935cc44f3dc12e9c87bbb40f190b7 (patch)
treeac60098e2e1b3730bd44818242b45959b5b90ebe /src/popupwin.c
parent57ad94c5a9ee6f3626e1ec728519a8558a4346c8 (diff)
downloadvim-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.c30
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);