mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
updated for version 7.3.545
Problem: When closing a window or buffer autocommands may close it too, causing problems for where the autocommand was invoked from. Solution: Add the w_closing and b_closing flags. When set disallow ":q" and ":close" to prevent recursive closing.
This commit is contained in:
36
src/buffer.c
36
src/buffer.c
@@ -377,28 +377,35 @@ close_buffer(win, buf, action, abort_if_last)
|
|||||||
/* When the buffer is no longer in a window, trigger BufWinLeave */
|
/* When the buffer is no longer in a window, trigger BufWinLeave */
|
||||||
if (buf->b_nwindows == 1)
|
if (buf->b_nwindows == 1)
|
||||||
{
|
{
|
||||||
|
buf->b_closing = TRUE;
|
||||||
apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
|
apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
|
||||||
FALSE, buf);
|
FALSE, buf);
|
||||||
/* Return if autocommands deleted the buffer or made it the only one. */
|
if (!buf_valid(buf))
|
||||||
if (!buf_valid(buf) || (abort_if_last && one_window()))
|
|
||||||
{
|
{
|
||||||
|
/* Autocommands deleted the buffer. */
|
||||||
|
aucmd_abort:
|
||||||
EMSG(_(e_auabort));
|
EMSG(_(e_auabort));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
buf->b_closing = FALSE;
|
||||||
|
if (abort_if_last && one_window())
|
||||||
|
/* Autocommands made this the only window. */
|
||||||
|
goto aucmd_abort;
|
||||||
|
|
||||||
/* When the buffer becomes hidden, but is not unloaded, trigger
|
/* When the buffer becomes hidden, but is not unloaded, trigger
|
||||||
* BufHidden */
|
* BufHidden */
|
||||||
if (!unload_buf)
|
if (!unload_buf)
|
||||||
{
|
{
|
||||||
|
buf->b_closing = TRUE;
|
||||||
apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname,
|
apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname,
|
||||||
FALSE, buf);
|
FALSE, buf);
|
||||||
/* Return if autocommands deleted the buffer or made it the only
|
if (!buf_valid(buf))
|
||||||
* one. */
|
/* Autocommands deleted the buffer. */
|
||||||
if (!buf_valid(buf) || (abort_if_last && one_window()))
|
goto aucmd_abort;
|
||||||
{
|
buf->b_closing = FALSE;
|
||||||
EMSG(_(e_auabort));
|
if (abort_if_last && one_window())
|
||||||
return;
|
/* Autocommands made this the only window. */
|
||||||
}
|
goto aucmd_abort;
|
||||||
}
|
}
|
||||||
# ifdef FEAT_EVAL
|
# ifdef FEAT_EVAL
|
||||||
if (aborting()) /* autocmds may abort script processing */
|
if (aborting()) /* autocmds may abort script processing */
|
||||||
@@ -552,6 +559,7 @@ buf_freeall(buf, flags)
|
|||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
int is_curbuf = (buf == curbuf);
|
int is_curbuf = (buf == curbuf);
|
||||||
|
|
||||||
|
buf->b_closing = TRUE;
|
||||||
apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf);
|
apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf);
|
||||||
if (!buf_valid(buf)) /* autocommands may delete the buffer */
|
if (!buf_valid(buf)) /* autocommands may delete the buffer */
|
||||||
return;
|
return;
|
||||||
@@ -568,6 +576,7 @@ buf_freeall(buf, flags)
|
|||||||
if (!buf_valid(buf)) /* autocommands may delete the buffer */
|
if (!buf_valid(buf)) /* autocommands may delete the buffer */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
buf->b_closing = FALSE;
|
||||||
# ifdef FEAT_EVAL
|
# ifdef FEAT_EVAL
|
||||||
if (aborting()) /* autocmds may abort script processing */
|
if (aborting()) /* autocmds may abort script processing */
|
||||||
return;
|
return;
|
||||||
@@ -1150,6 +1159,9 @@ do_buffer(action, start, dir, count, forceit)
|
|||||||
* a window with this buffer.
|
* a window with this buffer.
|
||||||
*/
|
*/
|
||||||
while (buf == curbuf
|
while (buf == curbuf
|
||||||
|
# ifdef FEAT_AUTOCMD
|
||||||
|
&& !(curwin->w_closing || curwin->w_buffer->b_closing)
|
||||||
|
# endif
|
||||||
&& (firstwin != lastwin || first_tabpage->tp_next != NULL))
|
&& (firstwin != lastwin || first_tabpage->tp_next != NULL))
|
||||||
win_close(curwin, FALSE);
|
win_close(curwin, FALSE);
|
||||||
#endif
|
#endif
|
||||||
@@ -4750,7 +4762,11 @@ ex_buffer_all(eap)
|
|||||||
#ifdef FEAT_WINDOWS
|
#ifdef FEAT_WINDOWS
|
||||||
|| (had_tab > 0 && wp != firstwin)
|
|| (had_tab > 0 && wp != firstwin)
|
||||||
#endif
|
#endif
|
||||||
) && firstwin != lastwin)
|
) && firstwin != lastwin
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
&& !(wp->w_closing || wp->w_buffer->b_closing)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
win_close(wp, FALSE);
|
win_close(wp, FALSE);
|
||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
|
@@ -6459,7 +6459,9 @@ ex_quit(eap)
|
|||||||
}
|
}
|
||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
|
apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
|
||||||
if (curbuf_locked())
|
/* Refuse to quick when locked or when the buffer in the last window is
|
||||||
|
* being closed (can only happen in autocommands). */
|
||||||
|
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -1201,6 +1201,10 @@ struct dictvar_S
|
|||||||
typedef struct qf_info_S qf_info_T;
|
typedef struct qf_info_S qf_info_T;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are items normally related to a buffer. But when using ":ownsyntax"
|
||||||
|
* a window may have its own instance.
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
#ifdef FEAT_SYN_HL
|
#ifdef FEAT_SYN_HL
|
||||||
hashtab_T b_keywtab; /* syntax keywords hash table */
|
hashtab_T b_keywtab; /* syntax keywords hash table */
|
||||||
@@ -1290,6 +1294,10 @@ struct file_buffer
|
|||||||
int b_nwindows; /* nr of windows open on this buffer */
|
int b_nwindows; /* nr of windows open on this buffer */
|
||||||
|
|
||||||
int b_flags; /* various BF_ flags */
|
int b_flags; /* various BF_ flags */
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
int b_closing; /* buffer is being closed, don't let
|
||||||
|
autocommands close it too. */
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* b_ffname has the full path of the file (NULL for no name).
|
* b_ffname has the full path of the file (NULL for no name).
|
||||||
@@ -1853,6 +1861,10 @@ struct window_S
|
|||||||
win_T *w_prev; /* link to previous window */
|
win_T *w_prev; /* link to previous window */
|
||||||
win_T *w_next; /* link to next window */
|
win_T *w_next; /* link to next window */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
int w_closing; /* window is being closed, don't let
|
||||||
|
autocommands close it too. */
|
||||||
|
#endif
|
||||||
|
|
||||||
frame_T *w_frame; /* frame containing this window */
|
frame_T *w_frame; /* frame containing this window */
|
||||||
|
|
||||||
|
@@ -714,6 +714,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
545,
|
||||||
/**/
|
/**/
|
||||||
544,
|
544,
|
||||||
/**/
|
/**/
|
||||||
|
45
src/window.c
45
src/window.c
@@ -2034,7 +2034,11 @@ close_windows(buf, keep_curwin)
|
|||||||
|
|
||||||
for (wp = firstwin; wp != NULL && lastwin != firstwin; )
|
for (wp = firstwin; wp != NULL && lastwin != firstwin; )
|
||||||
{
|
{
|
||||||
if (wp->w_buffer == buf && (!keep_curwin || wp != curwin))
|
if (wp->w_buffer == buf && (!keep_curwin || wp != curwin)
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
&& !(wp->w_closing || wp->w_buffer->b_closing)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
win_close(wp, FALSE);
|
win_close(wp, FALSE);
|
||||||
|
|
||||||
@@ -2051,7 +2055,11 @@ close_windows(buf, keep_curwin)
|
|||||||
nexttp = tp->tp_next;
|
nexttp = tp->tp_next;
|
||||||
if (tp != curtab)
|
if (tp != curtab)
|
||||||
for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
|
for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
|
||||||
if (wp->w_buffer == buf)
|
if (wp->w_buffer == buf
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
&& !(wp->w_closing || wp->w_buffer->b_closing)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
win_close_othertab(wp, FALSE, tp);
|
win_close_othertab(wp, FALSE, tp);
|
||||||
|
|
||||||
@@ -2168,6 +2176,8 @@ win_close(win, free_buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
|
if (win->w_closing || win->w_buffer->b_closing)
|
||||||
|
return; /* window is already being closed */
|
||||||
if (win == aucmd_win)
|
if (win == aucmd_win)
|
||||||
{
|
{
|
||||||
EMSG(_("E813: Cannot close autocmd window"));
|
EMSG(_("E813: Cannot close autocmd window"));
|
||||||
@@ -2203,17 +2213,26 @@ win_close(win, free_buf)
|
|||||||
wp = frame2win(win_altframe(win, NULL));
|
wp = frame2win(win_altframe(win, NULL));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Be careful: If autocommands delete the window, return now.
|
* Be careful: If autocommands delete the window or cause this window
|
||||||
|
* to be the last one left, return now.
|
||||||
*/
|
*/
|
||||||
if (wp->w_buffer != curbuf)
|
if (wp->w_buffer != curbuf)
|
||||||
{
|
{
|
||||||
other_buffer = TRUE;
|
other_buffer = TRUE;
|
||||||
|
win->w_closing = TRUE;
|
||||||
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
|
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
|
||||||
if (!win_valid(win) || last_window())
|
if (!win_valid(win))
|
||||||
|
return;
|
||||||
|
win->w_closing = FALSE;
|
||||||
|
if (last_window())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
win->w_closing = TRUE;
|
||||||
apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
|
apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
|
||||||
if (!win_valid(win) || last_window())
|
if (!win_valid(win))
|
||||||
|
return;
|
||||||
|
win->w_closing = FALSE;
|
||||||
|
if (last_window())
|
||||||
return;
|
return;
|
||||||
# ifdef FEAT_EVAL
|
# ifdef FEAT_EVAL
|
||||||
/* autocmds may abort script processing */
|
/* autocmds may abort script processing */
|
||||||
@@ -2240,7 +2259,16 @@ win_close(win, free_buf)
|
|||||||
* Close the link to the buffer.
|
* Close the link to the buffer.
|
||||||
*/
|
*/
|
||||||
if (win->w_buffer != NULL)
|
if (win->w_buffer != NULL)
|
||||||
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, TRUE);
|
{
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
win->w_closing = TRUE;
|
||||||
|
#endif
|
||||||
|
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE);
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
if (win_valid(win))
|
||||||
|
win->w_closing = FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Autocommands may have closed the window already, or closed the only
|
/* Autocommands may have closed the window already, or closed the only
|
||||||
* other window or moved to another tab page. */
|
* other window or moved to another tab page. */
|
||||||
@@ -2346,6 +2374,11 @@ win_close_othertab(win, free_buf, tp)
|
|||||||
tabpage_T *ptp = NULL;
|
tabpage_T *ptp = NULL;
|
||||||
int free_tp = FALSE;
|
int free_tp = FALSE;
|
||||||
|
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
if (win->w_closing || win->w_buffer->b_closing)
|
||||||
|
return; /* window is already being closed */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Close the link to the buffer. */
|
/* Close the link to the buffer. */
|
||||||
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE);
|
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user