]> granicus.if.org Git - vim/commitdiff
patch 8.2.0670: cannot change window when evaluating 'completefunc' v8.2.0670
authorBram Moolenaar <Bram@vim.org>
Thu, 30 Apr 2020 20:31:18 +0000 (22:31 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 30 Apr 2020 20:31:18 +0000 (22:31 +0200)
Problem:    Cannot change window when evaluating 'completefunc'.
Solution:   Make a difference between not changing text or buffers and also
            not changing window.

18 files changed:
src/beval.c
src/change.c
src/edit.c
src/eval.c
src/ex_docmd.c
src/ex_getln.c
src/globals.h
src/indent.c
src/insexpand.c
src/map.c
src/proto/ex_getln.pro
src/register.c
src/testdir/test_edit.vim
src/testdir/test_ins_complete.vim
src/testdir/test_popup.vim
src/undo.c
src/version.c
src/window.c

index 6b10a654d8557c822a17f0e592bc9cae28442795..b7d9226e705f0cf8bcfc12a926c87885f2fd121d 100644 (file)
@@ -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)
index cfba90b3caee5b0b0510e22c2146b0bda0ccb4fd..45d67044e66b1e3d8041a9af935672eebfe96d6d 100644 (file)
@@ -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;
 
index 7f4f765012d8b304c43437573546270097d98839..0ac63ec8fd5986c6a5a19d26eae86c38c502cfe1 100644 (file)
@@ -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;
index 4bd45e9ceb22a407b82d0ee249407648a9ad1d14..31dde2faed6667aa2a2e44e4316d01a99a276737 100644 (file)
@@ -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;
 }
index ca69c293d6f4f87bb9acba84f3fa7494740c3d5e..65ef936e9f26b5977bf1d2589ae196ae01eb9181 100644 (file)
@@ -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
index 6376a5fba41c5fcff4583a1ad2c5b979c42e4b20..48d40cfc761325234993f2e2b6ec25b985cd2fc5 100644 (file)
@@ -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,9 +2578,21 @@ 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)
     {
index 2dceab5e2363a467c05e67345d6a9674d9abdc4c..9180befcb5291eaf9a6f4e0f1ebdb0166ac1adf7 100644 (file)
@@ -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"));
index 10c82d89de867e588fd2ec22a4c0d0444c096164..a1d4d3628e2d8dce56304d83e716444b4cc4d65b 100644 (file)
@@ -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"
index 48ab260a70f4240c9b6ab4dea5d0b0e4c2189180..bd809b0e6ffa9bcb1e3f71045a2050acefdec412 100644 (file)
@@ -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
index 85c46a52bbe072c6dea455e0e1bcb03690aee584..2e20d401cbd988d9ccfa58f262875a6e1fb3e512 100644 (file)
--- 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;
index a8ca7af17babff35bd5c9be2d482ec3a4863a5eb..f64bb1ff5d35fbde6754580c33d3591c9b1b5f95 100644 (file)
@@ -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);
index 2ad136bdc61652b44e91f4fa9579b1f83352b8a8..e56149f39221cdfd4162d4eee4d08b3579f9164f 100644 (file)
@@ -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
index a9ba31df4c1f7b18a878571aa1cdfe4343a9f1d2..f0bf5cc5f6c32b1bd41aaa9d15d8ebbe095680aa 100644 (file)
@@ -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
 
index cec4acf3f2736c7fc9a87e67e61d6e9498545f88..dbea9013f82fb84873aa5f8ba9915640e37fa2de 100644 (file)
@@ -491,7 +491,7 @@ func Test_completefunc_error()
   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
index 9890377ea7b386db6ef7fd14021bf4325393a05e..c7229fc8e7f1139b709abe133fcc6874aa1dab83 100644 (file)
@@ -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!
index c11b048a2c346408cfabe4b63602567c989ebda2..4bbc0af0fb3d052cff6fd89bc2b65a9314cdd5d6 100644 (file)
@@ -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;
index 6b3a1596aa5414167ac294df1eb6636c6d1b686a..8b9fec5516437d532103eb4c347a22646216b655 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    670,
 /**/
     669,
 /**/
index 7c18c06a7f9a2316ebe146077d835521f0026fda..532d31431ec2469924418e07f9d094ce8a4461b7 100644 (file)
@@ -4370,7 +4370,7 @@ win_goto(win_T *wp)
        return;
     }
 #endif
-    if (text_locked())
+    if (text_and_win_locked())
     {
        beep_flush();
        text_locked_msg();