Problem: Cannot change window when evaluating 'completefunc'.
Solution: Make a difference between not changing text or buffers and also
not changing window.
curbuf = save_curbuf;
if (use_sandbox)
++sandbox;
- ++textlock;
+ ++textwinlock;
vim_free(result);
result = eval_to_string(bexpr, NULL, TRUE);
if (use_sandbox)
--sandbox;
- --textlock;
+ --textwinlock;
set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
if (result != NULL && result[0] != NUL)
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)
{
clear_tv(&rettv);
}
- --textlock;
+ --textwinlock;
list_unref(buf->b_recorded_changes);
buf->b_recorded_changes = NULL;
// 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
}
// Lock the text to avoid weird things from happening.
- ++textlock;
+ ++textwinlock;
set_vim_var_string(VV_CHAR, buf, -1); // set v:char
res = NULL;
}
set_vim_var_string(VV_CHAR, NULL, -1); // clear v:char
- --textlock;
+ --textwinlock;
// Restore the State, it may have been changed.
State = save_State;
/*
* 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(
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;
}
++emsg_off;
if (use_sandbox)
++sandbox;
- ++textlock;
+ ++textwinlock;
*cp = NUL;
if (eval0(arg, &tv, NULL, TRUE) == FAIL)
retval = 0;
--emsg_off;
if (use_sandbox)
--sandbox;
- --textlock;
+ --textwinlock;
return (int)retval;
}
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
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)
{
/*
* 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;
}
/*
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.
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)
{
// 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
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"));
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.
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"
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);
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.
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
// 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;
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);
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
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
endfunc
set completefunc=CompleteFunc2
call setline(1, ['', 'abcd', ''])
- call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E565:')
+ call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E578:')
set completefunc&
delfunc CompleteFunc
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!
// 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;
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 670,
/**/
669,
/**/
return;
}
#endif
- if (text_locked())
+ if (text_and_win_locked())
{
beep_flush();
text_locked_msg();