diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-09-03 16:29:04 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-09-03 16:29:04 +0200 |
commit | 5a49789a9b1f6447aeafbbbdd5b235dd10c471d5 (patch) | |
tree | 611853ba4f58cc676cffdfdf622dad348372c269 | |
parent | dd905a2ae14bf2ee59a068f1c3acbca1ff0b7067 (diff) | |
download | vim-git-5a49789a9b1f6447aeafbbbdd5b235dd10c471d5.tar.gz |
patch 7.4.2312v7.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.
-rw-r--r-- | src/buffer.c | 22 | ||||
-rw-r--r-- | src/ex_cmds.c | 19 | ||||
-rw-r--r-- | src/ex_docmd.c | 7 | ||||
-rw-r--r-- | src/ex_getln.c | 11 | ||||
-rw-r--r-- | src/proto/ex_getln.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_tabpage.vim | 16 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/window.c | 7 |
8 files changed, 59 insertions, 26 deletions
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 @@ -2133,12 +2133,17 @@ 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 <buffer> 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 @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2312, +/**/ 2311, /**/ 2310, 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; } |