summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buffer.c4
-rw-r--r--src/testdir/test_autocmd.vim17
-rw-r--r--src/version.c2
-rw-r--r--src/window.c80
4 files changed, 68 insertions, 35 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 2dac4874c..93da5dcc3 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -708,6 +708,10 @@ aucmd_abort:
*/
if (wipe_buf)
{
+ // Do not wipe out the buffer if it is used in a window.
+ if (buf->b_nwindows > 0)
+ return FALSE;
+
if (action == DOBUF_WIPE_REUSE)
{
// we can re-use this buffer number, store it
diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim
index 688508a85..39ba9af7d 100644
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -2990,4 +2990,21 @@ func Test_closing_autocmd_window()
bwipe Xb.txt
endfunc
+func Test_bufwipeout_changes_window()
+ " This should not crash, but we don't have any expectations about what
+ " happens, changing window in BufWipeout has unpredictable results.
+ tabedit
+ let g:window_id = win_getid()
+ topleft new
+ setlocal bufhidden=wipe
+ autocmd BufWipeout <buffer> call win_gotoid(g:window_id)
+ tabprevious
+ +tabclose
+
+ unlet g:window_id
+ au! BufWipeout
+ %bwipe!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 5eb4eea1e..9d78a0e8f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4631,
+/**/
4630,
/**/
4629,
diff --git a/src/window.c b/src/window.c
index 5bda6add9..66dd099bf 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2285,6 +2285,41 @@ entering_window(win_T *win)
}
#endif
+ static void
+win_init_empty(win_T *wp)
+{
+ redraw_win_later(wp, NOT_VALID);
+ wp->w_lines_valid = 0;
+ wp->w_cursor.lnum = 1;
+ wp->w_curswant = wp->w_cursor.col = 0;
+ wp->w_cursor.coladd = 0;
+ wp->w_pcmark.lnum = 1; // pcmark not cleared but set to line 1
+ wp->w_pcmark.col = 0;
+ wp->w_prev_pcmark.lnum = 0;
+ wp->w_prev_pcmark.col = 0;
+ wp->w_topline = 1;
+#ifdef FEAT_DIFF
+ wp->w_topfill = 0;
+#endif
+ wp->w_botline = 2;
+#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
+ wp->w_s = &wp->w_buffer->b_s;
+#endif
+#ifdef FEAT_TERMINAL
+ term_reset_wincolor(wp);
+#endif
+}
+
+/*
+ * Init the current window "curwin".
+ * Called when a new file is being edited.
+ */
+ void
+curwin_init(void)
+{
+ win_init_empty(curwin);
+}
+
/*
* Close all windows for buffer "buf".
*/
@@ -2786,7 +2821,17 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next)
;
if (ptp == NULL || tp == curtab)
+ {
+ // If the buffer was removed from the window we have to give it any
+ // buffer.
+ if (win_valid_any_tab(win) && win->w_buffer == NULL)
+ {
+ win->w_buffer = firstbuf;
+ ++firstbuf->b_nwindows;
+ win_init_empty(win);
+ }
return;
+ }
// Autocommands may have closed the window already.
for (wp = tp->tp_firstwin; wp != NULL && wp != win; wp = wp->w_next)
@@ -3685,41 +3730,6 @@ close_others(
emsg(_(e_other_window_contains_changes));
}
- static void
-win_init_empty(win_T *wp)
-{
- redraw_win_later(wp, NOT_VALID);
- wp->w_lines_valid = 0;
- wp->w_cursor.lnum = 1;
- wp->w_curswant = wp->w_cursor.col = 0;
- wp->w_cursor.coladd = 0;
- wp->w_pcmark.lnum = 1; // pcmark not cleared but set to line 1
- wp->w_pcmark.col = 0;
- wp->w_prev_pcmark.lnum = 0;
- wp->w_prev_pcmark.col = 0;
- wp->w_topline = 1;
-#ifdef FEAT_DIFF
- wp->w_topfill = 0;
-#endif
- wp->w_botline = 2;
-#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
- wp->w_s = &wp->w_buffer->b_s;
-#endif
-#ifdef FEAT_TERMINAL
- term_reset_wincolor(wp);
-#endif
-}
-
-/*
- * Init the current window "curwin".
- * Called when a new file is being edited.
- */
- void
-curwin_init(void)
-{
- win_init_empty(curwin);
-}
-
/*
* Allocate the first window and put an empty buffer in it.
* Called from main().