summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-09-03 16:29:04 +0200
committerBram Moolenaar <Bram@vim.org>2016-09-03 16:29:04 +0200
commit5a49789a9b1f6447aeafbbbdd5b235dd10c471d5 (patch)
tree611853ba4f58cc676cffdfdf622dad348372c269
parentdd905a2ae14bf2ee59a068f1c3acbca1ff0b7067 (diff)
downloadvim-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.c22
-rw-r--r--src/ex_cmds.c19
-rw-r--r--src/ex_docmd.c7
-rw-r--r--src/ex_getln.c11
-rw-r--r--src/proto/ex_getln.pro1
-rw-r--r--src/testdir/test_tabpage.vim16
-rw-r--r--src/version.c2
-rw-r--r--src/window.c7
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;
}