444 lines
13 KiB
Diff
444 lines
13 KiB
Diff
From 6adb9ea0a6ca01414f4b591f379b0f829a8273c0 Mon Sep 17 00:00:00 2001
|
|
From: Bram Moolenaar <Bram@vim.org>
|
|
Date: Thu, 30 Apr 2020 22:31:18 +0200
|
|
Subject: [PATCH] patch 8.2.0670: cannot change window when evaluating
|
|
'completefunc'
|
|
|
|
Problem: Cannot change window when evaluating 'completefunc'.
|
|
Solution: Make a difference between not changing text or buffers and also
|
|
not changing window.
|
|
---
|
|
src/beval.c | 4 ++--
|
|
src/change.c | 4 ++--
|
|
src/edit.c | 9 +++++----
|
|
src/eval.c | 10 +++++-----
|
|
src/ex_docmd.c | 2 +-
|
|
src/ex_getln.c | 30 +++++++++++++++++++++---------
|
|
src/globals.h | 13 ++++++++++---
|
|
src/indent.c | 4 ++--
|
|
src/insexpand.c | 11 ++++++-----
|
|
src/map.c | 4 ++--
|
|
src/proto/ex_getln.pro | 3 ++-
|
|
src/register.c | 4 ++--
|
|
src/testdir/test_edit.vim | 2 +-
|
|
src/testdir/test_popup.vim | 2 +-
|
|
src/undo.c | 2 +-
|
|
src/window.c | 2 +-
|
|
16 files changed, 64 insertions(+), 42 deletions(-)
|
|
|
|
diff --git a/src/beval.c b/src/beval.c
|
|
index 6b10a65..b7d9226 100644
|
|
--- a/src/beval.c
|
|
+++ b/src/beval.c
|
|
@@ -282,7 +282,7 @@ general_beval_cb(BalloonEval *beval, int state UNUSED)
|
|
curbuf = save_curbuf;
|
|
if (use_sandbox)
|
|
++sandbox;
|
|
- ++textlock;
|
|
+ ++textwinlock;
|
|
|
|
vim_free(result);
|
|
result = eval_to_string(bexpr, NULL, TRUE);
|
|
@@ -299,7 +299,7 @@ general_beval_cb(BalloonEval *beval, int state UNUSED)
|
|
|
|
if (use_sandbox)
|
|
--sandbox;
|
|
- --textlock;
|
|
+ --textwinlock;
|
|
|
|
set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
|
|
if (result != NULL && result[0] != NUL)
|
|
diff --git a/src/change.c b/src/change.c
|
|
index cfba90b..45d6704 100644
|
|
--- a/src/change.c
|
|
+++ b/src/change.c
|
|
@@ -382,7 +382,7 @@ invoke_listeners(buf_T *buf)
|
|
|
|
argv[4].v_type = VAR_LIST;
|
|
argv[4].vval.v_list = buf->b_recorded_changes;
|
|
- ++textlock;
|
|
+ ++textwinlock;
|
|
|
|
for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
|
|
{
|
|
@@ -390,7 +390,7 @@ invoke_listeners(buf_T *buf)
|
|
clear_tv(&rettv);
|
|
}
|
|
|
|
- --textlock;
|
|
+ --textwinlock;
|
|
list_unref(buf->b_recorded_changes);
|
|
buf->b_recorded_changes = NULL;
|
|
|
|
diff --git a/src/edit.c b/src/edit.c
|
|
index 7f4f765..0ac63ec 100644
|
|
--- a/src/edit.c
|
|
+++ b/src/edit.c
|
|
@@ -176,9 +176,10 @@ edit(
|
|
// Don't allow changes in the buffer while editing the cmdline. The
|
|
// caller of getcmdline() may get confused.
|
|
// Don't allow recursive insert mode when busy with completion.
|
|
- if (textlock != 0 || ins_compl_active() || compl_busy || pum_visible())
|
|
+ if (textwinlock != 0 || textlock != 0
|
|
+ || ins_compl_active() || compl_busy || pum_visible())
|
|
{
|
|
- emsg(_(e_textlock));
|
|
+ emsg(_(e_textwinlock));
|
|
return FALSE;
|
|
}
|
|
ins_compl_clear(); // clear stuff for CTRL-X mode
|
|
@@ -5944,7 +5945,7 @@ do_insert_char_pre(int c)
|
|
}
|
|
|
|
// Lock the text to avoid weird things from happening.
|
|
- ++textlock;
|
|
+ ++textwinlock;
|
|
set_vim_var_string(VV_CHAR, buf, -1); // set v:char
|
|
|
|
res = NULL;
|
|
@@ -5958,7 +5959,7 @@ do_insert_char_pre(int c)
|
|
}
|
|
|
|
set_vim_var_string(VV_CHAR, NULL, -1); // clear v:char
|
|
- --textlock;
|
|
+ --textwinlock;
|
|
|
|
// Restore the State, it may have been changed.
|
|
State = save_State;
|
|
diff --git a/src/eval.c b/src/eval.c
|
|
index 4bd45e9..31dde2f 100644
|
|
--- a/src/eval.c
|
|
+++ b/src/eval.c
|
|
@@ -393,7 +393,7 @@ eval_to_string(
|
|
|
|
/*
|
|
* Call eval_to_string() without using current local variables and using
|
|
- * textlock. When "use_sandbox" is TRUE use the sandbox.
|
|
+ * textwinlock. When "use_sandbox" is TRUE use the sandbox.
|
|
*/
|
|
char_u *
|
|
eval_to_string_safe(
|
|
@@ -407,11 +407,11 @@ eval_to_string_safe(
|
|
save_funccal(&funccal_entry);
|
|
if (use_sandbox)
|
|
++sandbox;
|
|
- ++textlock;
|
|
+ ++textwinlock;
|
|
retval = eval_to_string(arg, nextcmd, FALSE);
|
|
if (use_sandbox)
|
|
--sandbox;
|
|
- --textlock;
|
|
+ --textwinlock;
|
|
restore_funccal();
|
|
return retval;
|
|
}
|
|
@@ -576,7 +576,7 @@ eval_foldexpr(char_u *arg, int *cp)
|
|
++emsg_off;
|
|
if (use_sandbox)
|
|
++sandbox;
|
|
- ++textlock;
|
|
+ ++textwinlock;
|
|
*cp = NUL;
|
|
if (eval0(arg, &tv, NULL, TRUE) == FAIL)
|
|
retval = 0;
|
|
@@ -601,7 +601,7 @@ eval_foldexpr(char_u *arg, int *cp)
|
|
--emsg_off;
|
|
if (use_sandbox)
|
|
--sandbox;
|
|
- --textlock;
|
|
+ --textwinlock;
|
|
|
|
return (int)retval;
|
|
}
|
|
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
|
|
index ca69c29..65ef936 100644
|
|
--- a/src/ex_docmd.c
|
|
+++ b/src/ex_docmd.c
|
|
@@ -5749,7 +5749,7 @@ handle_drop(
|
|
handle_any_postponed_drop(void)
|
|
{
|
|
if (!drop_busy && drop_filev != NULL
|
|
- && !text_locked() && !curbuf_locked() && !updating_screen)
|
|
+ && !text_locked() && !curbuf_locked() && !updating_screen)
|
|
handle_drop_internal();
|
|
}
|
|
#endif
|
|
diff --git a/src/ex_getln.c b/src/ex_getln.c
|
|
index 6376a5f..48d40cf 100644
|
|
--- a/src/ex_getln.c
|
|
+++ b/src/ex_getln.c
|
|
@@ -1318,12 +1318,12 @@ getcmdline_int(
|
|
c = get_expr_register();
|
|
if (c == '=')
|
|
{
|
|
- // Need to save and restore ccline. And set "textlock"
|
|
+ // Need to save and restore ccline. And set "textwinlock"
|
|
// to avoid nasty things like going to another buffer when
|
|
// evaluating an expression.
|
|
- ++textlock;
|
|
+ ++textwinlock;
|
|
p = get_expr_line();
|
|
- --textlock;
|
|
+ --textwinlock;
|
|
|
|
if (p != NULL)
|
|
{
|
|
@@ -2548,17 +2548,17 @@ check_opt_wim(void)
|
|
|
|
/*
|
|
* Return TRUE when the text must not be changed and we can't switch to
|
|
- * another window or buffer. Used when editing the command line, evaluating
|
|
+ * another window or buffer. TRUE when editing the command line, evaluating
|
|
* 'balloonexpr', etc.
|
|
*/
|
|
int
|
|
-text_locked(void)
|
|
+text_and_win_locked(void)
|
|
{
|
|
#ifdef FEAT_CMDWIN
|
|
if (cmdwin_type != 0)
|
|
return TRUE;
|
|
#endif
|
|
- return textlock != 0;
|
|
+ return textwinlock != 0;
|
|
}
|
|
|
|
/*
|
|
@@ -2578,10 +2578,22 @@ get_text_locked_msg(void)
|
|
if (cmdwin_type != 0)
|
|
return e_cmdwin;
|
|
#endif
|
|
+ if (textwinlock != 0)
|
|
+ return e_textwinlock;
|
|
return e_textlock;
|
|
}
|
|
|
|
/*
|
|
+ * Return TRUE when the text must not be changed and/or we cannot switch to
|
|
+ * another window. TRUE while evaluating 'completefunc'.
|
|
+ */
|
|
+ int
|
|
+text_locked(void)
|
|
+{
|
|
+ return text_and_win_locked() || textlock != 0;
|
|
+}
|
|
+
|
|
+/*
|
|
* Check if "curbuf_lock" or "allbuf_lock" is set and return TRUE when it is
|
|
* and give an error message.
|
|
*/
|
|
@@ -3560,11 +3572,11 @@ cmdline_paste(
|
|
regname = may_get_selection(regname);
|
|
#endif
|
|
|
|
- // Need to set "textlock" to avoid nasty things like going to another
|
|
+ // Need to set "textwinlock" to avoid nasty things like going to another
|
|
// buffer when evaluating an expression.
|
|
- ++textlock;
|
|
+ ++textwinlock;
|
|
i = get_spec_reg(regname, &arg, &allocated, TRUE);
|
|
- --textlock;
|
|
+ --textwinlock;
|
|
|
|
if (i)
|
|
{
|
|
diff --git a/src/globals.h b/src/globals.h
|
|
index 2dceab5..9180bef 100644
|
|
--- a/src/globals.h
|
|
+++ b/src/globals.h
|
|
@@ -798,9 +798,15 @@ EXTERN int secure INIT(= FALSE);
|
|
// allowed, e.g. when sourcing .exrc or .vimrc
|
|
// in current directory
|
|
|
|
-EXTERN int textlock INIT(= 0);
|
|
+EXTERN int textwinlock INIT(= 0);
|
|
// non-zero when changing text and jumping to
|
|
- // another window or buffer is not allowed
|
|
+ // another window or editing another buffer is
|
|
+ // not allowed
|
|
+
|
|
+EXTERN int textlock INIT(= 0);
|
|
+ // non-zero when changing text is not allowed,
|
|
+ // jumping to another window is allowed,
|
|
+ // editing another buffer is not allowed.
|
|
|
|
EXTERN int curbuf_lock INIT(= 0);
|
|
// non-zero when the current buffer can't be
|
|
@@ -1681,7 +1687,8 @@ EXTERN char e_readerrf[] INIT(= N_("E47: Error while reading errorfile"));
|
|
EXTERN char e_sandbox[] INIT(= N_("E48: Not allowed in sandbox"));
|
|
#endif
|
|
EXTERN char e_secure[] INIT(= N_("E523: Not allowed here"));
|
|
-EXTERN char e_textlock[] INIT(= N_("E565: Not allowed to change text here"));
|
|
+EXTERN char e_textlock[] INIT(= N_("E578: Not allowed to change text here"));
|
|
+EXTERN char e_textwinlock[] INIT(= N_("E565: Not allowed to change text or change window"));
|
|
#if defined(AMIGA) || defined(MACOS_X) || defined(MSWIN) \
|
|
|| defined(UNIX) || defined(VMS)
|
|
EXTERN char e_screenmode[] INIT(= N_("E359: Screen mode setting not supported"));
|
|
diff --git a/src/indent.c b/src/indent.c
|
|
index 10c82d8..a1d4d36 100644
|
|
--- a/src/indent.c
|
|
+++ b/src/indent.c
|
|
@@ -1760,7 +1760,7 @@ get_expr_indent(void)
|
|
set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
|
|
if (use_sandbox)
|
|
++sandbox;
|
|
- ++textlock;
|
|
+ ++textwinlock;
|
|
|
|
// Need to make a copy, the 'indentexpr' option could be changed while
|
|
// evaluating it.
|
|
@@ -1773,7 +1773,7 @@ get_expr_indent(void)
|
|
|
|
if (use_sandbox)
|
|
--sandbox;
|
|
- --textlock;
|
|
+ --textwinlock;
|
|
|
|
// Restore the cursor position so that 'indentexpr' doesn't need to.
|
|
// Pretend to be in Insert mode, allow cursor past end of line for "o"
|
|
diff --git a/src/insexpand.c b/src/insexpand.c
|
|
index 48ab260..bd809b0 100644
|
|
--- a/src/insexpand.c
|
|
+++ b/src/insexpand.c
|
|
@@ -989,9 +989,9 @@ trigger_complete_changed_event(int cur)
|
|
dict_set_items_ro(v_event);
|
|
|
|
recursive = TRUE;
|
|
- textlock++;
|
|
+ textwinlock++;
|
|
apply_autocmds(EVENT_COMPLETECHANGED, NULL, NULL, FALSE, curbuf);
|
|
- textlock--;
|
|
+ textwinlock--;
|
|
recursive = FALSE;
|
|
|
|
dict_free_contents(v_event);
|
|
@@ -2217,7 +2217,8 @@ expand_by_function(
|
|
pos = curwin->w_cursor;
|
|
curwin_save = curwin;
|
|
curbuf_save = curbuf;
|
|
- // Lock the text to avoid weird things from happening.
|
|
+ // Lock the text to avoid weird things from happening. Do allow switching
|
|
+ // to another window temporarily.
|
|
++textlock;
|
|
|
|
// Call a function, which returns a list or dict.
|
|
@@ -2442,8 +2443,8 @@ f_complete(typval_T *argvars, typval_T *rettv UNUSED)
|
|
return;
|
|
}
|
|
|
|
- // "textlock" is set when evaluating 'completefunc' but we can change text
|
|
- // here.
|
|
+ // "textlock" is set when evaluating 'completefunc' but we can change
|
|
+ // text here.
|
|
textlock = 0;
|
|
|
|
// Check for undo allowed here, because if something was already inserted
|
|
diff --git a/src/map.c b/src/map.c
|
|
index 85c46a5..2e20d40 100644
|
|
--- a/src/map.c
|
|
+++ b/src/map.c
|
|
@@ -1570,14 +1570,14 @@ eval_map_expr(
|
|
|
|
// Forbid changing text or using ":normal" to avoid most of the bad side
|
|
// effects. Also restore the cursor position.
|
|
- ++textlock;
|
|
+ ++textwinlock;
|
|
++ex_normal_lock;
|
|
set_vim_var_char(c); // set v:char to the typed character
|
|
save_cursor = curwin->w_cursor;
|
|
save_msg_col = msg_col;
|
|
save_msg_row = msg_row;
|
|
p = eval_to_string(expr, NULL, FALSE);
|
|
- --textlock;
|
|
+ --textwinlock;
|
|
--ex_normal_lock;
|
|
curwin->w_cursor = save_cursor;
|
|
msg_col = save_msg_col;
|
|
diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro
|
|
index a8ca7af..f64bb1f 100644
|
|
--- a/src/proto/ex_getln.pro
|
|
+++ b/src/proto/ex_getln.pro
|
|
@@ -3,9 +3,10 @@ void cmdline_init(void);
|
|
char_u *getcmdline(int firstc, long count, int indent, int do_concat);
|
|
char_u *getcmdline_prompt(int firstc, char_u *prompt, int attr, int xp_context, char_u *xp_arg);
|
|
int check_opt_wim(void);
|
|
-int text_locked(void);
|
|
+int text_and_win_locked(void);
|
|
void text_locked_msg(void);
|
|
char *get_text_locked_msg(void);
|
|
+int text_locked(void);
|
|
int curbuf_locked(void);
|
|
int allbuf_locked(void);
|
|
char_u *getexline(int c, void *cookie, int indent, int do_concat);
|
|
diff --git a/src/register.c b/src/register.c
|
|
index 2ad136b..e56149f 100644
|
|
--- a/src/register.c
|
|
+++ b/src/register.c
|
|
@@ -932,9 +932,9 @@ yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
|
|
dict_set_items_ro(v_event);
|
|
|
|
recursive = TRUE;
|
|
- textlock++;
|
|
+ textwinlock++;
|
|
apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, FALSE, curbuf);
|
|
- textlock--;
|
|
+ textwinlock--;
|
|
recursive = FALSE;
|
|
|
|
// Empty the dictionary, v:event is still valid
|
|
diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim
|
|
index a9ba31d..f0bf5cc 100644
|
|
--- a/src/testdir/test_edit.vim
|
|
+++ b/src/testdir/test_edit.vim
|
|
@@ -927,7 +927,7 @@ func Test_edit_completefunc_delete()
|
|
set completefunc=CompleteFunc
|
|
call setline(1, ['', 'abcd', ''])
|
|
2d
|
|
- call assert_fails("normal 2G$a\<C-X>\<C-U>", 'E565:')
|
|
+ call assert_fails("normal 2G$a\<C-X>\<C-U>", 'E578:')
|
|
bwipe!
|
|
endfunc
|
|
|
|
diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim
|
|
index 9890377..c7229fc 100644
|
|
--- a/src/testdir/test_popup.vim
|
|
+++ b/src/testdir/test_popup.vim
|
|
@@ -342,7 +342,7 @@ func Test_completefunc_opens_new_window_one()
|
|
setlocal completefunc=DummyCompleteOne
|
|
call setline(1, 'one')
|
|
/^one
|
|
- call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E565:')
|
|
+ call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E578:')
|
|
call assert_equal(winid, win_getid())
|
|
call assert_equal('oneDEF', getline(1))
|
|
q!
|
|
diff --git a/src/undo.c b/src/undo.c
|
|
index c11b048..4bbc0af 100644
|
|
--- a/src/undo.c
|
|
+++ b/src/undo.c
|
|
@@ -331,7 +331,7 @@ undo_allowed(void)
|
|
|
|
// Don't allow changes in the buffer while editing the cmdline. The
|
|
// caller of getcmdline() may get confused.
|
|
- if (textlock != 0)
|
|
+ if (textwinlock != 0 || textlock != 0)
|
|
{
|
|
emsg(_(e_textlock));
|
|
return FALSE;
|
|
diff --git a/src/window.c b/src/window.c
|
|
index 7c18c06..532d314 100644
|
|
--- a/src/window.c
|
|
+++ b/src/window.c
|
|
@@ -4370,7 +4370,7 @@ win_goto(win_T *wp)
|
|
|
|
if (ERROR_IF_POPUP_WINDOW)
|
|
return;
|
|
- if (text_locked())
|
|
+ if (text_and_win_locked())
|
|
{
|
|
beep_flush();
|
|
text_locked_msg();
|
|
--
|
|
1.8.3.1
|
|
|