Patch 8.2.0670
Problem:    Cannot change window when evaluating 'completefunc'.
Solution:   Make a difference between not changing text or buffers and also
            not changing window.
Files:      src/ex_getln.c, src/beval.c, src/change.c, src/edit.c, src/eval.c,
            src/ex_docmd.c, src/insexpand.c, src/globals.h, src/indent.c,
            src/map.c, src/window.c, src/proto/ex_getln.pro, src/register.c,
            src/undo.c, src/testdir/test_edit.vim,
            src/testdir/test_ins_complete.vim, src/testdir/test_popup.vim


*** ../vim-8.2.0669/src/ex_getln.c      2020-04-29 22:30:09.313356305 +0200
--- src/ex_getln.c      2020-04-30 22:11:16.889611605 +0200
***************
*** 1318,1329 ****
                c = get_expr_register();
                if (c == '=')
                {
!                   // Need to save and restore ccline.  And set "textlock"
                    // to avoid nasty things like going to another buffer when
                    // evaluating an expression.
!                   ++textlock;
                    p = get_expr_line();
!                   --textlock;
  
                    if (p != NULL)
                    {
--- 1318,1329 ----
                c = get_expr_register();
                if (c == '=')
                {
!                   // Need to save and restore ccline.  And set "textwinlock"
                    // to avoid nasty things like going to another buffer when
                    // evaluating an expression.
!                   ++textwinlock;
                    p = get_expr_line();
!                   --textwinlock;
  
                    if (p != NULL)
                    {
***************
*** 2548,2564 ****
  
  /*
   * 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
   * 'balloonexpr', etc.
   */
      int
! text_locked(void)
  {
  #ifdef FEAT_CMDWIN
      if (cmdwin_type != 0)
        return TRUE;
  #endif
!     return textlock != 0;
  }
  
  /*
--- 2548,2564 ----
  
  /*
   * Return TRUE when the text must not be changed and we can't switch to
!  * another window or buffer.  TRUE when editing the command line, evaluating
   * 'balloonexpr', etc.
   */
      int
! text_and_win_locked(void)
  {
  #ifdef FEAT_CMDWIN
      if (cmdwin_type != 0)
        return TRUE;
  #endif
!     return textwinlock != 0;
  }
  
  /*
***************
*** 2578,2587 ****
--- 2578,2599 ----
      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,3570 ****
      regname = may_get_selection(regname);
  #endif
  
!     // Need to  set "textlock" to avoid nasty things like going to another
      // buffer when evaluating an expression.
!     ++textlock;
      i = get_spec_reg(regname, &arg, &allocated, TRUE);
!     --textlock;
  
      if (i)
      {
--- 3572,3582 ----
      regname = may_get_selection(regname);
  #endif
  
!     // Need to  set "textwinlock" to avoid nasty things like going to another
      // buffer when evaluating an expression.
!     ++textwinlock;
      i = get_spec_reg(regname, &arg, &allocated, TRUE);
!     --textwinlock;
  
      if (i)
      {
*** ../vim-8.2.0669/src/beval.c 2020-04-04 14:50:28.931788970 +0200
--- src/beval.c 2020-04-30 21:33:26.549036219 +0200
***************
*** 282,288 ****
            curbuf = save_curbuf;
            if (use_sandbox)
                ++sandbox;
!           ++textlock;
  
            vim_free(result);
            result = eval_to_string(bexpr, NULL, TRUE);
--- 282,288 ----
            curbuf = save_curbuf;
            if (use_sandbox)
                ++sandbox;
!           ++textwinlock;
  
            vim_free(result);
            result = eval_to_string(bexpr, NULL, TRUE);
***************
*** 299,305 ****
  
            if (use_sandbox)
                --sandbox;
!           --textlock;
  
            set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
            if (result != NULL && result[0] != NUL)
--- 299,305 ----
  
            if (use_sandbox)
                --sandbox;
!           --textwinlock;
  
            set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
            if (result != NULL && result[0] != NUL)
*** ../vim-8.2.0669/src/change.c        2020-04-02 18:50:42.415773144 +0200
--- src/change.c        2020-04-30 21:33:47.824949393 +0200
***************
*** 382,388 ****
  
      argv[4].v_type = VAR_LIST;
      argv[4].vval.v_list = buf->b_recorded_changes;
!     ++textlock;
  
      for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
      {
--- 382,388 ----
  
      argv[4].v_type = VAR_LIST;
      argv[4].vval.v_list = buf->b_recorded_changes;
!     ++textwinlock;
  
      for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
      {
***************
*** 390,396 ****
        clear_tv(&rettv);
      }
  
!     --textlock;
      list_unref(buf->b_recorded_changes);
      buf->b_recorded_changes = NULL;
  
--- 390,396 ----
        clear_tv(&rettv);
      }
  
!     --textwinlock;
      list_unref(buf->b_recorded_changes);
      buf->b_recorded_changes = NULL;
  
*** ../vim-8.2.0669/src/edit.c  2020-04-27 20:18:27.678560149 +0200
--- src/edit.c  2020-04-30 22:10:39.837724202 +0200
***************
*** 176,184 ****
      // 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())
      {
!       emsg(_(e_textlock));
        return FALSE;
      }
      ins_compl_clear();            // clear stuff for CTRL-X mode
--- 176,185 ----
      // 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 (textwinlock != 0 || textlock != 0
!                         || ins_compl_active() || compl_busy || pum_visible())
      {
!       emsg(_(e_textwinlock));
        return FALSE;
      }
      ins_compl_clear();            // clear stuff for CTRL-X mode
***************
*** 5944,5950 ****
      }
  
      // Lock the text to avoid weird things from happening.
!     ++textlock;
      set_vim_var_string(VV_CHAR, buf, -1);  // set v:char
  
      res = NULL;
--- 5945,5951 ----
      }
  
      // Lock the text to avoid weird things from happening.
!     ++textwinlock;
      set_vim_var_string(VV_CHAR, buf, -1);  // set v:char
  
      res = NULL;
***************
*** 5958,5964 ****
      }
  
      set_vim_var_string(VV_CHAR, NULL, -1);  // clear v:char
!     --textlock;
  
      // Restore the State, it may have been changed.
      State = save_State;
--- 5959,5965 ----
      }
  
      set_vim_var_string(VV_CHAR, NULL, -1);  // clear v:char
!     --textwinlock;
  
      // Restore the State, it may have been changed.
      State = save_State;
*** ../vim-8.2.0669/src/eval.c  2020-04-25 15:24:40.547354124 +0200
--- src/eval.c  2020-04-30 21:34:40.060737816 +0200
***************
*** 393,399 ****
  
  /*
   * Call eval_to_string() without using current local variables and using
!  * textlock.  When "use_sandbox" is TRUE use the sandbox.
   */
      char_u *
  eval_to_string_safe(
--- 393,399 ----
  
  /*
   * Call eval_to_string() without using current local variables and using
!  * textwinlock.  When "use_sandbox" is TRUE use the sandbox.
   */
      char_u *
  eval_to_string_safe(
***************
*** 407,417 ****
      save_funccal(&funccal_entry);
      if (use_sandbox)
        ++sandbox;
!     ++textlock;
      retval = eval_to_string(arg, nextcmd, FALSE);
      if (use_sandbox)
        --sandbox;
!     --textlock;
      restore_funccal();
      return retval;
  }
--- 407,417 ----
      save_funccal(&funccal_entry);
      if (use_sandbox)
        ++sandbox;
!     ++textwinlock;
      retval = eval_to_string(arg, nextcmd, FALSE);
      if (use_sandbox)
        --sandbox;
!     --textwinlock;
      restore_funccal();
      return retval;
  }
***************
*** 576,582 ****
      ++emsg_off;
      if (use_sandbox)
        ++sandbox;
!     ++textlock;
      *cp = NUL;
      if (eval0(arg, &tv, NULL, TRUE) == FAIL)
        retval = 0;
--- 576,582 ----
      ++emsg_off;
      if (use_sandbox)
        ++sandbox;
!     ++textwinlock;
      *cp = NUL;
      if (eval0(arg, &tv, NULL, TRUE) == FAIL)
        retval = 0;
***************
*** 601,607 ****
      --emsg_off;
      if (use_sandbox)
        --sandbox;
!     --textlock;
  
      return (int)retval;
  }
--- 601,607 ----
      --emsg_off;
      if (use_sandbox)
        --sandbox;
!     --textwinlock;
  
      return (int)retval;
  }
*** ../vim-8.2.0669/src/ex_docmd.c      2020-04-27 19:28:58.536998688 +0200
--- src/ex_docmd.c      2020-04-30 21:53:50.776355590 +0200
***************
*** 5749,5755 ****
  handle_any_postponed_drop(void)
  {
      if (!drop_busy && drop_filev != NULL
!                    && !text_locked() && !curbuf_locked() && !updating_screen)
        handle_drop_internal();
  }
  #endif
--- 5749,5755 ----
  handle_any_postponed_drop(void)
  {
      if (!drop_busy && drop_filev != NULL
!            && !text_locked() && !curbuf_locked() && !updating_screen)
        handle_drop_internal();
  }
  #endif
*** ../vim-8.2.0669/src/insexpand.c     2020-04-21 22:01:11.089499502 +0200
--- src/insexpand.c     2020-04-30 21:56:56.727749016 +0200
***************
*** 989,997 ****
      dict_set_items_ro(v_event);
  
      recursive = TRUE;
!     textlock++;
      apply_autocmds(EVENT_COMPLETECHANGED, NULL, NULL, FALSE, curbuf);
!     textlock--;
      recursive = FALSE;
  
      dict_free_contents(v_event);
--- 989,997 ----
      dict_set_items_ro(v_event);
  
      recursive = TRUE;
!     textwinlock++;
      apply_autocmds(EVENT_COMPLETECHANGED, NULL, NULL, FALSE, curbuf);
!     textwinlock--;
      recursive = FALSE;
  
      dict_free_contents(v_event);
***************
*** 2217,2223 ****
      pos = curwin->w_cursor;
      curwin_save = curwin;
      curbuf_save = curbuf;
!     // Lock the text to avoid weird things from happening.
      ++textlock;
  
      // Call a function, which returns a list or dict.
--- 2217,2224 ----
      pos = curwin->w_cursor;
      curwin_save = curwin;
      curbuf_save = curbuf;
!     // 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,2449 ****
        return;
      }
  
!     // "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
--- 2443,2450 ----
        return;
      }
  
!     // "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
*** ../vim-8.2.0669/src/globals.h       2020-04-29 22:30:09.313356305 +0200
--- src/globals.h       2020-04-30 22:20:33.027836570 +0200
***************
*** 798,806 ****
                                // allowed, e.g. when sourcing .exrc or .vimrc
                                // in current directory
  
! EXTERN int    textlock INIT(= 0);
                                // non-zero when changing text and jumping to
!                               // another window or buffer is not allowed
  
  EXTERN int    curbuf_lock INIT(= 0);
                                // non-zero when the current buffer can't be
--- 798,812 ----
                                // allowed, e.g. when sourcing .exrc or .vimrc
                                // in current directory
  
! EXTERN int    textwinlock INIT(= 0);
                                // non-zero when changing text and jumping to
!                               // 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,1687 ****
  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"));
  #if defined(AMIGA) || defined(MACOS_X) || defined(MSWIN)  \
        || defined(UNIX) || defined(VMS)
  EXTERN char e_screenmode[]    INIT(= N_("E359: Screen mode setting not 
supported"));
--- 1687,1694 ----
  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_("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"));
*** ../vim-8.2.0669/src/indent.c        2020-02-23 15:29:43.013454555 +0100
--- src/indent.c        2020-04-30 21:35:20.464575532 +0200
***************
*** 1760,1766 ****
      set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
      if (use_sandbox)
        ++sandbox;
!     ++textlock;
  
      // Need to make a copy, the 'indentexpr' option could be changed while
      // evaluating it.
--- 1760,1766 ----
      set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
      if (use_sandbox)
        ++sandbox;
!     ++textwinlock;
  
      // Need to make a copy, the 'indentexpr' option could be changed while
      // evaluating it.
***************
*** 1773,1779 ****
  
      if (use_sandbox)
        --sandbox;
!     --textlock;
  
      // 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"
--- 1773,1779 ----
  
      if (use_sandbox)
        --sandbox;
!     --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"
*** ../vim-8.2.0669/src/map.c   2020-04-12 19:37:13.518297259 +0200
--- src/map.c   2020-04-30 21:36:06.124393444 +0200
***************
*** 1570,1583 ****
  
      // Forbid changing text or using ":normal" to avoid most of the bad side
      // effects.  Also restore the cursor position.
!     ++textlock;
      ++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;
      --ex_normal_lock;
      curwin->w_cursor = save_cursor;
      msg_col = save_msg_col;
--- 1570,1583 ----
  
      // Forbid changing text or using ":normal" to avoid most of the bad side
      // effects.  Also restore the cursor position.
!     ++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);
!     --textwinlock;
      --ex_normal_lock;
      curwin->w_cursor = save_cursor;
      msg_col = save_msg_col;
*** ../vim-8.2.0669/src/window.c        2020-04-15 20:05:42.740054643 +0200
--- src/window.c        2020-04-30 21:54:56.636111802 +0200
***************
*** 4370,4376 ****
        return;
      }
  #endif
!     if (text_locked())
      {
        beep_flush();
        text_locked_msg();
--- 4370,4376 ----
        return;
      }
  #endif
!     if (text_and_win_locked())
      {
        beep_flush();
        text_locked_msg();
*** ../vim-8.2.0669/src/proto/ex_getln.pro      2019-12-12 12:55:21.000000000 
+0100
--- src/proto/ex_getln.pro      2020-04-30 22:02:15.187115459 +0200
***************
*** 3,11 ****
  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);
  void text_locked_msg(void);
  char *get_text_locked_msg(void);
  int curbuf_locked(void);
  int allbuf_locked(void);
  char_u *getexline(int c, void *cookie, int indent, int do_concat);
--- 3,12 ----
  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_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);
*** ../vim-8.2.0669/src/register.c      2020-03-24 21:41:38.027535418 +0100
--- src/register.c      2020-04-30 21:36:16.544352080 +0200
***************
*** 932,940 ****
      dict_set_items_ro(v_event);
  
      recursive = TRUE;
!     textlock++;
      apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, FALSE, curbuf);
!     textlock--;
      recursive = FALSE;
  
      // Empty the dictionary, v:event is still valid
--- 932,940 ----
      dict_set_items_ro(v_event);
  
      recursive = TRUE;
!     textwinlock++;
      apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, FALSE, curbuf);
!     textwinlock--;
      recursive = FALSE;
  
      // Empty the dictionary, v:event is still valid
*** ../vim-8.2.0669/src/undo.c  2020-04-21 22:01:11.089499502 +0200
--- src/undo.c  2020-04-30 21:58:05.595637041 +0200
***************
*** 331,337 ****
  
      // Don't allow changes in the buffer while editing the cmdline.  The
      // caller of getcmdline() may get confused.
!     if (textlock != 0)
      {
        emsg(_(e_textlock));
        return FALSE;
--- 331,337 ----
  
      // Don't allow changes in the buffer while editing the cmdline.  The
      // caller of getcmdline() may get confused.
!     if (textwinlock != 0 || textlock != 0)
      {
        emsg(_(e_textlock));
        return FALSE;
*** ../vim-8.2.0669/src/testdir/test_edit.vim   2020-04-27 20:18:27.678560149 
+0200
--- src/testdir/test_edit.vim   2020-04-30 22:24:40.139018027 +0200
***************
*** 927,933 ****
    set completefunc=CompleteFunc
    call setline(1, ['', 'abcd', ''])
    2d
!   call assert_fails("normal 2G$a\<C-X>\<C-U>", 'E565:')
    bwipe!
  endfunc
  
--- 927,933 ----
    set completefunc=CompleteFunc
    call setline(1, ['', 'abcd', ''])
    2d
!   call assert_fails("normal 2G$a\<C-X>\<C-U>", 'E578:')
    bwipe!
  endfunc
  
*** ../vim-8.2.0669/src/testdir/test_ins_complete.vim   2020-04-28 
20:29:04.237851565 +0200
--- src/testdir/test_ins_complete.vim   2020-04-30 22:25:12.878908683 +0200
***************
*** 491,497 ****
    endfunc
    set completefunc=CompleteFunc2
    call setline(1, ['', 'abcd', ''])
!   call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E565:')
  
    set completefunc&
    delfunc CompleteFunc
--- 491,497 ----
    endfunc
    set completefunc=CompleteFunc2
    call setline(1, ['', 'abcd', ''])
!   call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E578:')
  
    set completefunc&
    delfunc CompleteFunc
*** ../vim-8.2.0669/src/testdir/test_popup.vim  2020-04-21 22:01:11.093499495 
+0200
--- src/testdir/test_popup.vim  2020-04-30 22:25:47.590792705 +0200
***************
*** 342,348 ****
    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_equal(winid, win_getid())
    call assert_equal('oneDEF', getline(1))
    q!
--- 342,348 ----
    setlocal completefunc=DummyCompleteOne
    call setline(1, 'one')
    /^one
!   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!
*** ../vim-8.2.0669/src/version.c       2020-04-30 20:59:54.080610231 +0200
--- src/version.c       2020-04-30 22:08:51.006048599 +0200
***************
*** 748,749 ****
--- 748,751 ----
  {   /* Add new patch number below this line */
+ /**/
+     670,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
30. Even though you died last week, you've managed to retain OPS on your
    favorite IRC channel.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202004302031.03UKVqR7032114%40masaka.moolenaar.net.

Raspunde prin e-mail lui