@@ -450,6 +450,11 @@ close_buffer(
450450 int is_curbuf ;
451451 int nwindows ;
452452 bufref_T bufref ;
453+ # ifdef FEAT_WINDOWS
454+ int is_curwin = (curwin != NULL && curwin -> w_buffer == buf );
455+ win_T * the_curwin = curwin ;
456+ tabpage_T * the_curtab = curtab ;
457+ # endif
453458#endif
454459 int unload_buf = (action != 0 );
455460 int del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE );
@@ -476,6 +481,16 @@ close_buffer(
476481 unload_buf = TRUE;
477482#endif
478483
484+ #ifdef FEAT_AUTOCMD
485+ /* Disallow deleting the buffer when it is locked (already being closed or
486+ * halfway a command that relies on it). Unloading is allowed. */
487+ if (buf -> b_locked > 0 && (del_buf || wipe_buf ))
488+ {
489+ EMSG (_ ("E937: Attempt to delete a buffer that is in use" ));
490+ return ;
491+ }
492+ #endif
493+
479494 if (win != NULL
480495#ifdef FEAT_WINDOWS
481496 && win_valid_any_tab (win ) /* in case autocommands closed the window */
@@ -499,7 +514,7 @@ close_buffer(
499514 /* When the buffer is no longer in a window, trigger BufWinLeave */
500515 if (buf -> b_nwindows == 1 )
501516 {
502- buf -> b_closing = TRUE ;
517+ ++ buf -> b_locked ;
503518 if (apply_autocmds (EVENT_BUFWINLEAVE , buf -> b_fname , buf -> b_fname ,
504519 FALSE, buf )
505520 && !bufref_valid (& bufref ))
@@ -509,7 +524,7 @@ close_buffer(
509524 EMSG (_ (e_auabort ));
510525 return ;
511526 }
512- buf -> b_closing = FALSE ;
527+ -- buf -> b_locked ;
513528 if (abort_if_last && one_window ())
514529 /* Autocommands made this the only window. */
515530 goto aucmd_abort ;
@@ -518,13 +533,13 @@ close_buffer(
518533 * BufHidden */
519534 if (!unload_buf )
520535 {
521- buf -> b_closing = TRUE ;
536+ ++ buf -> b_locked ;
522537 if (apply_autocmds (EVENT_BUFHIDDEN , buf -> b_fname , buf -> b_fname ,
523538 FALSE, buf )
524539 && !bufref_valid (& bufref ))
525540 /* Autocommands deleted the buffer. */
526541 goto aucmd_abort ;
527- buf -> b_closing = FALSE ;
542+ -- buf -> b_locked ;
528543 if (abort_if_last && one_window ())
529544 /* Autocommands made this the only window. */
530545 goto aucmd_abort ;
@@ -534,6 +549,19 @@ close_buffer(
534549 return ;
535550# endif
536551 }
552+
553+ # ifdef FEAT_WINDOWS
554+ /* If the buffer was in curwin and the window has changed, go back to that
555+ * window, if it still exists. This avoids that ":edit x" triggering a
556+ * "tabnext" BufUnload autocmd leaves a window behind without a buffer. */
557+ if (is_curwin && curwin != the_curwin && win_valid_any_tab (the_curwin ))
558+ {
559+ block_autocmds ();
560+ goto_tabpage_win (the_curtab , the_curwin );
561+ unblock_autocmds ();
562+ }
563+ # endif
564+
537565 nwindows = buf -> b_nwindows ;
538566#endif
539567
@@ -683,13 +711,13 @@ buf_freeall(buf_T *buf, int flags)
683711 int is_curbuf = (buf == curbuf );
684712 bufref_T bufref ;
685713# ifdef FEAT_WINDOWS
686- int is_curwin = (curwin != NULL && curwin -> w_buffer == buf );
714+ int is_curwin = (curwin != NULL && curwin -> w_buffer == buf );
687715 win_T * the_curwin = curwin ;
688716 tabpage_T * the_curtab = curtab ;
689717# endif
690718
691719 /* Make sure the buffer isn't closed by autocommands. */
692- buf -> b_closing = TRUE ;
720+ ++ buf -> b_locked ;
693721 set_bufref (& bufref , buf );
694722 if (buf -> b_ml .ml_mfp != NULL )
695723 {
@@ -715,7 +743,7 @@ buf_freeall(buf_T *buf, int flags)
715743 /* autocommands deleted the buffer */
716744 return ;
717745 }
718- buf -> b_closing = FALSE ;
746+ -- buf -> b_locked ;
719747
720748# ifdef FEAT_WINDOWS
721749 /* If the buffer was in curwin and the window has changed, go back to that
@@ -748,7 +776,7 @@ buf_freeall(buf_T *buf, int flags)
748776#endif
749777#ifdef FEAT_SYN_HL
750778 /* Remove any ownsyntax, unless exiting. */
751- if (firstwin != NULL && curwin -> w_buffer == buf )
779+ if (curwin != NULL && curwin -> w_buffer == buf )
752780 reset_synblock (curwin );
753781#endif
754782
@@ -764,7 +792,7 @@ buf_freeall(buf_T *buf, int flags)
764792 clearFolding (win );
765793 }
766794# else
767- if (curwin -> w_buffer == buf )
795+ if (curwin != NULL && curwin -> w_buffer == buf )
768796 clearFolding (curwin );
769797# endif
770798#endif
@@ -1373,7 +1401,7 @@ do_buffer(
13731401 */
13741402 while (buf == curbuf
13751403# ifdef FEAT_AUTOCMD
1376- && !(curwin -> w_closing || curwin -> w_buffer -> b_closing )
1404+ && !(curwin -> w_closing || curwin -> w_buffer -> b_locked > 0 )
13771405# endif
13781406 && (firstwin != lastwin || first_tabpage -> tp_next != NULL ))
13791407 {
@@ -5110,7 +5138,7 @@ ex_buffer_all(exarg_T *eap)
51105138#endif
51115139 ) && firstwin != lastwin
51125140#ifdef FEAT_AUTOCMD
5113- && !(wp -> w_closing || wp -> w_buffer -> b_closing )
5141+ && !(wp -> w_closing || wp -> w_buffer -> b_locked > 0 )
51145142#endif
51155143 )
51165144 {
0 commit comments