From 2bc127f94016801250f8f24234f90a5182d77e73 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 13:57:40 +0200 Subject: [PATCH 01/10] patch 7.4.2016 Problem: Warning from MinGW about _WIN32_WINNT redefined. (John Marriott) Solution: First undefine it. (Ken Takata) --- src/Make_cyg_ming.mak | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index 005df196ae..e0638abb9b 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -893,7 +893,7 @@ if_perl.c: if_perl.xs typemap $(PERLTYPEMAP) if_perl.xs > $@ $(OUTDIR)/iscygpty.o: iscygpty.c $(CUI_INCL) - $(CC) -c $(CFLAGS) iscygpty.c -o $(OUTDIR)/iscygpty.o -D_WIN32_WINNT=0x0600 -DUSE_DYNFILEID -DENABLE_STUB_IMPL + $(CC) -c $(CFLAGS) iscygpty.c -o $(OUTDIR)/iscygpty.o -U_WIN32_WINNT -D_WIN32_WINNT=0x0600 -DUSE_DYNFILEID -DENABLE_STUB_IMPL $(OUTDIR)/main.o: main.c $(INCL) $(CUI_INCL) $(CC) -c $(CFLAGS) main.c -o $(OUTDIR)/main.o diff --git a/src/version.c b/src/version.c index b2dc76ec3d..cce37b19f1 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2016, /**/ 2015, /**/ From 8240433f48f7383c281ba2453cc55f10b8ec47d9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 17:00:38 +0200 Subject: [PATCH 02/10] patch 7.4.2017 Problem: When there are many errors adding them to the quickfix list takes a long time. Solution: Add BLN_NOOPT. Don't call buf_valid() in buf_copy_options(). Remember the last file name used. When going through the buffer list start from the end of the list. Only call buf_valid() when autocommands were executed. --- src/buffer.c | 61 +++++++++++++++++++++++++++++--------------------- src/option.c | 6 ----- src/quickfix.c | 31 ++++++++++++++++++++++--- src/version.c | 2 ++ src/vim.h | 1 + 5 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index b434d58e90..586ab3848c 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -316,7 +316,9 @@ buf_valid(buf_T *buf) { buf_T *bp; - for (bp = firstbuf; bp != NULL; bp = bp->b_next) + /* Assume that we more often have a recent buffer, start with the last + * one. */ + for (bp = lastbuf; bp != NULL; bp = bp->b_prev) if (bp == buf) return TRUE; return FALSE; @@ -397,9 +399,9 @@ close_buffer( if (buf->b_nwindows == 1) { buf->b_closing = TRUE; - apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) + if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, + FALSE, buf) + && !buf_valid(buf)) { /* Autocommands deleted the buffer. */ aucmd_abort: @@ -416,9 +418,9 @@ aucmd_abort: if (!unload_buf) { buf->b_closing = TRUE; - apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) + if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, + FALSE, buf) + && !buf_valid(buf)) /* Autocommands deleted the buffer. */ goto aucmd_abort; buf->b_closing = FALSE; @@ -577,21 +579,23 @@ buf_freeall(buf_T *buf, int flags) buf->b_closing = TRUE; if (buf->b_ml.ml_mfp != NULL) { - apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf); - if (!buf_valid(buf)) /* autocommands may delete the buffer */ + if (apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, + FALSE, buf) + && !buf_valid(buf)) /* autocommands may delete the buffer */ return; } if ((flags & BFA_DEL) && buf->b_p_bl) { - apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, FALSE, buf); - if (!buf_valid(buf)) /* autocommands may delete the buffer */ + if (apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, + FALSE, buf) + && !buf_valid(buf)) /* autocommands may delete the buffer */ return; } if (flags & BFA_WIPE) { - apply_autocmds(EVENT_BUFWIPEOUT, buf->b_fname, buf->b_fname, - FALSE, buf); - if (!buf_valid(buf)) /* autocommands may delete the buffer */ + if (apply_autocmds(EVENT_BUFWIPEOUT, buf->b_fname, buf->b_fname, + FALSE, buf) + && !buf_valid(buf)) /* autocommands may delete the buffer */ return; } buf->b_closing = FALSE; @@ -1452,11 +1456,11 @@ set_curbuf(buf_T *buf, int action) prevbuf = curbuf; #ifdef FEAT_AUTOCMD - apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); + if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf) # ifdef FEAT_EVAL - if (buf_valid(prevbuf) && !aborting()) + || (buf_valid(prevbuf) && !aborting())) # else - if (buf_valid(prevbuf)) + || buf_valid(prevbuf)) # endif #endif { @@ -1654,6 +1658,8 @@ do_autochdir(void) * If (flags & BLN_LISTED) is TRUE, add new buffer to buffer list. * If (flags & BLN_DUMMY) is TRUE, don't count it as a real buffer. * If (flags & BLN_NEW) is TRUE, don't use an existing buffer. + * If (flags & BLN_NOOPT) is TRUE, don't copy options from the current buffer + * if the buffer already exists. * This is the ONLY way to create a new buffer. */ static int top_file_num = 1; /* highest file number */ @@ -1692,17 +1698,20 @@ buflist_new( vim_free(ffname); if (lnum != 0) buflist_setfpos(buf, curwin, lnum, (colnr_T)0, FALSE); - /* copy the options now, if 'cpo' doesn't have 's' and not done - * already */ - buf_copy_options(buf, 0); + + if ((flags & BLN_NOOPT) == 0) + /* copy the options now, if 'cpo' doesn't have 's' and not done + * already */ + buf_copy_options(buf, 0); + if ((flags & BLN_LISTED) && !buf->b_p_bl) { buf->b_p_bl = TRUE; #ifdef FEAT_AUTOCMD if (!(flags & BLN_DUMMY)) { - apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf); - if (!buf_valid(buf)) + if (apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf) + && !buf_valid(buf)) return NULL; } #endif @@ -1881,13 +1890,13 @@ buflist_new( /* Tricky: these autocommands may change the buffer list. They could * also split the window with re-using the one empty buffer. This may * result in unexpectedly losing the empty buffer. */ - apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf); - if (!buf_valid(buf)) + if (apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf) + && !buf_valid(buf)) return NULL; if (flags & BLN_LISTED) { - apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf); - if (!buf_valid(buf)) + if (apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf) + && !buf_valid(buf)) return NULL; } # ifdef FEAT_EVAL diff --git a/src/option.c b/src/option.c index 95f4c734ac..fbf07600ed 100644 --- a/src/option.c +++ b/src/option.c @@ -10634,12 +10634,6 @@ buf_copy_options(buf_T *buf, int flags) int dont_do_help; int did_isk = FALSE; - /* - * Don't do anything if the buffer is invalid. - */ - if (buf == NULL || !buf_valid(buf)) - return; - /* * Skip this when the option defaults have not been set yet. Happens when * main() allocates the first buffer. diff --git a/src/quickfix.c b/src/quickfix.c index 92a0204174..065216afe1 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -1482,6 +1482,13 @@ copy_loclist(win_T *from, win_T *to) to->w_llist->qf_curlist = qi->qf_curlist; /* current list */ } +/* + * Looking up a buffer can be slow if there are many. Remember the last one + * to make this a lot faster if there are multiple matches in the same file. + */ +static char_u *qf_last_bufname = NULL; +static buf_T *qf_last_buf = NULL; + /* * Get buffer number for file "dir.name". * Also sets the b_has_qf_entry flag. @@ -1489,8 +1496,9 @@ copy_loclist(win_T *from, win_T *to) static int qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) { - char_u *ptr; + char_u *ptr = NULL; buf_T *buf; + char_u *bufname; if (fname == NULL || *fname == NUL) /* no file name */ return 0; @@ -1522,13 +1530,30 @@ qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) ptr = vim_strsave(fname); } /* Use concatenated directory name and file name */ - buf = buflist_new(ptr, NULL, (linenr_T)0, 0); + bufname = ptr; + } + else + bufname = fname; + + if (qf_last_bufname != NULL && STRCMP(bufname, qf_last_bufname) == 0 + && buf_valid(qf_last_buf)) + { + buf = qf_last_buf; vim_free(ptr); } else - buf = buflist_new(fname, NULL, (linenr_T)0, 0); + { + vim_free(qf_last_bufname); + buf = buflist_new(bufname, NULL, (linenr_T)0, BLN_NOOPT); + if (bufname == ptr) + qf_last_bufname = bufname; + else + qf_last_bufname = vim_strsave(bufname); + qf_last_buf = buf; + } if (buf == NULL) return 0; + buf->b_has_qf_entry = TRUE; return buf->b_fnum; } diff --git a/src/version.c b/src/version.c index cce37b19f1..0d39ffa624 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2017, /**/ 2016, /**/ diff --git a/src/vim.h b/src/vim.h index 7d76504bbc..4d6f9340d1 100644 --- a/src/vim.h +++ b/src/vim.h @@ -941,6 +941,7 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname); #define BLN_LISTED 2 /* put new buffer in buffer list */ #define BLN_DUMMY 4 /* allocating dummy buffer */ #define BLN_NEW 8 /* create a new buffer */ +#define BLN_NOOPT 16 /* don't copy options to existing buffer */ /* Values for in_cinkeys() */ #define KEY_OPEN_FORW 0x101 From b25f9a97e9aad3cbb4bc3fe87cdbd5700f8aa0c6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 18:21:50 +0200 Subject: [PATCH 03/10] patch 7.4.2018 Problem: buf_valid() can be slow when there are many buffers. Solution: Add bufref_valid(), only go through the buffer list when a buffer was freed. --- src/buffer.c | 117 ++++++++++++++++++++++++++++++++++--------- src/proto/buffer.pro | 2 + src/quickfix.c | 8 +-- src/structs.h | 8 +++ src/version.c | 2 + 5 files changed, 108 insertions(+), 29 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 586ab3848c..8fe2b8a597 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -67,6 +67,9 @@ static char *msg_qflist = N_("[Quickfix List]"); static char *e_auabort = N_("E855: Autocommands caused command to abort"); #endif +/* Number of times free_buffer() was called. */ +static int buf_free_count = 0; + /* * Open current buffer, that is: open the memfile and read the file into * memory. @@ -308,8 +311,30 @@ open_buffer( return retval; } +/* + * Store "buf" in "bufref" and set the free count. + */ + void +set_bufref(bufref_T *bufref, buf_T *buf) +{ + bufref->br_buf = buf; + bufref->br_buf_free_count = buf_free_count; +} + +/* + * Return TRUE if "bufref->br_buf" points to a valid buffer. + * Only goes through the buffer list if buf_free_count changed. + */ + int +bufref_valid(bufref_T *bufref) +{ + return bufref->br_buf_free_count == buf_free_count + ? TRUE : buf_valid(bufref->br_buf); +} + /* * Return TRUE if "buf" points to a valid buffer (in the buffer list). + * This can be slow if there are many buffers, prefer using bufref_valid(). */ int buf_valid(buf_T *buf) @@ -351,6 +376,7 @@ close_buffer( #ifdef FEAT_AUTOCMD int is_curbuf; int nwindows; + bufref_T bufref; #endif int unload_buf = (action != 0); int del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE); @@ -395,13 +421,15 @@ close_buffer( } #ifdef FEAT_AUTOCMD + set_bufref(&bufref, buf); + /* When the buffer is no longer in a window, trigger BufWinLeave */ if (buf->b_nwindows == 1) { buf->b_closing = TRUE; if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, FALSE, buf) - && !buf_valid(buf)) + && !bufref_valid(&bufref)) { /* Autocommands deleted the buffer. */ aucmd_abort: @@ -420,7 +448,7 @@ aucmd_abort: buf->b_closing = TRUE; if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, FALSE, buf) - && !buf_valid(buf)) + && !bufref_valid(&bufref)) /* Autocommands deleted the buffer. */ goto aucmd_abort; buf->b_closing = FALSE; @@ -464,7 +492,7 @@ aucmd_abort: #ifdef FEAT_AUTOCMD /* Autocommands may have deleted the buffer. */ - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) return; # ifdef FEAT_EVAL if (aborting()) /* autocmds may abort script processing */ @@ -575,27 +603,32 @@ buf_freeall(buf_T *buf, int flags) { #ifdef FEAT_AUTOCMD int is_curbuf = (buf == curbuf); + bufref_T bufref; buf->b_closing = TRUE; + set_bufref(&bufref, buf); if (buf->b_ml.ml_mfp != NULL) { if (apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf) - && !buf_valid(buf)) /* autocommands may delete the buffer */ + && !bufref_valid(&bufref)) + /* autocommands deleted the buffer */ return; } if ((flags & BFA_DEL) && buf->b_p_bl) { if (apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, FALSE, buf) - && !buf_valid(buf)) /* autocommands may delete the buffer */ + && !bufref_valid(&bufref)) + /* autocommands deleted the buffer */ return; } if (flags & BFA_WIPE) { if (apply_autocmds(EVENT_BUFWIPEOUT, buf->b_fname, buf->b_fname, FALSE, buf) - && !buf_valid(buf)) /* autocommands may delete the buffer */ + && !bufref_valid(&bufref)) + /* autocommands deleted the buffer */ return; } buf->b_closing = FALSE; @@ -662,6 +695,7 @@ buf_freeall(buf_T *buf, int flags) static void free_buffer(buf_T *buf) { + ++buf_free_count; free_buffer_stuff(buf, TRUE); #ifdef FEAT_EVAL unref_var_dict(buf->b_vars); @@ -1027,6 +1061,7 @@ empty_curbuf( { int retval; buf_T *buf = curbuf; + bufref_T bufref; if (action == DOBUF_UNLOAD) { @@ -1034,13 +1069,12 @@ empty_curbuf( return FAIL; } - if (close_others) - { - /* Close any other windows on this buffer, then make it empty. */ + set_bufref(&bufref, buf); #ifdef FEAT_WINDOWS + if (close_others) + /* Close any other windows on this buffer, then make it empty. */ close_windows(buf, TRUE); #endif - } setpcmark(); retval = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, @@ -1051,7 +1085,7 @@ empty_curbuf( * the old one. But do_ecmd() may have done that already, check * if the buffer still exists. */ - if (buf != curbuf && buf_valid(buf) && buf->b_nwindows == 0) + if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows == 0) close_buffer(NULL, buf, action, FALSE); if (!close_others) need_fileinfo = FALSE; @@ -1177,6 +1211,11 @@ do_buffer( if (unload) { int forward; +# if defined(FEAT_AUTOCMD) || defined(FEAT_WINDOWS) + bufref_T bufref; + + set_bufref(&bufref, buf); +# endif /* When unloading or deleting a buffer that's already unloaded and * unlisted: fail silently. */ @@ -1190,7 +1229,7 @@ do_buffer( { dialog_changed(buf, FALSE); # ifdef FEAT_AUTOCMD - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) /* Autocommand deleted buffer, oops! It's not changed * now. */ return FAIL; @@ -1243,9 +1282,10 @@ do_buffer( { #ifdef FEAT_WINDOWS close_windows(buf, FALSE); + if (buf != curbuf && bufref_valid(&bufref)) #endif - if (buf != curbuf && buf_valid(buf) && buf->b_nwindows <= 0) - close_buffer(NULL, buf, action, FALSE); + if (buf->b_nwindows <= 0) + close_buffer(NULL, buf, action, FALSE); return OK; } @@ -1390,9 +1430,14 @@ do_buffer( #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) if ((p_confirm || cmdmod.confirm) && p_write) { +# ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, buf); +# endif dialog_changed(curbuf, FALSE); # ifdef FEAT_AUTOCMD - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) /* Autocommand deleted buffer, oops! */ return FAIL; # endif @@ -1443,6 +1488,9 @@ set_curbuf(buf_T *buf, int action) #ifdef FEAT_SYN_HL long old_tw = curbuf->b_p_tw; #endif +#ifdef FEAT_AUTOCMD + bufref_T bufref; +#endif setpcmark(); if (!cmdmod.keepalt) @@ -1456,11 +1504,12 @@ set_curbuf(buf_T *buf, int action) prevbuf = curbuf; #ifdef FEAT_AUTOCMD + set_bufref(&bufref, prevbuf); if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf) # ifdef FEAT_EVAL - || (buf_valid(prevbuf) && !aborting())) + || (bufref_valid(&bufref) && !aborting())) # else - || buf_valid(prevbuf)) + || bufref_valid(&bufref)) # endif #endif { @@ -1473,9 +1522,9 @@ set_curbuf(buf_T *buf, int action) close_windows(prevbuf, FALSE); #endif #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) - if (buf_valid(prevbuf) && !aborting()) + if (bufref_valid(&bufref) && !aborting()) #else - if (buf_valid(prevbuf)) + if (bufref_valid(&bufref)) #endif { #ifdef FEAT_WINDOWS @@ -1496,7 +1545,7 @@ set_curbuf(buf_T *buf, int action) } #ifdef FEAT_AUTOCMD /* An autocommand may have deleted "buf", already entered it (e.g., when - * it did ":bunload") or aborted the script processing! + * it did ":bunload") or aborted the script processing. * If curwin->w_buffer is null, enter_buffer() will make it valid again */ if ((buf_valid(buf) && buf != curbuf # ifdef FEAT_EVAL @@ -1706,12 +1755,16 @@ buflist_new( if ((flags & BLN_LISTED) && !buf->b_p_bl) { +#ifdef FEAT_AUTOCMD + bufref_T bufref; +#endif buf->b_p_bl = TRUE; #ifdef FEAT_AUTOCMD + set_bufref(&bufref, buf); if (!(flags & BLN_DUMMY)) { if (apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf) - && !buf_valid(buf)) + && !bufref_valid(&bufref)) return NULL; } #endif @@ -1887,16 +1940,19 @@ buflist_new( #ifdef FEAT_AUTOCMD if (!(flags & BLN_DUMMY)) { + bufref_T bufref; + /* Tricky: these autocommands may change the buffer list. They could * also split the window with re-using the one empty buffer. This may * result in unexpectedly losing the empty buffer. */ + set_bufref(&bufref, buf); if (apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf) - && !buf_valid(buf)) + && !bufref_valid(&bufref)) return NULL; if (flags & BLN_LISTED) { if (apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf) - && !buf_valid(buf)) + && !bufref_valid(&bufref)) return NULL; } # ifdef FEAT_EVAL @@ -4708,10 +4764,15 @@ do_arg_all( if (!P_HID(buf) && buf->b_nwindows <= 1 && bufIsChanged(buf)) { +#ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, buf); +#endif (void)autowrite(buf, FALSE); #ifdef FEAT_AUTOCMD /* check if autocommands removed the window */ - if (!win_valid(wp) || !buf_valid(buf)) + if (!win_valid(wp) || !bufref_valid(&bufref)) { wpnext = firstwin; /* start all over... */ continue; @@ -4993,6 +5054,11 @@ ex_buffer_all(exarg_T *eap) if (wp == NULL && split_ret == OK) { +#ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, buf); +#endif /* Split the window and put the buffer in it */ p_ea_save = p_ea; p_ea = TRUE; /* use space from all windows */ @@ -5008,8 +5074,9 @@ ex_buffer_all(exarg_T *eap) #endif set_curbuf(buf, DOBUF_GOTO); #ifdef FEAT_AUTOCMD - if (!buf_valid(buf)) /* autocommands deleted the buffer!!! */ + if (!bufref_valid(&bufref)) { + /* autocommands deleted the buffer!!! */ #if defined(HAS_SWAP_EXISTS_ACTION) swap_exists_action = SEA_NONE; # endif diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro index 71217287a6..e2adf5c9f5 100644 --- a/src/proto/buffer.pro +++ b/src/proto/buffer.pro @@ -1,5 +1,7 @@ /* buffer.c */ int open_buffer(int read_stdin, exarg_T *eap, int flags); +void set_bufref(bufref_T *bufref, buf_T *buf); +int bufref_valid(bufref_T *bufref); int buf_valid(buf_T *buf); void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last); void buf_clear_file(buf_T *buf); diff --git a/src/quickfix.c b/src/quickfix.c index 065216afe1..1e5abc69e6 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -1487,7 +1487,7 @@ copy_loclist(win_T *from, win_T *to) * to make this a lot faster if there are multiple matches in the same file. */ static char_u *qf_last_bufname = NULL; -static buf_T *qf_last_buf = NULL; +static bufref_T qf_last_bufref = {NULL, 0}; /* * Get buffer number for file "dir.name". @@ -1536,9 +1536,9 @@ qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) bufname = fname; if (qf_last_bufname != NULL && STRCMP(bufname, qf_last_bufname) == 0 - && buf_valid(qf_last_buf)) + && bufref_valid(&qf_last_bufref)) { - buf = qf_last_buf; + buf = qf_last_bufref.br_buf; vim_free(ptr); } else @@ -1549,7 +1549,7 @@ qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) qf_last_bufname = bufname; else qf_last_bufname = vim_strsave(bufname); - qf_last_buf = buf; + set_bufref(&qf_last_bufref, buf); } if (buf == NULL) return 0; diff --git a/src/structs.h b/src/structs.h index 05f4617059..e092e6b2d8 100644 --- a/src/structs.h +++ b/src/structs.h @@ -69,6 +69,14 @@ typedef struct frame_S frame_T; typedef int scid_T; /* script ID */ typedef struct file_buffer buf_T; /* forward declaration */ +/* Reference to a buffer that stores the value of buf_free_count. + * bufref_valid() only needs to check "buf" when the count differs. + */ +typedef struct { + buf_T *br_buf; + int br_buf_free_count; +} bufref_T; + /* * This is here because regexp.h needs pos_T and below regprog_T is used. */ diff --git a/src/version.c b/src/version.c index 0d39ffa624..7317edf217 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2018, /**/ 2017, /**/ From c4a927ca8dc383190d5df2cacd3f966698b6190c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 18:24:27 +0200 Subject: [PATCH 04/10] patch 7.4.2019 Problem: When ignoring case utf_fold() may consume a lot of time. Solution: Optimize for ASCII. --- src/mbyte.c | 3 +++ src/version.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/mbyte.c b/src/mbyte.c index 49057000ff..7bc184ba24 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -3067,6 +3067,9 @@ utf_convert( int utf_fold(int a) { + if (a < 0x80) + /* be fast for ASCII */ + return a >= 0x41 && a <= 0x5a ? a + 32 : a; return utf_convert(a, foldCase, (int)sizeof(foldCase)); } diff --git a/src/version.c b/src/version.c index 7317edf217..8013b459d4 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2019, /**/ 2018, /**/ From 453f37dbfd6f8304a36ea84e40a9965404206186 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 18:33:59 +0200 Subject: [PATCH 05/10] patch 7.4.2020 Problem: Can't build without +autocmd feature. Solution: Adjust #ifdefs. --- src/buffer.c | 4 +--- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 8fe2b8a597..3507f94ca8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1488,9 +1488,7 @@ set_curbuf(buf_T *buf, int action) #ifdef FEAT_SYN_HL long old_tw = curbuf->b_p_tw; #endif -#ifdef FEAT_AUTOCMD bufref_T bufref; -#endif setpcmark(); if (!cmdmod.keepalt) @@ -1502,9 +1500,9 @@ set_curbuf(buf_T *buf, int action) /* close_windows() or apply_autocmds() may change curbuf */ prevbuf = curbuf; + set_bufref(&bufref, prevbuf); #ifdef FEAT_AUTOCMD - set_bufref(&bufref, prevbuf); if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf) # ifdef FEAT_EVAL || (bufref_valid(&bufref) && !aborting())) diff --git a/src/version.c b/src/version.c index 8013b459d4..ebaef410d6 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2020, /**/ 2019, /**/ From 19ff9bf454b7492be64dd87aaf0830fa7961871e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 19:03:57 +0200 Subject: [PATCH 06/10] patch 7.4.2021 Problem: Still too many buf_valid() calls. Solution: Make au_new_curbuf a bufref. Use bufref_valid() in more places. --- src/buffer.c | 6 +++--- src/ex_cmds.c | 26 ++++++++++++++++++-------- src/globals.h | 2 +- src/version.c | 2 ++ 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 3507f94ca8..409564b966 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1293,7 +1293,7 @@ do_buffer( * Deleting the current buffer: Need to find another buffer to go to. * There should be another, otherwise it would have been handled * above. However, autocommands may have deleted all buffers. - * First use au_new_curbuf, if it is valid. + * First use au_new_curbuf.br_buf, if it is valid. * Then prefer the buffer we most recently visited. * Else try to find one that is loaded, after the current buffer, * then before the current buffer. @@ -1302,8 +1302,8 @@ do_buffer( buf = NULL; /* selected buffer */ bp = NULL; /* used when no loaded buffer found */ #ifdef FEAT_AUTOCMD - if (au_new_curbuf != NULL && buf_valid(au_new_curbuf)) - buf = au_new_curbuf; + if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)) + buf = au_new_curbuf.br_buf; # ifdef FEAT_JUMPLIST else # endif diff --git a/src/ex_cmds.c b/src/ex_cmds.c index d93a7ec7fc..3e29d76892 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3447,11 +3447,16 @@ do_wqall(exarg_T *eap) } else { +#ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, buf); +#endif if (buf_write_all(buf, eap->forceit) == FAIL) ++error; #ifdef FEAT_AUTOCMD /* an autocommand may have deleted the buffer */ - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) buf = firstbuf; #endif } @@ -3659,6 +3664,7 @@ do_ecmd( int did_set_swapcommand = FALSE; #endif buf_T *buf; + bufref_T bufref; #if defined(FEAT_AUTOCMD) || defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) buf_T *old_curbuf = curbuf; #endif @@ -3863,10 +3869,11 @@ do_ecmd( else /* existing memfile */ { oldbuf = TRUE; + set_bufref(&bufref, buf); (void)buf_check_timestamp(buf, FALSE); /* Check if autocommands made buffer invalid or changed the current * buffer. */ - if (!buf_valid(buf) + if (!bufref_valid(&bufref) #ifdef FEAT_AUTOCMD || curbuf != old_curbuf #endif @@ -3908,10 +3915,11 @@ do_ecmd( */ if (buf->b_fname != NULL) new_name = vim_strsave(buf->b_fname); - au_new_curbuf = buf; + set_bufref(&au_new_curbuf, buf); apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); - if (!buf_valid(buf)) /* new buffer has been deleted */ + if (!bufref_valid(&au_new_curbuf)) { + /* new buffer has been deleted */ delbuf_msg(new_name); /* frees new_name */ goto theend; } @@ -3951,8 +3959,9 @@ do_ecmd( } # endif /* Be careful again, like above. */ - if (!buf_valid(buf)) /* new buffer has been deleted */ + if (!bufref_valid(&au_new_curbuf)) { + /* new buffer has been deleted */ delbuf_msg(new_name); /* frees new_name */ goto theend; } @@ -3995,7 +4004,7 @@ do_ecmd( #ifdef FEAT_AUTOCMD } vim_free(new_name); - au_new_curbuf = NULL; + au_new_curbuf.br_buf = NULL; #endif } @@ -4071,6 +4080,7 @@ do_ecmd( new_name = vim_strsave(buf->b_fname); else new_name = NULL; + set_bufref(&bufref, buf); #endif if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) { @@ -4091,7 +4101,7 @@ do_ecmd( #ifdef FEAT_AUTOCMD /* If autocommands deleted the buffer we were going to re-edit, give * up and jump to the end. */ - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) { delbuf_msg(new_name); /* frees new_name */ goto theend; @@ -4375,7 +4385,7 @@ delbuf_msg(char_u *name) EMSG2(_("E143: Autocommands unexpectedly deleted new buffer %s"), name == NULL ? (char_u *)"" : name); vim_free(name); - au_new_curbuf = NULL; + au_new_curbuf.br_buf = NULL; } #endif diff --git a/src/globals.h b/src/globals.h index 879255cd57..566d6e13bb 100644 --- a/src/globals.h +++ b/src/globals.h @@ -386,7 +386,7 @@ 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); +EXTERN bufref_T au_new_curbuf INIT(= {NULL}); /* When deleting a buffer/window and autocmd_busy is TRUE, do not free the * buffer/window. but link it in the list starting with diff --git a/src/version.c b/src/version.c index ebaef410d6..04b7c01789 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2021, /**/ 2020, /**/ From 25065ec375a8a55462f6c07c76dc1a72a770ac19 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 19:22:53 +0200 Subject: [PATCH 07/10] patch 7.4.2022 Problem: Warnings from 64 bit compiler. Solution: Add type casts. (Mike Williams) --- src/eval.c | 4 ++-- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/eval.c b/src/eval.c index 8b67604471..b68fcfda55 100644 --- a/src/eval.c +++ b/src/eval.c @@ -13108,7 +13108,7 @@ f_getcompletion(typval_T *argvars, typval_T *rettv) ExpandInit(&xpc); xpc.xp_pattern = get_tv_string(&argvars[0]); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); xpc.xp_context = cmdcomplete_str_to_type(get_tv_string(&argvars[1])); if (xpc.xp_context == EXPAND_NOTHING) { @@ -13122,7 +13122,7 @@ f_getcompletion(typval_T *argvars, typval_T *rettv) if (xpc.xp_context == EXPAND_MENUS) { set_context_in_menu_cmd(&xpc, (char_u *)"menu", xpc.xp_pattern, FALSE); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); } pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context); diff --git a/src/version.c b/src/version.c index 04b7c01789..c9febf7c94 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2022, /**/ 2021, /**/ From ea3f2e7be447a8f0c4436869620f908de5e8ef1e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 20:27:32 +0200 Subject: [PATCH 08/10] patch 7.4.2023 Problem: buflist_findname_stat() may find a dummy buffer. Solution: Set the BF_DUMMY flag after loading a dummy buffer. Start finding buffers from the end of the list. --- src/buffer.c | 8 +++++--- src/quickfix.c | 4 ++++ src/version.c | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 409564b966..903a94aebf 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2270,7 +2270,8 @@ buflist_findname_stat( #endif buf_T *buf; - for (buf = firstbuf; buf != NULL; buf = buf->b_next) + /* Start at the last buffer, expect to find a match sooner. */ + for (buf = lastbuf; buf != NULL; buf = buf->b_prev) if ((buf->b_flags & BF_DUMMY) == 0 && !otherfile_buf(buf, ffname #ifdef UNIX , stp @@ -2355,7 +2356,7 @@ buflist_findpat( return -1; } - for (buf = firstbuf; buf != NULL; buf = buf->b_next) + for (buf = lastbuf; buf != NULL; buf = buf->b_prev) if (buf->b_p_bl == find_listed #ifdef FEAT_DIFF && (!diffmode || diff_mode_buf(buf)) @@ -2581,7 +2582,8 @@ buflist_findnr(int nr) if (nr == 0) nr = curwin->w_alt_fnum; - for (buf = firstbuf; buf != NULL; buf = buf->b_next) + /* Assume newer buffers are used more often, start from the end. */ + for (buf = lastbuf; buf != NULL; buf = buf->b_prev) if (buf->b_fnum == nr) return buf; return NULL; diff --git a/src/quickfix.c b/src/quickfix.c index 1e5abc69e6..24852b366e 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -4292,6 +4292,10 @@ load_dummy_buffer( aucmd_restbuf(&aco); if (newbuf_to_wipe != NULL && buf_valid(newbuf_to_wipe)) wipe_buffer(newbuf_to_wipe, FALSE); + + /* Add back the "dummy" flag, otherwise buflist_findname_stat() won't + * skip it. */ + newbuf->b_flags |= BF_DUMMY; } /* diff --git a/src/version.c b/src/version.c index c9febf7c94..913bf69661 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2023, /**/ 2022, /**/ From 7c0a2f367f2507669560b1a66423155c70d2e75b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 22:11:16 +0200 Subject: [PATCH 09/10] patch 7.4.2024 Problem: More buf_valid() calls can be optimized. Solution: Use bufref_valid() instead. --- src/buffer.c | 28 ++++++++++++-------- src/channel.c | 62 +++++++++++++++++++++++--------------------- src/diff.c | 10 ++++--- src/eval.c | 5 ++-- src/ex_cmds.c | 13 ++++++---- src/ex_cmds2.c | 41 +++++++++++++++++++++++------ src/ex_docmd.c | 5 +++- src/ex_getln.c | 17 ++++++------ src/fileio.c | 44 +++++++++++++++++++++---------- src/if_py_both.h | 49 +++++++++++++++++----------------- src/main.c | 6 ++++- src/misc2.c | 5 +++- src/netbeans.c | 7 ++++- src/proto/buffer.pro | 2 +- src/proto/window.pro | 4 +-- src/quickfix.c | 13 ++++++---- src/spell.c | 9 +++++-- src/structs.h | 4 +-- src/term.c | 8 +++--- src/version.c | 2 ++ src/window.c | 17 +++++++----- 21 files changed, 218 insertions(+), 133 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 903a94aebf..9511d61597 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -83,7 +83,7 @@ open_buffer( { int retval = OK; #ifdef FEAT_AUTOCMD - buf_T *old_curbuf; + bufref_T old_curbuf; #endif #ifdef FEAT_SYN_HL long old_tw = curbuf->b_p_tw; @@ -129,7 +129,7 @@ open_buffer( #ifdef FEAT_AUTOCMD /* The autocommands in readfile() may change the buffer, but only AFTER * reading the file. */ - old_curbuf = curbuf; + set_bufref(&old_curbuf, curbuf); modified_was_set = FALSE; #endif @@ -284,12 +284,12 @@ open_buffer( * The autocommands may have changed the current buffer. Apply the * modelines to the correct buffer, if it still exists and is loaded. */ - if (buf_valid(old_curbuf) && old_curbuf->b_ml.ml_mfp != NULL) + if (bufref_valid(&old_curbuf) && old_curbuf.br_buf->b_ml.ml_mfp != NULL) { aco_save_T aco; /* Go to the buffer that was opened. */ - aucmd_prepbuf(&aco, old_curbuf); + aucmd_prepbuf(&aco, old_curbuf.br_buf); #endif do_modelines(0); curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED); @@ -809,7 +809,9 @@ goto_buffer( int count) { # if defined(FEAT_WINDOWS) && defined(HAS_SWAP_EXISTS_ACTION) - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; + + set_bufref(&old_curbuf, curbuf); swap_exists_action = SEA_DIALOG; # endif @@ -838,7 +840,7 @@ goto_buffer( # endif } else - handle_swap_exists(old_curbuf); + handle_swap_exists(&old_curbuf); # endif } #endif @@ -849,7 +851,7 @@ goto_buffer( * It is allowed for "old_curbuf" to be NULL or invalid. */ void -handle_swap_exists(buf_T *old_curbuf) +handle_swap_exists(bufref_T *old_curbuf) { # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) cleanup_T cs; @@ -857,6 +859,7 @@ handle_swap_exists(buf_T *old_curbuf) #ifdef FEAT_SYN_HL long old_tw = curbuf->b_p_tw; #endif + buf_T *buf; if (swap_exists_action == SEA_QUIT) { @@ -872,11 +875,14 @@ handle_swap_exists(buf_T *old_curbuf) swap_exists_action = SEA_NONE; /* don't want it again */ swap_exists_did_quit = TRUE; close_buffer(curwin, curbuf, DOBUF_UNLOAD, FALSE); - if (!buf_valid(old_curbuf) || old_curbuf == curbuf) - old_curbuf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED); - if (old_curbuf != NULL) + if (old_curbuf == NULL || !bufref_valid(old_curbuf) + || old_curbuf->br_buf == curbuf) + buf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED); + else + buf = old_curbuf->br_buf; + if (buf != NULL) { - enter_buffer(old_curbuf); + enter_buffer(buf); #ifdef FEAT_SYN_HL if (old_tw != curbuf->b_p_tw) check_colorcolumn(curwin); diff --git a/src/channel.c b/src/channel.c index bb818dcd17..2e88080414 100644 --- a/src/channel.c +++ b/src/channel.c @@ -362,7 +362,7 @@ channel_still_useful(channel_T *channel) return TRUE; /* If reading from or a buffer it's still useful. */ - if (channel->ch_part[PART_IN].ch_buffer != NULL) + if (channel->ch_part[PART_IN].ch_bufref.br_buf != NULL) return TRUE; /* If there is no callback then nobody can get readahead. If the fd is @@ -379,9 +379,11 @@ channel_still_useful(channel_T *channel) return (channel->ch_callback != NULL && (has_sock_msg || has_out_msg || has_err_msg)) || ((channel->ch_part[PART_OUT].ch_callback != NULL - || channel->ch_part[PART_OUT].ch_buffer) && has_out_msg) + || channel->ch_part[PART_OUT].ch_bufref.br_buf != NULL) + && has_out_msg) || ((channel->ch_part[PART_ERR].ch_callback != NULL - || channel->ch_part[PART_ERR].ch_buffer) && has_err_msg); + || channel->ch_part[PART_ERR].ch_bufref.br_buf != NULL) + && has_err_msg); } /* @@ -1046,19 +1048,19 @@ channel_set_job(channel_T *channel, job_T *job, jobopt_T *options) { chanpart_T *in_part = &channel->ch_part[PART_IN]; - in_part->ch_buffer = job->jv_in_buf; + set_bufref(&in_part->ch_bufref, job->jv_in_buf); ch_logs(channel, "reading from buffer '%s'", - (char *)in_part->ch_buffer->b_ffname); + (char *)in_part->ch_bufref.br_buf->b_ffname); if (options->jo_set & JO_IN_TOP) { if (options->jo_in_top == 0 && !(options->jo_set & JO_IN_BOT)) { /* Special mode: send last-but-one line when appending a line * to the buffer. */ - in_part->ch_buffer->b_write_to_channel = TRUE; + in_part->ch_bufref.br_buf->b_write_to_channel = TRUE; in_part->ch_buf_append = TRUE; in_part->ch_buf_top = - in_part->ch_buffer->b_ml.ml_line_count + 1; + in_part->ch_bufref.br_buf->b_ml.ml_line_count + 1; } else in_part->ch_buf_top = options->jo_in_top; @@ -1068,7 +1070,7 @@ channel_set_job(channel_T *channel, job_T *job, jobopt_T *options) if (options->jo_set & JO_IN_BOT) in_part->ch_buf_bot = options->jo_in_bot; else - in_part->ch_buf_bot = in_part->ch_buffer->b_ml.ml_line_count; + in_part->ch_buf_bot = in_part->ch_bufref.br_buf->b_ml.ml_line_count; } } @@ -1229,7 +1231,7 @@ channel_set_options(channel_T *channel, jobopt_T *opt) { ch_logs(channel, "writing out to buffer '%s'", (char *)buf->b_ffname); - channel->ch_part[PART_OUT].ch_buffer = buf; + set_bufref(&channel->ch_part[PART_OUT].ch_bufref, buf); } } } @@ -1244,7 +1246,7 @@ channel_set_options(channel_T *channel, jobopt_T *opt) if (!(opt->jo_set & JO_ERR_MODE)) channel->ch_part[PART_ERR].ch_mode = MODE_NL; if (opt->jo_io[PART_ERR] == JIO_OUT) - buf = channel->ch_part[PART_OUT].ch_buffer; + buf = channel->ch_part[PART_OUT].ch_bufref.br_buf; else if (opt->jo_set & JO_ERR_BUF) { buf = buflist_findnr(opt->jo_io_buf[PART_ERR]); @@ -1266,7 +1268,7 @@ channel_set_options(channel_T *channel, jobopt_T *opt) { ch_logs(channel, "writing err to buffer '%s'", (char *)buf->b_ffname); - channel->ch_part[PART_ERR].ch_buffer = buf; + set_bufref(&channel->ch_part[PART_ERR].ch_bufref, buf); } } } @@ -1407,15 +1409,15 @@ channel_write_in(channel_T *channel) { chanpart_T *in_part = &channel->ch_part[PART_IN]; linenr_T lnum; - buf_T *buf = in_part->ch_buffer; + buf_T *buf = in_part->ch_bufref.br_buf; int written = 0; if (buf == NULL || in_part->ch_buf_append) return; /* no buffer or using appending */ - if (!buf_valid(buf) || buf->b_ml.ml_mfp == NULL) + if (!bufref_valid(&in_part->ch_bufref) || buf->b_ml.ml_mfp == NULL) { /* buffer was wiped out or unloaded */ - in_part->ch_buffer = NULL; + in_part->ch_bufref.br_buf = NULL; return; } @@ -1437,7 +1439,7 @@ channel_write_in(channel_T *channel) if (lnum > buf->b_ml.ml_line_count) { /* Writing is done, no longer need the buffer. */ - in_part->ch_buffer = NULL; + in_part->ch_bufref.br_buf = NULL; ch_log(channel, "Finished writing all lines to channel"); } else @@ -1459,11 +1461,11 @@ channel_buffer_free(buf_T *buf) { chanpart_T *ch_part = &channel->ch_part[part]; - if (ch_part->ch_buffer == buf) + if (ch_part->ch_bufref.br_buf == buf) { ch_logs(channel, "%s buffer has been wiped out", part_names[part]); - ch_part->ch_buffer = NULL; + ch_part->ch_bufref.br_buf = NULL; } } } @@ -1480,10 +1482,10 @@ channel_write_any_lines(void) { chanpart_T *in_part = &channel->ch_part[PART_IN]; - if (in_part->ch_buffer != NULL) + if (in_part->ch_bufref.br_buf != NULL) { if (in_part->ch_buf_append) - channel_write_new_lines(in_part->ch_buffer); + channel_write_new_lines(in_part->ch_bufref.br_buf); else channel_write_in(channel); } @@ -1507,7 +1509,7 @@ channel_write_new_lines(buf_T *buf) linenr_T lnum; int written = 0; - if (in_part->ch_buffer == buf && in_part->ch_buf_append) + if (in_part->ch_bufref.br_buf == buf && in_part->ch_buf_append) { if (in_part->ch_fd == INVALID_FD) continue; /* pipe was closed */ @@ -2312,7 +2314,7 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, int part) { chanpart_T *in_part = &ch->ch_part[PART_IN]; - if (in_part->ch_buffer == buffer) + if (in_part->ch_bufref.br_buf == buffer) in_part->ch_buf_bot = buffer->b_ml.ml_line_count; } } @@ -2374,11 +2376,11 @@ may_invoke_callback(channel_T *channel, int part) partial = channel->ch_partial; } - buffer = channel->ch_part[part].ch_buffer; - if (buffer != NULL && !buf_valid(buffer)) + buffer = channel->ch_part[part].ch_bufref.br_buf; + if (buffer != NULL && !bufref_valid(&channel->ch_part[part].ch_bufref)) { /* buffer was wiped out */ - channel->ch_part[part].ch_buffer = NULL; + channel->ch_part[part].ch_bufref.br_buf = NULL; buffer = NULL; } @@ -2834,7 +2836,7 @@ channel_fill_wfds(int maxfd_arg, fd_set *wfds) { chanpart_T *in_part = &ch->ch_part[PART_IN]; - if (in_part->ch_fd != INVALID_FD && in_part->ch_buffer != NULL) + if (in_part->ch_fd != INVALID_FD && in_part->ch_bufref.br_buf != NULL) { FD_SET((int)in_part->ch_fd, wfds); if ((int)in_part->ch_fd >= maxfd) @@ -2857,7 +2859,7 @@ channel_fill_poll_write(int nfd_in, struct pollfd *fds) { chanpart_T *in_part = &ch->ch_part[PART_IN]; - if (in_part->ch_fd != INVALID_FD && in_part->ch_buffer != NULL) + if (in_part->ch_fd != INVALID_FD && in_part->ch_bufref.br_buf != NULL) { in_part->ch_poll_idx = nfd; fds[nfd].fd = in_part->ch_fd; @@ -3643,8 +3645,8 @@ channel_poll_check(int ret_in, void *fds_in) { if (in_part->ch_buf_append) { - if (in_part->ch_buffer != NULL) - channel_write_new_lines(in_part->ch_buffer); + if (in_part->ch_bufref.br_buf != NULL) + channel_write_new_lines(in_part->ch_bufref.br_buf); } else channel_write_in(channel); @@ -3721,8 +3723,8 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in) { if (in_part->ch_buf_append) { - if (in_part->ch_buffer != NULL) - channel_write_new_lines(in_part->ch_buffer); + if (in_part->ch_bufref.br_buf != NULL) + channel_write_new_lines(in_part->ch_bufref.br_buf); } else channel_write_in(channel); diff --git a/src/diff.c b/src/diff.c index 5e17943ec5..287f434bee 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1069,8 +1069,9 @@ theend: ex_diffsplit(exarg_T *eap) { win_T *old_curwin = curwin; - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; + set_bufref(&old_curbuf, curbuf); #ifdef FEAT_GUI need_mouse_correct = TRUE; #endif @@ -1092,10 +1093,10 @@ ex_diffsplit(exarg_T *eap) { diff_win_options(old_curwin, TRUE); - if (buf_valid(old_curbuf)) + if (bufref_valid(&old_curbuf)) /* Move the cursor position to that of the old window. */ curwin->w_cursor.lnum = diff_get_corresponding_line( - old_curbuf, + old_curbuf.br_buf, old_curwin->w_cursor.lnum, curbuf, curwin->w_cursor.lnum); @@ -1557,7 +1558,8 @@ diff_check(win_T *wp, linenr_T lnum) /* Compare all lines. If they are equal the lines were inserted * in some buffers, deleted in others, but not changed. */ for (i = 0; i < DB_COUNT; ++i) - if (i != idx && curtab->tp_diffbuf[i] != NULL && dp->df_count[i] != 0) + if (i != idx && curtab->tp_diffbuf[i] != NULL + && dp->df_count[i] != 0) if (!diff_equal_entry(dp, idx, i)) return -1; } diff --git a/src/eval.c b/src/eval.c index b68fcfda55..a9504363d1 100644 --- a/src/eval.c +++ b/src/eval.c @@ -10503,8 +10503,9 @@ f_ch_getbufnr(typval_T *argvars, typval_T *rettv) part = PART_IN; else part = PART_SOCK; - if (channel->ch_part[part].ch_buffer != NULL) - rettv->vval.v_number = channel->ch_part[part].ch_buffer->b_fnum; + if (channel->ch_part[part].ch_bufref.br_buf != NULL) + rettv->vval.v_number = + channel->ch_part[part].ch_bufref.br_buf->b_fnum; } } diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 3e29d76892..7ec17b132c 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3666,7 +3666,7 @@ do_ecmd( buf_T *buf; bufref_T bufref; #if defined(FEAT_AUTOCMD) || defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; #endif char_u *free_fname = NULL; #ifdef FEAT_BROWSE @@ -3691,6 +3691,9 @@ do_ecmd( if (eap != NULL) command = eap->do_ecmd_cmd; +#if defined(FEAT_AUTOCMD) || defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) + set_bufref(&old_curbuf, curbuf); +#endif if (fnum != 0) { @@ -3857,7 +3860,7 @@ do_ecmd( /* autocommands may change curwin and curbuf */ if (oldwin != NULL) oldwin = curwin; - old_curbuf = curbuf; + set_bufref(&old_curbuf, curbuf); #endif } if (buf == NULL) @@ -3875,7 +3878,7 @@ do_ecmd( * buffer. */ if (!bufref_valid(&bufref) #ifdef FEAT_AUTOCMD - || curbuf != old_curbuf + || curbuf != old_curbuf.br_buf #endif ) goto theend; @@ -3934,7 +3937,7 @@ do_ecmd( auto_buf = TRUE; else { - if (curbuf == old_curbuf) + if (curbuf == old_curbuf.br_buf) #endif buf_copy_options(buf, BCO_ENTER); @@ -4196,7 +4199,7 @@ do_ecmd( #if defined(HAS_SWAP_EXISTS_ACTION) if (swap_exists_action == SEA_QUIT) retval = FAIL; - handle_swap_exists(old_curbuf); + handle_swap_exists(&old_curbuf); #endif } #ifdef FEAT_AUTOCMD diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index eb06e385ec..c8980b44b7 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -1693,6 +1693,7 @@ prof_def_func(void) autowrite(buf_T *buf, int forceit) { int r; + bufref_T bufref; if (!(p_aw || p_awa) || !p_write #ifdef FEAT_QUICKFIX @@ -1701,11 +1702,12 @@ autowrite(buf_T *buf, int forceit) #endif || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) return FAIL; + set_bufref(&bufref, buf); r = buf_write_all(buf, forceit); /* Writing may succeed but the buffer still changed, e.g., when there is a * conversion error. We do want to return FAIL then. */ - if (buf_valid(buf) && bufIsChanged(buf)) + if (bufref_valid(&bufref) && bufIsChanged(buf)) r = FAIL; return r; } @@ -1723,10 +1725,15 @@ autowrite_all(void) for (buf = firstbuf; buf; buf = buf->b_next) if (bufIsChanged(buf) && !buf->b_p_ro) { +#ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, buf); +#endif (void)buf_write_all(buf, FALSE); #ifdef FEAT_AUTOCMD /* an autocommand may have deleted the buffer */ - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) buf = firstbuf; #endif } @@ -1739,7 +1746,12 @@ autowrite_all(void) int check_changed(buf_T *buf, int flags) { - int forceit = (flags & CCGD_FORCEIT); + int forceit = (flags & CCGD_FORCEIT); +#ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, buf); +#endif if ( !forceit && bufIsChanged(buf) @@ -1762,13 +1774,13 @@ check_changed(buf_T *buf, int flags) )) ++count; # ifdef FEAT_AUTOCMD - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) /* Autocommand deleted buffer, oops! It's not changed now. */ return FALSE; # endif dialog_changed(buf, count > 1); # ifdef FEAT_AUTOCMD - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) /* Autocommand deleted buffer, oops! It's not changed now. */ return FALSE; # endif @@ -1867,6 +1879,11 @@ dialog_changed( ) && !buf2->b_p_ro) { +#ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, buf2); +#endif #ifdef FEAT_BROWSE /* May get file name, when there is none */ browse_save_fname(buf2); @@ -1877,7 +1894,7 @@ dialog_changed( (void)buf_write_all(buf2, FALSE); #ifdef FEAT_AUTOCMD /* an autocommand may have deleted the buffer */ - if (!buf_valid(buf2)) + if (!bufref_valid(&bufref)) buf2 = firstbuf; #endif } @@ -1983,11 +2000,14 @@ check_changed_any( continue; if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) { + bufref_T bufref; + + set_bufref(&bufref, buf); /* Try auto-writing the buffer. If this fails but the buffer no * longer exists it's not changed, that's OK. */ if (check_changed(buf, (p_awa ? CCGD_AW : 0) | CCGD_MULTWIN - | CCGD_ALLBUF) && buf_valid(buf)) + | CCGD_ALLBUF) && bufref_valid(&bufref)) break; /* didn't save - still changes */ } } @@ -2030,10 +2050,15 @@ check_changed_any( FOR_ALL_TAB_WINDOWS(tp, wp) if (wp->w_buffer == buf) { +# ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, buf); +# endif goto_tabpage_win(tp, wp); # ifdef FEAT_AUTOCMD /* Paranoia: did autocms wipe out the buffer with changes? */ - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) { goto theend; } diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 07fdaa94a0..646f7ec080 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -7322,8 +7322,11 @@ ex_win_close( # if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) if ((p_confirm || cmdmod.confirm) && p_write) { + bufref_T bufref; + + set_bufref(&bufref, buf); dialog_changed(buf, FALSE); - if (buf_valid(buf) && bufIsChanged(buf)) + if (bufref_valid(&bufref) && bufIsChanged(buf)) return; need_hide = FALSE; } diff --git a/src/ex_getln.c b/src/ex_getln.c index 36902e5c53..642e090107 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -1666,7 +1666,7 @@ getcmdline( case Ctrl__: /* CTRL-_: switch language mode */ if (!p_ari) break; -#ifdef FEAT_FKMAP +# ifdef FEAT_FKMAP if (p_altkeymap) { cmd_fkmap = !cmd_fkmap; @@ -1674,7 +1674,7 @@ getcmdline( ccline.overstrike = FALSE; } else /* Hebrew is default */ -#endif +# endif cmd_hkmap = !cmd_hkmap; goto cmdline_not_changed; #endif @@ -6655,9 +6655,9 @@ cmd_gchar(int offset) ex_window(void) { struct cmdline_info save_ccline; - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; win_T *old_curwin = curwin; - buf_T *bp; + bufref_T bufref; win_T *wp; int i; linenr_T lnum; @@ -6686,6 +6686,7 @@ ex_window(void) beep_flush(); return K_IGNORE; } + set_bufref(&old_curbuf, curbuf); /* Save current window sizes. */ win_size_save(&winsizes); @@ -6832,7 +6833,7 @@ ex_window(void) /* Safety check: The old window or buffer was deleted: It's a bug when * this happens! */ - if (!win_valid(old_curwin) || !buf_valid(old_curbuf)) + if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)) { cmdwin_result = Ctrl_C; EMSG(_("E199: Active window or buffer deleted")); @@ -6903,14 +6904,14 @@ ex_window(void) curwin->w_p_cole = 0; # endif wp = curwin; - bp = curbuf; + set_bufref(&bufref, curbuf); win_goto(old_curwin); win_close(wp, TRUE); /* win_close() may have already wiped the buffer when 'bh' is * set to 'wipe' */ - if (buf_valid(bp)) - close_buffer(NULL, bp, DOBUF_WIPE, FALSE); + if (bufref_valid(&bufref)) + close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, FALSE); /* Restore window sizes. */ win_size_restore(&winsizes); diff --git a/src/fileio.c b/src/fileio.c index fa927ff349..14a6f31baa 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -3287,6 +3287,7 @@ buf_write( int did_cmd = FALSE; int nofile_err = FALSE; int empty_memline = (buf->b_ml.ml_mfp == NULL); + bufref_T bufref; /* * Apply PRE autocommands. @@ -3304,6 +3305,7 @@ buf_write( /* set curwin/curbuf to buf and save a few things */ aucmd_prepbuf(&aco, buf); + set_bufref(&bufref, buf); if (append) { @@ -3376,7 +3378,7 @@ buf_write( * 2. The autocommands abort script processing. * 3. If one of the "Cmd" autocommands was executed. */ - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) buf = NULL; if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline) || did_cmd || nofile_err @@ -6675,10 +6677,13 @@ check_timestamps( /* Only check buffers in a window. */ if (buf->b_nwindows > 0) { + bufref_T bufref; + + set_bufref(&bufref, buf); n = buf_check_timestamp(buf, focus); if (didit < n) didit = n; - if (n > 0 && !buf_valid(buf)) + if (n > 0 && !bufref_valid(&bufref)) { /* Autocommands have removed the buffer, start at the * first one again. */ @@ -6766,6 +6771,7 @@ buf_check_timestamp( char *mesg2 = ""; int helpmesg = FALSE; int reload = FALSE; + char *reason; #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG) int can_reload = FALSE; #endif @@ -6778,8 +6784,10 @@ buf_check_timestamp( static int busy = FALSE; int n; char_u *s; + bufref_T bufref; + + set_bufref(&bufref, buf); #endif - char *reason; /* If there is no file name, the buffer is not loaded, 'buftype' is * set, we are in the middle of a save or being called recursively: ignore @@ -6868,7 +6876,7 @@ buf_check_timestamp( busy = FALSE; if (n) { - if (!buf_valid(buf)) + if (!bufref_valid(&bufref)) EMSG(_("E246: FileChangedShell autocommand deleted buffer")); # ifdef FEAT_EVAL s = get_vim_var_str(VV_FCS_CHOICE); @@ -7026,7 +7034,7 @@ buf_check_timestamp( #ifdef FEAT_AUTOCMD /* Trigger FileChangedShell when the file was changed in any way. */ - if (buf_valid(buf) && retval != 0) + if (bufref_valid(&bufref) && retval != 0) (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST, buf->b_fname, buf->b_fname, FALSE, buf); #endif @@ -7053,6 +7061,7 @@ buf_reload(buf_T *buf, int orig_mode) linenr_T old_topline; int old_ro = buf->b_p_ro; buf_T *savebuf; + bufref_T bufref; int saved = OK; aco_save_T aco; int flags = READ_NEW; @@ -7090,6 +7099,7 @@ buf_reload(buf_T *buf, int orig_mode) { /* Allocate a buffer without putting it in the buffer list. */ savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); + set_bufref(&bufref, savebuf); if (savebuf != NULL && buf == curbuf) { /* Open the memline. */ @@ -7122,7 +7132,7 @@ buf_reload(buf_T *buf, int orig_mode) if (!aborting()) #endif EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname); - if (savebuf != NULL && buf_valid(savebuf) && buf == curbuf) + if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf) { /* Put the text back from the save buffer. First * delete any lines that readfile() added. */ @@ -7150,7 +7160,7 @@ buf_reload(buf_T *buf, int orig_mode) } vim_free(ea.cmd); - if (savebuf != NULL && buf_valid(savebuf)) + if (savebuf != NULL && bufref_valid(&bufref)) wipe_buffer(savebuf, FALSE); #ifdef FEAT_DIFF @@ -8739,6 +8749,7 @@ ex_doautoall(exarg_T *eap) int retval; aco_save_T aco; buf_T *buf; + bufref_T bufref; char_u *arg = eap->arg; int call_do_modelines = check_nomodeline(&arg); int did_aucmd; @@ -8756,6 +8767,7 @@ ex_doautoall(exarg_T *eap) { /* find a window for this buffer and save some values */ aucmd_prepbuf(&aco, buf); + set_bufref(&bufref, buf); /* execute the autocommands for this buffer */ retval = do_doautocmd(arg, FALSE, &did_aucmd); @@ -8772,7 +8784,7 @@ ex_doautoall(exarg_T *eap) aucmd_restbuf(&aco); /* stop if there is some error or buffer was deleted */ - if (retval == FAIL || !buf_valid(buf)) + if (retval == FAIL || !bufref_valid(&bufref)) break; } } @@ -8898,7 +8910,7 @@ aucmd_prepbuf( } curbuf = buf; aco->new_curwin = curwin; - aco->new_curbuf = curbuf; + set_bufref(&aco->new_curbuf, curbuf); } /* @@ -8992,16 +9004,16 @@ win_found: * it was changed, we are still the same window and the buffer is * valid. */ if (curwin == aco->new_curwin - && curbuf != aco->new_curbuf - && buf_valid(aco->new_curbuf) - && aco->new_curbuf->b_ml.ml_mfp != NULL) + && curbuf != aco->new_curbuf.br_buf + && bufref_valid(&aco->new_curbuf) + && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL) { # if defined(FEAT_SYN_HL) || defined(FEAT_SPELL) if (curwin->w_s == &curbuf->b_s) - curwin->w_s = &aco->new_curbuf->b_s; + curwin->w_s = &aco->new_curbuf.br_buf->b_s; # endif --curbuf->b_nwindows; - curbuf = aco->new_curbuf; + curbuf = aco->new_curbuf.br_buf; curwin->w_buffer = curbuf; ++curbuf->b_nwindows; } @@ -9180,6 +9192,10 @@ has_funcundefined(void) return (first_autopat[(int)EVENT_FUNCUNDEFINED] != NULL); } +/* + * Execute autocommands for "event" and file name "fname". + * Return TRUE if some commands were executed. + */ static int apply_autocmds_group( event_T event, diff --git a/src/if_py_both.h b/src/if_py_both.h index 50fd687d96..062f8226d7 100644 --- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -3409,7 +3409,7 @@ set_option_value_for( { win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; - buf_T *save_curbuf = NULL; + bufref_T save_curbuf; int set_ret = 0; VimTryStart(); @@ -3431,7 +3431,7 @@ set_option_value_for( case SREQ_BUF: switch_buffer(&save_curbuf, (buf_T *)from); set_ret = set_option_value_err(key, numval, stringval, opt_flags); - restore_buffer(save_curbuf); + restore_buffer(&save_curbuf); break; case SREQ_GLOBAL: set_ret = set_option_value_err(key, numval, stringval, opt_flags); @@ -4273,17 +4273,17 @@ switch_to_win_for_buf( buf_T *buf, win_T **save_curwinp, tabpage_T **save_curtabp, - buf_T **save_curbufp) + bufref_T *save_curbuf) { win_T *wp; tabpage_T *tp; if (find_win_for_buf(buf, &wp, &tp) == FAIL) - switch_buffer(save_curbufp, buf); + switch_buffer(save_curbuf, buf); else if (switch_win(save_curwinp, save_curtabp, wp, tp, TRUE) == FAIL) { restore_win(*save_curwinp, *save_curtabp, TRUE); - switch_buffer(save_curbufp, buf); + switch_buffer(save_curbuf, buf); } } @@ -4291,9 +4291,9 @@ switch_to_win_for_buf( restore_win_for_buf( win_T *save_curwin, tabpage_T *save_curtab, - buf_T *save_curbuf) + bufref_T *save_curbuf) { - if (save_curbuf == NULL) + if (save_curbuf->br_buf == NULL) restore_win(save_curwin, save_curtab, TRUE); else restore_buffer(save_curbuf); @@ -4311,7 +4311,7 @@ restore_win_for_buf( static int SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change) { - buf_T *save_curbuf = NULL; + bufref_T save_curbuf = {NULL, 0}; win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; @@ -4336,13 +4336,13 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change) { if (buf == curbuf) py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1); - if (save_curbuf == NULL) + if (save_curbuf.br_buf == NULL) /* Only adjust marks if we managed to switch to a window that * holds the buffer, otherwise line numbers will be invalid. */ deleted_lines_mark((linenr_T)n, 1L); } - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); if (VimTryEnd()) return FAIL; @@ -4378,7 +4378,7 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change) else changed_bytes((linenr_T)n, 0); - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); /* Check that the cursor is not beyond the end of the line now. */ if (buf == curbuf) @@ -4415,7 +4415,7 @@ SetBufferLineList( PyObject *list, PyInt *len_change) { - buf_T *save_curbuf = NULL; + bufref_T save_curbuf = {NULL, 0}; win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; @@ -4446,17 +4446,18 @@ SetBufferLineList( break; } } - if (buf == curbuf && (save_curwin != NULL || save_curbuf == NULL)) + if (buf == curbuf && (save_curwin != NULL + || save_curbuf.br_buf == NULL)) /* Using an existing window for the buffer, adjust the cursor * position. */ py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n); - if (save_curbuf == NULL) + if (save_curbuf.br_buf == NULL) /* Only adjust marks if we managed to switch to a window that * holds the buffer, otherwise line numbers will be invalid. */ deleted_lines_mark((linenr_T)lo, (long)i); } - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); if (VimTryEnd()) return FAIL; @@ -4578,7 +4579,7 @@ SetBufferLineList( * changed range, and move any in the remainder of the buffer. * Only adjust marks if we managed to switch to a window that holds * the buffer, otherwise line numbers will be invalid. */ - if (save_curbuf == NULL) + if (save_curbuf.br_buf == NULL) mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), (long)MAXLNUM, (long)extra); changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); @@ -4587,7 +4588,7 @@ SetBufferLineList( py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra); /* END of region without "return". */ - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); if (VimTryEnd()) return FAIL; @@ -4615,7 +4616,7 @@ SetBufferLineList( static int InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change) { - buf_T *save_curbuf = NULL; + bufref_T save_curbuf = {NULL, 0}; win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; @@ -4637,13 +4638,13 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change) RAISE_UNDO_FAIL; else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL) RAISE_INSERT_LINE_FAIL; - else if (save_curbuf == NULL) + else if (save_curbuf.br_buf == NULL) /* Only adjust marks if we managed to switch to a window that * holds the buffer, otherwise line numbers will be invalid. */ appended_lines_mark((linenr_T)n, 1L); vim_free(str); - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); update_screen(VALID); if (VimTryEnd()) @@ -4704,7 +4705,7 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change) } vim_free(array[i]); } - if (i > 0 && save_curbuf == NULL) + if (i > 0 && save_curbuf.br_buf == NULL) /* Only adjust marks if we managed to switch to a window that * holds the buffer, otherwise line numbers will be invalid. */ appended_lines_mark((linenr_T)n, (long)i); @@ -4713,7 +4714,7 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change) /* Free the array of lines. All of its contents have now * been freed. */ PyMem_Free(array); - restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + restore_win_for_buf(save_curwin, save_curtab, &save_curbuf); update_screen(VALID); @@ -5216,7 +5217,7 @@ BufferMark(BufferObject *self, PyObject *pmarkObject) pos_T *posp; char_u *pmark; char_u mark; - buf_T *savebuf; + bufref_T savebuf; PyObject *todecref; if (CheckBuffer(self)) @@ -5240,7 +5241,7 @@ BufferMark(BufferObject *self, PyObject *pmarkObject) VimTryStart(); switch_buffer(&savebuf, self->buf); posp = getmark(mark, FALSE); - restore_buffer(savebuf); + restore_buffer(&savebuf); if (VimTryEnd()) return NULL; diff --git a/src/main.c b/src/main.c index 42638e4485..26941bd6e7 100644 --- a/src/main.c +++ b/src/main.c @@ -1460,9 +1460,13 @@ getout(int exitval) for (buf = firstbuf; buf != NULL; buf = buf->b_next) if (buf->b_ml.ml_mfp != NULL) { + bufref_T bufref; + + set_bufref(&bufref, buf); apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf); - if (!buf_valid(buf)) /* autocmd may delete the buffer */ + if (!bufref_valid(&bufref)) + /* autocmd deleted the buffer */ break; } apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf); diff --git a/src/misc2.c b/src/misc2.c index 4ed715b420..23b6090cee 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -1173,9 +1173,12 @@ free_all_mem(void) #endif for (buf = firstbuf; buf != NULL; ) { + bufref_T bufref; + + set_bufref(&bufref, buf); nextbuf = buf->b_next; close_buffer(NULL, buf, DOBUF_WIPE, FALSE); - if (buf_valid(buf)) + if (bufref_valid(&bufref)) buf = nextbuf; /* didn't work, try next one */ else buf = firstbuf; diff --git a/src/netbeans.c b/src/netbeans.c index e326af8f36..736bb16b09 100644 --- a/src/netbeans.c +++ b/src/netbeans.c @@ -2177,10 +2177,15 @@ nb_do_cmd( #endif ) { +#ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, buf->bufp); +#endif buf_write_all(buf->bufp, FALSE); #ifdef FEAT_AUTOCMD /* an autocommand may have deleted the buffer */ - if (!buf_valid(buf->bufp)) + if (!bufref_valid(&bufref)) buf->bufp = NULL; #endif } diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro index e2adf5c9f5..183f79a408 100644 --- a/src/proto/buffer.pro +++ b/src/proto/buffer.pro @@ -7,7 +7,7 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last); void buf_clear_file(buf_T *buf); void buf_freeall(buf_T *buf, int flags); void goto_buffer(exarg_T *eap, int start, int dir, int count); -void handle_swap_exists(buf_T *old_curbuf); +void handle_swap_exists(bufref_T *old_curbuf); char_u *do_bufdel(int command, char_u *arg, int addr_count, int start_bnr, int end_bnr, int forceit); int do_buffer(int action, int start, int dir, int count, int forceit); void set_curbuf(buf_T *buf, int action); diff --git a/src/proto/window.pro b/src/proto/window.pro index 05b6b9daeb..e091e34ad8 100644 --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -74,8 +74,8 @@ void make_snapshot(int idx); void restore_snapshot(int idx, int close_curwin); int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp, int no_display); void restore_win(win_T *save_curwin, tabpage_T *save_curtab, int no_display); -void switch_buffer(buf_T **save_curbuf, buf_T *buf); -void restore_buffer(buf_T *save_curbuf); +void switch_buffer(bufref_T *save_curbuf, buf_T *buf); +void restore_buffer(bufref_T *save_curbuf); int win_hasvertsplit(void); int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list, char_u *conceal_char); int match_delete(win_T *wp, int id, int perr); diff --git a/src/quickfix.c b/src/quickfix.c index 24852b366e..c60e98fdf9 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -4242,7 +4242,8 @@ load_dummy_buffer( char_u *resulting_dir) /* out: new directory */ { buf_T *newbuf; - buf_T *newbuf_to_wipe = NULL; + bufref_T newbufref; + bufref_T newbuf_to_wipe; int failed = TRUE; aco_save_T aco; @@ -4250,6 +4251,7 @@ load_dummy_buffer( newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); if (newbuf == NULL) return NULL; + set_bufref(&newbufref, newbuf); /* Init the options. */ buf_copy_options(newbuf, BCO_ENTER | BCO_NOHELP); @@ -4270,6 +4272,7 @@ load_dummy_buffer( * work. */ curbuf->b_flags &= ~BF_DUMMY; + newbuf_to_wipe.br_buf = NULL; if (readfile(fname, NULL, (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW | READ_DUMMY) == OK @@ -4283,15 +4286,15 @@ load_dummy_buffer( * using netrw and editing a remote file. Use the current * buffer instead, delete the dummy one after restoring the * window stuff. */ - newbuf_to_wipe = newbuf; + set_bufref(&newbuf_to_wipe, newbuf); newbuf = curbuf; } } /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); - if (newbuf_to_wipe != NULL && buf_valid(newbuf_to_wipe)) - wipe_buffer(newbuf_to_wipe, FALSE); + if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe)) + wipe_buffer(newbuf_to_wipe.br_buf, FALSE); /* Add back the "dummy" flag, otherwise buflist_findname_stat() won't * skip it. */ @@ -4306,7 +4309,7 @@ load_dummy_buffer( mch_dirname(resulting_dir, MAXPATHL); restore_start_dir(dirname_start); - if (!buf_valid(newbuf)) + if (!bufref_valid(&newbufref)) return NULL; if (failed) { diff --git a/src/spell.c b/src/spell.c index 610c7b8202..af96891076 100644 --- a/src/spell.c +++ b/src/spell.c @@ -4178,6 +4178,11 @@ did_set_spelllang(win_T *wp) static int recursive = FALSE; char_u *ret_msg = NULL; char_u *spl_copy; +#ifdef FEAT_AUTOCMD + bufref_T bufref; + + set_bufref(&bufref, wp->w_buffer); +#endif /* We don't want to do this recursively. May happen when a language is * not available and the SpellFileMissing autocommand opens a new buffer @@ -4278,7 +4283,7 @@ did_set_spelllang(win_T *wp) #ifdef FEAT_AUTOCMD /* SpellFileMissing autocommands may do anything, including * destroying the buffer we are using... */ - if (!buf_valid(wp->w_buffer)) + if (!bufref_valid(&bufref)) { ret_msg = (char_u *)"E797: SpellFileMissing autocommand deleted buffer"; goto theend; @@ -15561,7 +15566,7 @@ ex_spelldump(exarg_T *eap) set_option_value((char_u*)"spl", dummy, spl, OPT_LOCAL); vim_free(spl); - if (!bufempty() || !buf_valid(curbuf)) + if (!bufempty()) return; spell_dump_compl(NULL, 0, NULL, eap->forceit ? DUMPFLAG_COUNT : 0); diff --git a/src/structs.h b/src/structs.h index e092e6b2d8..0cf2800614 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1431,7 +1431,7 @@ typedef struct { char_u *ch_callback; /* call when a msg is not handled */ partial_T *ch_partial; - buf_T *ch_buffer; /* buffer to read from or write to */ + bufref_T ch_bufref; /* buffer to read from or write to */ int ch_nomodifiable; /* TRUE when buffer can be 'nomodifiable' */ int ch_nomod_error; /* TRUE when e_modifiable was given */ int ch_buf_append; /* write appended lines instead top-bot */ @@ -2925,7 +2925,7 @@ typedef struct int use_aucmd_win; /* using aucmd_win */ win_T *save_curwin; /* saved curwin */ win_T *new_curwin; /* new curwin */ - buf_T *new_curbuf; /* new curbuf */ + bufref_T new_curbuf; /* new curbuf */ char_u *globaldir; /* saved value of globaldir */ #endif } aco_save_T; diff --git a/src/term.c b/src/term.c index 7ff5af6dc3..8cb3e8a67f 100644 --- a/src/term.c +++ b/src/term.c @@ -1908,21 +1908,21 @@ set_termname(char_u *term) #ifdef FEAT_AUTOCMD { - buf_T *old_curbuf; + bufref_T old_curbuf; /* * Execute the TermChanged autocommands for each buffer that is * loaded. */ - old_curbuf = curbuf; + set_bufref(&old_curbuf, curbuf); for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next) { if (curbuf->b_ml.ml_mfp != NULL) apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE, curbuf); } - if (buf_valid(old_curbuf)) - curbuf = old_curbuf; + if (bufref_valid(&old_curbuf)) + curbuf = old_curbuf.br_buf; } #endif } diff --git a/src/version.c b/src/version.c index 913bf69661..1a7ff06bac 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2024, /**/ 2023, /**/ diff --git a/src/window.c b/src/window.c index c3cd7a2339..b9e75d6dfc 100644 --- a/src/window.c +++ b/src/window.c @@ -2340,6 +2340,9 @@ win_close(win_T *win, int free_buf) */ if (win->w_buffer != NULL) { + bufref_T bufref; + + set_bufref(&bufref, curbuf); #ifdef FEAT_AUTOCMD win->w_closing = TRUE; #endif @@ -2350,7 +2353,7 @@ win_close(win_T *win, int free_buf) #endif /* Make sure curbuf is valid. It can become invalid if 'bufhidden' is * "wipe". */ - if (!buf_valid(curbuf)) + if (!bufref_valid(&bufref)) curbuf = firstbuf; } @@ -6632,12 +6635,12 @@ restore_win( * No autocommands will be executed. Use aucmd_prepbuf() if there are any. */ void -switch_buffer(buf_T **save_curbuf, buf_T *buf) +switch_buffer(bufref_T *save_curbuf, buf_T *buf) { # ifdef FEAT_AUTOCMD block_autocmds(); # endif - *save_curbuf = curbuf; + set_bufref(save_curbuf, curbuf); --curbuf->b_nwindows; curbuf = buf; curwin->w_buffer = buf; @@ -6648,17 +6651,17 @@ switch_buffer(buf_T **save_curbuf, buf_T *buf) * Restore the current buffer after using switch_buffer(). */ void -restore_buffer(buf_T *save_curbuf) +restore_buffer(bufref_T *save_curbuf) { # ifdef FEAT_AUTOCMD unblock_autocmds(); # endif /* Check for valid buffer, just in case. */ - if (buf_valid(save_curbuf)) + if (bufref_valid(save_curbuf)) { --curbuf->b_nwindows; - curwin->w_buffer = save_curbuf; - curbuf = save_curbuf; + curwin->w_buffer = save_curbuf->br_buf; + curbuf = save_curbuf->br_buf; ++curbuf->b_nwindows; } } From da3a77d9ec28407b8fa2aa014e76944d0a525662 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 10 Jul 2016 23:16:09 +0200 Subject: [PATCH 10/10] patch 7.4.2025 Problem: The cursor blinking stops or is irregular when receiving date over a channel and writing it in a buffer, and when updating the status line. (Ramel Eshed) Solution: Make it a bit better by flushing GUI output. Don't redraw the cursor after updating the screen if the blink state is off. --- src/gui_gtk_x11.c | 5 +++++ src/screen.c | 2 +- src/version.c | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index 39b918ab83..9437ed3b17 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -867,7 +867,10 @@ gui_mch_stop_blink(void) blink_timer = 0; } if (blink_state == BLINK_OFF) + { gui_update_cursor(TRUE, FALSE); + gui_mch_flush(); + } blink_state = BLINK_NONE; } @@ -902,6 +905,7 @@ blink_cb(gpointer data UNUSED) (GtkFunction) blink_cb, NULL); #endif } + gui_mch_flush(); return FALSE; /* don't happen again */ } @@ -934,6 +938,7 @@ gui_mch_start_blink(void) #endif blink_state = BLINK_ON; gui_update_cursor(TRUE, FALSE); + gui_mch_flush(); } } diff --git a/src/screen.c b/src/screen.c index 7c4ee3064d..04a0da9eb5 100644 --- a/src/screen.c +++ b/src/screen.c @@ -757,7 +757,7 @@ update_screen(int type) if (gui.in_use) { out_flush(); /* required before updating the cursor */ - if (did_one) + if (did_one && !gui_mch_is_blink_off()) { /* Put the GUI position where the cursor was, gui_update_cursor() * uses that. */ diff --git a/src/version.c b/src/version.c index 1a7ff06bac..67f8b653e1 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2025, /**/ 2024, /**/