diff options
-rw-r--r-- | src/buffer.c | 20 | ||||
-rw-r--r-- | src/ex_cmds.c | 6 | ||||
-rw-r--r-- | src/fileio.c | 8 | ||||
-rw-r--r-- | src/globals.h | 5 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |