summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buffer.c20
-rw-r--r--src/ex_cmds.c6
-rw-r--r--src/fileio.c8
-rw-r--r--src/globals.h5
-rw-r--r--src/version.c2
5 files changed, 39 insertions, 2 deletions
diff --git a/src/buffer.c b/src/buffer.c
index c703465e3..3506dbb9a 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -676,8 +676,16 @@ free_buffer(buf)
#endif
#ifdef FEAT_AUTOCMD
aubuflocal_remove(buf);
+ if (autocmd_busy)
+ {
+ /* Do not free the buffer structure while autocommands are executing,
+ * it's still needed. Free it when autocmd_busy is reset. */
+ buf->b_next = au_pending_free_buf;
+ au_pending_free_buf = buf;
+ }
+ else
#endif
- vim_free(buf);
+ vim_free(buf);
}
/*
@@ -1681,7 +1689,11 @@ buflist_new(ffname, sfname, lnum, flags)
buf->b_p_bl = TRUE;
#ifdef FEAT_AUTOCMD
if (!(flags & BLN_DUMMY))
+ {
apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
+ if (!buf_valid(buf))
+ return NULL;
+ }
#endif
}
return buf;
@@ -1857,8 +1869,14 @@ buflist_new(ffname, sfname, lnum, flags)
if (!(flags & BLN_DUMMY))
{
apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf);
+ if (!buf_valid(buf))
+ return NULL;
if (flags & BLN_LISTED)
+ {
apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
+ if (!buf_valid(buf))
+ return NULL;
+ }
# ifdef FEAT_EVAL
if (aborting()) /* autocmds may abort script processing */
return NULL;
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 7ae4917a8..ac30f2c01 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3343,6 +3343,12 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin)
#endif
buf = buflist_new(ffname, sfname, 0L,
BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED));
+#ifdef FEAT_AUTOCMD
+ /* autocommands may change curwin and curbuf */
+ if (oldwin != NULL)
+ oldwin = curwin;
+ old_curbuf = curbuf;
+#endif
}
if (buf == NULL)
goto theend;
diff --git a/src/fileio.c b/src/fileio.c
index 17f36e7b0..f8b384b9e 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -9548,13 +9548,19 @@ apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
/*
* When stopping to execute autocommands, restore the search patterns and
- * the redo buffer.
+ * the redo buffer. Free buffers in the au_pending_free_buf list.
*/
if (!autocmd_busy)
{
restore_search_patterns();
restoreRedobuff();
did_filetype = FALSE;
+ while (au_pending_free_buf != NULL)
+ {
+ buf_T *b = au_pending_free_buf->b_next;
+ vim_free(au_pending_free_buf);
+ au_pending_free_buf = b;
+ }
}
/*
diff --git a/src/globals.h b/src/globals.h
index 028110336..a17430d06 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -386,6 +386,11 @@ EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when
/* When deleting the current buffer, another one must be loaded. If we know
* which one is preferred, au_new_curbuf is set to it */
EXTERN buf_T *au_new_curbuf INIT(= NULL);
+
+/* When deleting the buffer and autocmd_busy is TRUE, do not free the buffer
+ * but link it in the list starting with au_pending_free_buf, using b_next.
+ * Free the buffer when autocmd_busy is set to FALSE. */
+EXTERN buf_T *au_pending_free_buf INIT(= NULL);
#endif
#ifdef FEAT_MOUSE
diff --git a/src/version.c b/src/version.c
index ad38a7d0c..b74ea983c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -735,6 +735,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 251,
+/**/
250,
/**/
249,