From: Bram Moolenaar Date: Sat, 3 Sep 2016 14:29:04 +0000 (+0200) Subject: patch 7.4.2312 X-Git-Tag: v7.4.2312 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5a49789a9b1f6447aeafbbbdd5b235dd10c471d5;p=vim patch 7.4.2312 Problem: Crash when autocommand moves to another tab. (Dominique Pelle) Solution: When navigating to another window halfway the :edit command go back to the right window. --- diff --git a/src/buffer.c b/src/buffer.c index 4841f9ab2..9270c39fc 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -666,7 +666,8 @@ buf_clear_file(buf_T *buf) /* * buf_freeall() - free all things allocated for a buffer that are related to - * the file. flags: + * the file. Careful: get here with "curwin" NULL when exiting. + * flags: * BFA_DEL buffer is going to be deleted * BFA_WIPE buffer is going to be wiped out * BFA_KEEP_UNDO do not free undo information @@ -677,7 +678,13 @@ buf_freeall(buf_T *buf, int flags) #ifdef FEAT_AUTOCMD int is_curbuf = (buf == curbuf); bufref_T bufref; +# ifdef FEAT_WINDOWS + int is_curwin = (curwin!= NULL && curwin->w_buffer == buf); + win_T *the_curwin = curwin; + tabpage_T *the_curtab = curtab; +# endif + /* Make sure the buffer isn't closed by autocommands. */ buf->b_closing = TRUE; set_bufref(&bufref, buf); if (buf->b_ml.ml_mfp != NULL) @@ -705,6 +712,19 @@ buf_freeall(buf_T *buf, int flags) return; } buf->b_closing = FALSE; + +# ifdef FEAT_WINDOWS + /* If the buffer was in curwin and the window has changed, go back to that + * window, if it still exists. This avoids that ":edit x" triggering a + * "tabnext" BufUnload autocmd leaves a window behind without a buffer. */ + if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin)) + { + block_autocmds(); + goto_tabpage_win(the_curtab, the_curwin); + unblock_autocmds(); + } +# endif + # ifdef FEAT_EVAL if (aborting()) /* autocmds may abort script processing */ return; diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 1deb8a368..61ab2ab12 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3935,25 +3935,28 @@ do_ecmd( auto_buf = TRUE; else { + win_T *the_curwin = curwin; + + /* Set the w_closing flag to avoid that autocommands close the + * window. */ + the_curwin->w_closing = TRUE; + if (curbuf == old_curbuf.br_buf) #endif buf_copy_options(buf, BCO_ENTER); - /* close the link to the current buffer */ + /* Close the link to the current buffer. This will set + * curwin->w_buffer to NULL. */ u_sync(FALSE); close_buffer(oldwin, curbuf, (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE); #ifdef FEAT_AUTOCMD - /* Autocommands may open a new window and leave oldwin open - * which leads to crashes since the above call sets - * oldwin->w_buffer to NULL. */ - if (curwin != oldwin && oldwin != aucmd_win - && win_valid(oldwin) && oldwin->w_buffer == NULL) - win_close(oldwin, FALSE); + the_curwin->w_closing = FALSE; # ifdef FEAT_EVAL - if (aborting()) /* autocmds may abort script processing */ + /* autocmds may abort script processing */ + if (aborting() && curwin->w_buffer != NULL) { vim_free(new_name); goto theend; diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 866b347d6..b568e46c3 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2475,12 +2475,7 @@ do_one_cmd( && !IS_USER_CMDIDX(ea.cmdidx)) { /* Command not allowed when editing the command line. */ -#ifdef FEAT_CMDWIN - if (cmdwin_type != 0) - errormsg = (char_u *)_(e_cmdwin); - else -#endif - errormsg = (char_u *)_(e_secure); + errormsg = get_text_locked_msg(); goto doend; } #ifdef FEAT_AUTOCMD diff --git a/src/ex_getln.c b/src/ex_getln.c index 110a95afd..1627ee74f 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -2132,13 +2132,18 @@ text_locked(void) */ void text_locked_msg(void) +{ + EMSG(_(get_text_locked_msg())); +} + + char_u * +get_text_locked_msg(void) { #ifdef FEAT_CMDWIN if (cmdwin_type != 0) - EMSG(_(e_cmdwin)); - else + return e_cmdwin; #endif - EMSG(_(e_secure)); + return e_secure; } #if defined(FEAT_AUTOCMD) || defined(PROTO) diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro index 581bfcebb..afc875c59 100644 --- a/src/proto/ex_getln.pro +++ b/src/proto/ex_getln.pro @@ -3,6 +3,7 @@ char_u *getcmdline(int firstc, long count, int indent); char_u *getcmdline_prompt(int firstc, char_u *prompt, int attr, int xp_context, char_u *xp_arg); int text_locked(void); void text_locked_msg(void); +char_u *get_text_locked_msg(void); int curbuf_locked(void); int allbuf_locked(void); char_u *getexline(int c, void *cookie, int indent); diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index 7bdea0b18..0bf7d056d 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -218,7 +218,7 @@ function Test_tabpage_with_tab_modifier() bw! endfunction -func Test_tabnext_on_buf_unload() +func Test_tabnext_on_buf_unload1() " This once caused a crash new tabedit @@ -227,7 +227,19 @@ func Test_tabnext_on_buf_unload() q while tabpagenr('$') > 1 - quit + bwipe! + endwhile +endfunc + +func Test_tabnext_on_buf_unload2() + " This once caused a crash + tabedit + autocmd BufUnload tabnext + file x + edit y + + while tabpagenr('$') > 1 + bwipe! endwhile endfunc diff --git a/src/version.c b/src/version.c index ff7f23685..df1de63e0 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2312, /**/ 2311, /**/ diff --git a/src/window.c b/src/window.c index 2f3ec8c62..4f992711f 100644 --- a/src/window.c +++ b/src/window.c @@ -3912,12 +3912,7 @@ goto_tabpage(int n) if (text_locked()) { /* Not allowed when editing the command line. */ -#ifdef FEAT_CMDWIN - if (cmdwin_type != 0) - EMSG(_(e_cmdwin)); - else -#endif - EMSG(_(e_secure)); + text_locked_msg(); return; }