To: vim_dev@googlegroups.com Subject: Patch 8.2.0670 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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\\", 'E565:') bwipe! endfunc --- 927,933 ---- set completefunc=CompleteFunc call setline(1, ['', 'abcd', '']) 2d ! call assert_fails("normal 2G$a\\", '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\\"', 'E565:') set completefunc& delfunc CompleteFunc --- 491,497 ---- endfunc set completefunc=CompleteFunc2 call setline(1, ['', 'abcd', '']) ! call assert_fails('exe "normal 2G$a\\"', '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\\\\", "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\\\\", "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 -- Bram@Moolenaar.net -- 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 ///