aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/buffer.c39
-rw-r--r--src/nvim/buffer.h7
-rw-r--r--src/nvim/change.c6
-rw-r--r--src/nvim/diff.c14
-rw-r--r--src/nvim/edit.c42
-rw-r--r--src/nvim/ex_cmds.c8
-rw-r--r--src/nvim/ex_docmd.c4
-rw-r--r--src/nvim/ex_docmd.h1
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/fileio.c38
-rw-r--r--src/nvim/getchar.c21
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/memline.c159
-rw-r--r--src/nvim/memory.c2
-rw-r--r--src/nvim/option.c66
-rw-r--r--src/nvim/quickfix.c4
-rw-r--r--src/nvim/state.c5
-rw-r--r--src/nvim/syntax.c79
-rw-r--r--src/nvim/testdir/test_autocmd.vim34
-rw-r--r--src/nvim/testdir/test_diffmode.vim37
-rw-r--r--src/nvim/testdir/test_edit.vim23
-rw-r--r--src/nvim/testdir/test_filetype.vim2
-rw-r--r--src/nvim/testdir/test_highlight.vim8
-rw-r--r--src/nvim/testdir/test_ins_complete.vim19
-rw-r--r--src/nvim/testdir/test_registers.vim18
-rw-r--r--src/nvim/testdir/test_trycatch.vim27
-rw-r--r--src/nvim/window.c68
27 files changed, 466 insertions, 269 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index bf592a626d..4ec23244cd 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -174,7 +174,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags)
if (ml_open(curbuf) == FAIL) {
// There MUST be a memfile, otherwise we can't do anything
// If we can't create one for the current buffer, take another buffer
- close_buffer(NULL, curbuf, 0, false);
+ close_buffer(NULL, curbuf, 0, false, false);
curbuf = NULL;
FOR_ALL_BUFFERS(buf) {
@@ -402,8 +402,10 @@ bool buf_valid(buf_T *buf)
/// there to be only one window with this buffer. e.g. when
/// ":quit" is supposed to close the window but autocommands
/// close all other windows.
+/// @param ignore_abort
+/// If true, don't abort even when aborting() returns true.
/// @return true when we got to the end and b_nwindows was decremented.
-bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
+bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool ignore_abort)
{
bool unload_buf = (action != 0);
bool del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE);
@@ -494,7 +496,8 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
return false;
}
}
- if (aborting()) { // autocmds may abort script processing
+ // autocmds may abort script processing
+ if (!ignore_abort && aborting()) {
return false;
}
}
@@ -552,14 +555,16 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
buf->b_nwindows = nwindows;
- buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0));
+ buf_freeall(buf, ((del_buf ? BFA_DEL : 0)
+ + (wipe_buf ? BFA_WIPE : 0)
+ + (ignore_abort ? BFA_IGNORE_ABORT : 0)));
if (!bufref_valid(&bufref)) {
// Autocommands may have deleted the buffer.
return false;
}
- if (aborting()) {
- // Autocmds may abort script processing.
+ // autocmds may abort script processing.
+ if (!ignore_abort && aborting()) {
return false;
}
@@ -660,9 +665,10 @@ void buf_clear(void)
/// buf_freeall() - free all things allocated for a buffer that are related to
/// the file. Careful: get here with "curwin" NULL when exiting.
///
-/// @param flags BFA_DEL buffer is going to be deleted
-/// BFA_WIPE buffer is going to be wiped out
-/// BFA_KEEP_UNDO do not free undo information
+/// @param flags BFA_DEL buffer is going to be deleted
+/// BFA_WIPE buffer is going to be wiped out
+/// BFA_KEEP_UNDO do not free undo information
+/// BFA_IGNORE_ABORT don't abort even when aborting() returns true
void buf_freeall(buf_T *buf, int flags)
{
bool is_curbuf = (buf == curbuf);
@@ -706,7 +712,8 @@ void buf_freeall(buf_T *buf, int flags)
goto_tabpage_win(the_curtab, the_curwin);
unblock_autocmds();
}
- if (aborting()) { // autocmds may abort script processing
+ // autocmds may abort script processing
+ if ((flags & BFA_IGNORE_ABORT) == 0 && aborting()) {
return;
}
@@ -877,7 +884,7 @@ void handle_swap_exists(bufref_T *old_curbuf)
// open a new, empty buffer.
swap_exists_action = SEA_NONE; // don't want it again
swap_exists_did_quit = true;
- close_buffer(curwin, curbuf, DOBUF_UNLOAD, false);
+ close_buffer(curwin, curbuf, DOBUF_UNLOAD, false, false);
if (old_curbuf == NULL
|| !bufref_valid(old_curbuf)
|| old_curbuf->br_buf == curbuf) {
@@ -1074,7 +1081,7 @@ static int empty_curbuf(int close_others, int forceit, int action)
// the old one. But do_ecmd() may have done that already, check
// if the buffer still exists.
if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows == 0) {
- close_buffer(NULL, buf, action, false);
+ close_buffer(NULL, buf, action, false, false);
}
if (!close_others) {
@@ -1259,7 +1266,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
if (buf != curbuf) {
close_windows(buf, false);
if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) {
- close_buffer(NULL, buf, action, false);
+ close_buffer(NULL, buf, action, false, false);
}
return OK;
}
@@ -1485,7 +1492,7 @@ void set_curbuf(buf_T *buf, int action)
? action
: (action == DOBUF_GOTO && !buf_hide(prevbuf)
&& !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0,
- false);
+ false, false);
if (curwin != previouswin && win_valid(previouswin)) {
// autocommands changed curwin, Grr!
curwin = previouswin;
@@ -2805,7 +2812,7 @@ int setfname(buf_T *buf, char_u *ffname_arg, char_u *sfname_arg, bool message)
return FAIL;
}
// delete from the list
- close_buffer(NULL, obuf, DOBUF_WIPE, false);
+ close_buffer(NULL, obuf, DOBUF_WIPE, false, false);
}
sfname = vim_strsave(sfname);
#ifdef USE_FNAME_CASE
@@ -5650,7 +5657,7 @@ void wipe_buffer(buf_T *buf, bool aucmd)
// Don't trigger BufDelete autocommands here.
block_autocmds();
}
- close_buffer(NULL, buf, DOBUF_WIPE, false);
+ close_buffer(NULL, buf, DOBUF_WIPE, false, true);
if (!aucmd) {
unblock_autocmds();
}
diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h
index 850ab175a5..7f4bbcc9e5 100644
--- a/src/nvim/buffer.h
+++ b/src/nvim/buffer.h
@@ -58,9 +58,10 @@ enum dobuf_start_values {
// flags for buf_freeall()
enum bfa_values {
- BFA_DEL = 1, // buffer is going to be deleted
- BFA_WIPE = 2, // buffer is going to be wiped out
- BFA_KEEP_UNDO = 4, // do not free undo information
+ BFA_DEL = 1, // buffer is going to be deleted
+ BFA_WIPE = 2, // buffer is going to be wiped out
+ BFA_KEEP_UNDO = 4, // do not free undo information
+ BFA_IGNORE_ABORT = 8, // do not abort for aborting()
};
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 0644b1d601..44abd69733 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -286,9 +286,11 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
set_topline(wp, wp->w_topline);
}
- // Relative numbering may require updating more.
+ // If lines have been added or removed, relative numbering always
+ // requires a redraw.
if (wp->w_p_rnu && xtra != 0) {
- redraw_later(wp, SOME_VALID);
+ wp->w_last_cursor_lnum_rnu = 0;
+ redraw_later(wp, VALID);
}
// Cursor line highlighting probably need to be updated with
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index a6bbe40999..0b55fb877c 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -743,11 +743,16 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
for (char_u *s = ml_get_buf(buf, lnum, false); *s != NUL;) {
if (diff_flags & DIFF_ICASE) {
+ int c;
char_u cbuf[MB_MAXBYTES + 1];
- // xdiff doesn't support ignoring case, fold-case the text.
- int c = utf_ptr2char(s);
- c = utf_fold(c);
+ if (*s == NL) {
+ c = NUL;
+ } else {
+ // xdiff doesn't support ignoring case, fold-case the text.
+ c = utf_ptr2char(s);
+ c = utf_fold(c);
+ }
const int orig_len = utfc_ptr2len(s);
if (utf_char2bytes(c, cbuf) != orig_len) {
// TODO(Bram): handle byte length difference
@@ -759,7 +764,8 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
s += orig_len;
len += orig_len;
} else {
- ptr[len++] = *s++;
+ ptr[len++] = *s == NL ? NUL : *s;
+ s++;
}
}
ptr[len++] = NL;
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index da0b577056..3eb4ab9517 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -390,12 +390,9 @@ static void insert_enter(InsertState *s)
trigger_modechanged();
stop_insert_mode = false;
- // Need to recompute the cursor position, it might move when the cursor
- // is on a TAB or special character.
- // ptr2cells() treats a TAB character as double-width.
- if (ptr2cells(get_cursor_pos_ptr()) > 1) {
- curwin->w_valid &= ~VALID_VIRTCOL;
- curs_columns(curwin, true);
+ // need to position cursor again when on a TAB
+ if (gchar_cursor() == TAB) {
+ curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
}
// Enable langmap or IME, indicated by 'iminsert'.
@@ -1396,6 +1393,7 @@ static void insert_do_complete(InsertState *s)
compl_cont_status = 0;
}
compl_busy = false;
+ can_si = true; // allow smartindenting
}
static void insert_do_cindent(InsertState *s)
@@ -7330,21 +7328,21 @@ static void mb_replace_pop_ins(int cc)
// Not a multi-byte char, put it back.
replace_push(c);
break;
+ }
+
+ buf[0] = c;
+ assert(n > 1);
+ for (i = 1; i < n; i++) {
+ buf[i] = replace_pop();
+ }
+ if (utf_iscomposing(utf_ptr2char(buf))) {
+ ins_bytes_len(buf, n);
} else {
- buf[0] = c;
- assert(n > 1);
- for (i = 1; i < n; i++) {
- buf[i] = replace_pop();
- }
- if (utf_iscomposing(utf_ptr2char(buf))) {
- ins_bytes_len(buf, n);
- } else {
- // Not a composing char, put it back.
- for (i = n - 1; i >= 0; i--) {
- replace_push(buf[i]);
- }
- break;
+ // Not a composing char, put it back.
+ for (i = n - 1; i >= 0; i--) {
+ replace_push(buf[i]);
}
+ break;
}
}
}
@@ -8054,8 +8052,10 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
State = NORMAL;
trigger_modechanged();
- // need to position cursor again (e.g. when on a TAB )
- changed_cline_bef_curs();
+ // need to position cursor again when on a TAB
+ if (gchar_cursor() == TAB) {
+ curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
+ }
setmouse();
ui_cursor_shape(); // may show different cursor shape
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 5d5b342c35..98aabe89b3 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -2527,9 +2527,9 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
// Close the link to the current buffer. This will set
// oldwin->w_buffer to NULL.
u_sync(false);
- const bool did_decrement = close_buffer(oldwin, curbuf,
- (flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD,
- false);
+ const bool did_decrement
+ = close_buffer(oldwin, curbuf, (flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD,
+ false, false);
// Autocommands may have closed the window.
if (win_valid(the_curwin)) {
@@ -2875,7 +2875,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
redraw_curbuf_later(NOT_VALID); // redraw this buffer later
}
- if (p_im) {
+ if (p_im && (State & INSERT) == 0) {
need_start_insertmode = true;
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index bb6f3ba395..1f17101aca 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1248,6 +1248,7 @@ static char_u *do_one_cmd(char_u **cmdlinep, int flags, cstack_T *cstack, LineGe
const int save_msg_scroll = msg_scroll;
cmdmod_T save_cmdmod;
const int save_reg_executing = reg_executing;
+ const bool save_pending_end_reg_executing = pending_end_reg_executing;
char_u *cmd;
memset(&ea, 0, sizeof(ea));
@@ -2018,6 +2019,7 @@ doend:
undo_cmdmod(&ea, save_msg_scroll);
cmdmod = save_cmdmod;
reg_executing = save_reg_executing;
+ pending_end_reg_executing = save_pending_end_reg_executing;
if (ea.did_sandbox) {
sandbox--;
@@ -8529,6 +8531,7 @@ bool save_current_state(save_state_T *sst)
sst->save_finish_op = finish_op;
sst->save_opcount = opcount;
sst->save_reg_executing = reg_executing;
+ sst->save_pending_end_reg_executing = pending_end_reg_executing;
msg_scroll = false; // no msg scrolling in Normal mode
restart_edit = 0; // don't go to Insert mode
@@ -8559,6 +8562,7 @@ void restore_current_state(save_state_T *sst)
finish_op = sst->save_finish_op;
opcount = sst->save_opcount;
reg_executing = sst->save_reg_executing;
+ pending_end_reg_executing = sst->save_pending_end_reg_executing;
// don't reset msg_didout now
msg_didout |= sst->save_msg_didout;
diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h
index be9f97e27d..874e0e599e 100644
--- a/src/nvim/ex_docmd.h
+++ b/src/nvim/ex_docmd.h
@@ -29,6 +29,7 @@ typedef struct {
bool save_finish_op;
long save_opcount;
int save_reg_executing;
+ bool save_pending_end_reg_executing;
tasave_T tabuf;
} save_state_T;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 9104a2dd5a..dd6e4630d2 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -6544,7 +6544,7 @@ static int open_cmdwin(void)
// win_close() may have already wiped the buffer when 'bh' is
// set to 'wipe', autocommands may have closed other windows
if (bufref_valid(&bufref) && bufref.br_buf != curbuf) {
- close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false);
+ close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false, false);
}
// Restore window sizes.
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index d68dda15f3..d4407b4982 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -1015,27 +1015,27 @@ retry:
}
read_buf_col += n;
break;
- } else {
- // Append whole line and new-line. Change NL
- // to NUL to reverse the effect done below.
- for (ni = 0; ni < n; ni++) {
- if (p[ni] == NL) {
- ptr[tlen++] = NUL;
- } else {
- ptr[tlen++] = p[ni];
- }
+ }
+
+ // Append whole line and new-line. Change NL
+ // to NUL to reverse the effect done below.
+ for (ni = 0; ni < n; ni++) {
+ if (p[ni] == NL) {
+ ptr[tlen++] = NUL;
+ } else {
+ ptr[tlen++] = p[ni];
}
- ptr[tlen++] = NL;
- read_buf_col = 0;
- if (++read_buf_lnum > from) {
- // When the last line didn't have an
- // end-of-line don't add it now either.
- if (!curbuf->b_p_eol) {
- --tlen;
- }
- size = tlen;
- break;
+ }
+ ptr[tlen++] = NL;
+ read_buf_col = 0;
+ if (++read_buf_lnum > from) {
+ // When the last line didn't have an
+ // end-of-line don't add it now either.
+ if (!curbuf->b_p_eol) {
+ tlen--;
}
+ size = tlen;
+ break;
}
}
}
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index eddd5ccd14..299385cb17 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -2060,7 +2060,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
}
/// unget one character (can only be done once!)
-/// If the character was stuffed, vgetc() will get it next time it was called.
+/// If the character was stuffed, vgetc() will get it next time it is called.
/// Otherwise vgetc() will only get it when the stuff buffer is empty.
void vungetc(int c)
{
@@ -2072,6 +2072,20 @@ void vungetc(int c)
old_KeyStuffed = KeyStuffed;
}
+/// When peeking and not getting a character, reg_executing cannot be cleared
+/// yet, so set a flag to clear it later.
+void check_end_reg_executing(bool advance)
+{
+ if (reg_executing != 0 && (typebuf.tb_maplen == 0 || pending_end_reg_executing)) {
+ if (advance) {
+ reg_executing = 0;
+ pending_end_reg_executing = false;
+ } else {
+ pending_end_reg_executing = true;
+ }
+ }
+}
+
/// Gets a byte:
/// 1. from the stuffbuffer
/// This is used for abbreviated commands like "D" -> "d$".
@@ -2126,9 +2140,7 @@ static int vgetorpeek(bool advance)
init_typebuf();
start_stuff();
- if (advance && typebuf.tb_maplen == 0) {
- reg_executing = 0;
- }
+ check_end_reg_executing(advance);
do {
// get a character: 1. from the stuffbuffer
if (typeahead_char != 0) {
@@ -2155,6 +2167,7 @@ static int vgetorpeek(bool advance)
// If a mapped key sequence is found we go back to the start to
// try re-mapping.
for (;;) {
+ check_end_reg_executing(advance);
// os_breakcheck() is slow, don't use it too often when
// inside a mapping. But call it each time for typed
// characters.
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index ace7647b35..4aa49337cf 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -643,6 +643,8 @@ EXTERN bool ex_no_reprint INIT(=false); // No need to print after z or p.
EXTERN int reg_recording INIT(= 0); // register for recording or zero
EXTERN int reg_executing INIT(= 0); // register being executed or zero
+// Flag set when peeking a character and found the end of executed register
+EXTERN bool pending_end_reg_executing INIT(= false);
EXTERN int reg_recorded INIT(= 0); // last recorded register or zero
EXTERN int no_mapping INIT(= false); // currently no mapping allowed
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 418887a6b1..5f6e1ea273 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -2327,95 +2327,88 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
* We are finished, break the loop here.
*/
break;
- } else { // pointer block full
- /*
- * split the pointer block
- * allocate a new pointer block
- * move some of the pointer into the new block
- * prepare for updating the parent block
- */
- for (;;) { // do this twice when splitting block 1
- hp_new = ml_new_ptr(mfp);
- if (hp_new == NULL) { // TODO: try to fix tree
- return FAIL;
- }
- pp_new = hp_new->bh_data;
-
- if (hp->bh_bnum != 1) {
- break;
- }
-
- /*
- * if block 1 becomes full the tree is given an extra level
- * The pointers from block 1 are moved into the new block.
- * block 1 is updated to point to the new block
- * then continue to split the new block
- */
- memmove(pp_new, pp, (size_t)page_size);
- pp->pb_count = 1;
- pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum;
- pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count;
- pp->pb_pointer[0].pe_old_lnum = 1;
- pp->pb_pointer[0].pe_page_count = 1;
- mf_put(mfp, hp, true, false); // release block 1
- hp = hp_new; // new block is to be split
- pp = pp_new;
- CHECK(stack_idx != 0, _("stack_idx should be 0"));
- ip->ip_index = 0;
- ++stack_idx; // do block 1 again later
- }
- /*
- * move the pointers after the current one to the new block
- * If there are none, the new entry will be in the new block.
- */
- total_moved = pp->pb_count - pb_idx - 1;
- if (total_moved) {
- memmove(&pp_new->pb_pointer[0],
- &pp->pb_pointer[pb_idx + 1],
- (size_t)(total_moved) * sizeof(PTR_EN));
- pp_new->pb_count = total_moved;
- pp->pb_count -= total_moved - 1;
- pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
- pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
- pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
- if (lnum_right) {
- pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
- }
- } else {
- pp_new->pb_count = 1;
- pp_new->pb_pointer[0].pe_bnum = bnum_right;
- pp_new->pb_pointer[0].pe_line_count = line_count_right;
- pp_new->pb_pointer[0].pe_page_count = page_count_right;
- pp_new->pb_pointer[0].pe_old_lnum = lnum_right;
- }
- pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
- pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
- pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
- if (lnum_left) {
- pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
+ }
+ // pointer block full
+ //
+ // split the pointer block
+ // allocate a new pointer block
+ // move some of the pointer into the new block
+ // prepare for updating the parent block
+ for (;;) { // do this twice when splitting block 1
+ hp_new = ml_new_ptr(mfp);
+ if (hp_new == NULL) { // TODO(vim): try to fix tree
+ return FAIL;
}
- lnum_left = 0;
- lnum_right = 0;
+ pp_new = hp_new->bh_data;
- /*
- * recompute line counts
- */
- line_count_right = 0;
- for (i = 0; i < (int)pp_new->pb_count; ++i) {
- line_count_right += pp_new->pb_pointer[i].pe_line_count;
+ if (hp->bh_bnum != 1) {
+ break;
}
- line_count_left = 0;
- for (i = 0; i < (int)pp->pb_count; ++i) {
- line_count_left += pp->pb_pointer[i].pe_line_count;
+
+ // if block 1 becomes full the tree is given an extra level
+ // The pointers from block 1 are moved into the new block.
+ // block 1 is updated to point to the new block
+ // then continue to split the new block
+ memmove(pp_new, pp, (size_t)page_size);
+ pp->pb_count = 1;
+ pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum;
+ pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count;
+ pp->pb_pointer[0].pe_old_lnum = 1;
+ pp->pb_pointer[0].pe_page_count = 1;
+ mf_put(mfp, hp, true, false); // release block 1
+ hp = hp_new; // new block is to be split
+ pp = pp_new;
+ CHECK(stack_idx != 0, _("stack_idx should be 0"));
+ ip->ip_index = 0;
+ stack_idx++; // do block 1 again later
+ }
+ // move the pointers after the current one to the new block
+ // If there are none, the new entry will be in the new block.
+ total_moved = pp->pb_count - pb_idx - 1;
+ if (total_moved) {
+ memmove(&pp_new->pb_pointer[0],
+ &pp->pb_pointer[pb_idx + 1],
+ (size_t)(total_moved) * sizeof(PTR_EN));
+ pp_new->pb_count = total_moved;
+ pp->pb_count -= total_moved - 1;
+ pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
+ pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
+ pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
+ if (lnum_right) {
+ pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
}
+ } else {
+ pp_new->pb_count = 1;
+ pp_new->pb_pointer[0].pe_bnum = bnum_right;
+ pp_new->pb_pointer[0].pe_line_count = line_count_right;
+ pp_new->pb_pointer[0].pe_page_count = page_count_right;
+ pp_new->pb_pointer[0].pe_old_lnum = lnum_right;
+ }
+ pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
+ pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
+ pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
+ if (lnum_left) {
+ pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
+ }
+ lnum_left = 0;
+ lnum_right = 0;
- bnum_left = hp->bh_bnum;
- bnum_right = hp_new->bh_bnum;
- page_count_left = 1;
- page_count_right = 1;
- mf_put(mfp, hp, true, false);
- mf_put(mfp, hp_new, true, false);
+ // recompute line counts
+ line_count_right = 0;
+ for (i = 0; i < (int)pp_new->pb_count; i++) {
+ line_count_right += pp_new->pb_pointer[i].pe_line_count;
}
+ line_count_left = 0;
+ for (i = 0; i < (int)pp->pb_count; i++) {
+ line_count_left += pp->pb_pointer[i].pe_line_count;
+ }
+
+ bnum_left = hp->bh_bnum;
+ bnum_right = hp_new->bh_bnum;
+ page_count_left = 1;
+ page_count_right = 1;
+ mf_put(mfp, hp, true, false);
+ mf_put(mfp, hp_new, true, false);
}
/*
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 6cdc4f1fde..c895cc1ec6 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -691,7 +691,7 @@ void free_all_mem(void)
bufref_T bufref;
set_bufref(&bufref, buf);
nextbuf = buf->b_next;
- close_buffer(NULL, buf, DOBUF_WIPE, false);
+ close_buffer(NULL, buf, DOBUF_WIPE, false, false);
// Didn't work, try next one.
buf = bufref_valid(&bufref) ? nextbuf : firstbuf;
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 9fd0e0b222..551bc1fbdf 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -5140,43 +5140,43 @@ char *set_option_value(const char *const name, const long number, const char *co
s = "";
}
return set_string_option(opt_idx, s, opt_flags);
- } else {
- varp = get_varp_scope(&(options[opt_idx]), opt_flags);
- if (varp != NULL) { // hidden option is not changed
- if (number == 0 && string != NULL) {
- int idx;
-
- // Either we are given a string or we are setting option
- // to zero.
- for (idx = 0; string[idx] == '0'; idx++) {}
- if (string[idx] != NUL || idx == 0) {
- // There's another character after zeros or the string
- // is empty. In both cases, we are trying to set a
- // num option using a string.
- semsg(_("E521: Number required: &%s = '%s'"),
- name, string);
- return NULL; // do nothing as we hit an error
- }
- }
- long numval = number;
- if (opt_flags & OPT_CLEAR) {
- if ((int *)varp == &curbuf->b_p_ar) {
- numval = -1;
- } else if ((long *)varp == &curbuf->b_p_ul) {
- numval = NO_LOCAL_UNDOLEVEL;
- } else if ((long *)varp == &curwin->w_p_so || (long *)varp == &curwin->w_p_siso) {
- numval = -1;
- } else {
- char *s = NULL;
- (void)get_option_value(name, &numval, (char_u **)&s, OPT_GLOBAL);
- }
+ }
+
+ varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+ if (varp != NULL) { // hidden option is not changed
+ if (number == 0 && string != NULL) {
+ int idx;
+
+ // Either we are given a string or we are setting option
+ // to zero.
+ for (idx = 0; string[idx] == '0'; idx++) {}
+ if (string[idx] != NUL || idx == 0) {
+ // There's another character after zeros or the string
+ // is empty. In both cases, we are trying to set a
+ // num option using a string.
+ semsg(_("E521: Number required: &%s = '%s'"),
+ name, string);
+ return NULL; // do nothing as we hit an error
}
- if (flags & P_NUM) {
- return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags);
+ }
+ long numval = number;
+ if (opt_flags & OPT_CLEAR) {
+ if ((int *)varp == &curbuf->b_p_ar) {
+ numval = -1;
+ } else if ((long *)varp == &curbuf->b_p_ul) {
+ numval = NO_LOCAL_UNDOLEVEL;
+ } else if ((long *)varp == &curwin->w_p_so || (long *)varp == &curwin->w_p_siso) {
+ numval = -1;
} else {
- return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
+ char *s = NULL;
+ (void)get_option_value(name, &numval, (char_u **)&s, OPT_GLOBAL);
}
}
+ if (flags & P_NUM) {
+ return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags);
+ } else {
+ return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
+ }
}
}
return NULL;
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 1d589e8ca0..4ad5e40fee 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -1721,7 +1721,7 @@ static void wipe_qf_buffer(qf_info_T *qi)
if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
// If the quickfix buffer is not loaded in any window, then
// wipe the buffer.
- close_buffer(NULL, qfbuf, DOBUF_WIPE, false);
+ close_buffer(NULL, qfbuf, DOBUF_WIPE, false, false);
qi->qf_bufnr = INVALID_QFBUFNR;
}
}
@@ -5843,7 +5843,7 @@ static void wipe_dummy_buffer(buf_T *buf, char_u *dirname_start)
static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start)
{
if (curbuf != buf) { // safety check
- close_buffer(NULL, buf, DOBUF_UNLOAD, false);
+ close_buffer(NULL, buf, DOBUF_UNLOAD, false, true);
// When autocommands/'autochdir' option changed directory: go back.
restore_start_dir(dirname_start);
diff --git a/src/nvim/state.c b/src/nvim/state.c
index 3a7636085b..34e3ddf654 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -40,7 +40,7 @@ void state_enter(VimState *s)
int key;
getkey:
- // Expand mappings first by calling vpeekc() directly.
+ // Apply mappings first by calling vpeekc() directly.
// - If vpeekc() returns non-NUL, there is a character already available for processing, so
// don't block for events. vgetc() may still block, in case of an incomplete UTF-8 sequence.
// - If vpeekc() returns NUL, vgetc() will block, and there are three cases:
@@ -76,6 +76,9 @@ getkey:
}
if (key == K_EVENT) {
+ // An event handler may use the value of reg_executing.
+ // Clear it if it should be cleared when getting the next character.
+ check_end_reg_executing(true);
may_sync_undo();
}
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index a82e8fa103..d884ad704b 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -2289,55 +2289,52 @@ static void check_state_ends(void)
next_match_idx = 0;
next_match_col = MAXCOL;
break;
- } else {
- // handle next_list, unless at end of line and no "skipnl" or
- // "skipempty"
- current_next_list = cur_si->si_next_list;
- current_next_flags = cur_si->si_flags;
- if (!(current_next_flags & (HL_SKIPNL | HL_SKIPEMPTY))
- && syn_getcurline()[current_col] == NUL) {
- current_next_list = NULL;
- }
+ }
+
+ // handle next_list, unless at end of line and no "skipnl" or
+ // "skipempty"
+ current_next_list = cur_si->si_next_list;
+ current_next_flags = cur_si->si_flags;
+ if (!(current_next_flags & (HL_SKIPNL | HL_SKIPEMPTY))
+ && syn_getcurline()[current_col] == NUL) {
+ current_next_list = NULL;
+ }
+
+ // When the ended item has "extend", another item with
+ // "keepend" now needs to check for its end.
+ had_extend = (cur_si->si_flags & HL_EXTEND);
- // When the ended item has "extend", another item with
- // "keepend" now needs to check for its end.
- had_extend = (cur_si->si_flags & HL_EXTEND);
+ pop_current_state();
- pop_current_state();
+ if (GA_EMPTY(&current_state)) {
+ break;
+ }
+ if (had_extend && keepend_level >= 0) {
+ syn_update_ends(false);
if (GA_EMPTY(&current_state)) {
break;
}
+ }
- if (had_extend && keepend_level >= 0) {
- syn_update_ends(false);
- if (GA_EMPTY(&current_state)) {
- break;
- }
- }
-
- cur_si = &CUR_STATE(current_state.ga_len - 1);
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
- /*
- * Only for a region the search for the end continues after
- * the end of the contained item. If the contained match
- * included the end-of-line, break here, the region continues.
- * Don't do this when:
- * - "keepend" is used for the contained item
- * - not at the end of the line (could be end="x$"me=e-1).
- * - "excludenl" is used (HL_HAS_EOL won't be set)
- */
- if (cur_si->si_idx >= 0
- && SYN_ITEMS(syn_block)[cur_si->si_idx].sp_type
- == SPTYPE_START
- && !(cur_si->si_flags & (HL_MATCH | HL_KEEPEND))) {
- update_si_end(cur_si, (int)current_col, true);
- check_keepend();
- if ((current_next_flags & HL_HAS_EOL)
- && keepend_level < 0
- && syn_getcurline()[current_col] == NUL) {
- break;
- }
+ // Only for a region the search for the end continues after
+ // the end of the contained item. If the contained match
+ // included the end-of-line, break here, the region continues.
+ // Don't do this when:
+ // - "keepend" is used for the contained item
+ // - not at the end of the line (could be end="x$"me=e-1).
+ // - "excludenl" is used (HL_HAS_EOL won't be set)
+ if (cur_si->si_idx >= 0
+ && SYN_ITEMS(syn_block)[cur_si->si_idx].sp_type == SPTYPE_START
+ && !(cur_si->si_flags & (HL_MATCH | HL_KEEPEND))) {
+ update_si_end(cur_si, (int)current_col, true);
+ check_keepend();
+ if ((current_next_flags & HL_HAS_EOL)
+ && keepend_level < 0
+ && syn_getcurline()[current_col] == NUL) {
+ break;
}
}
} else {
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 76c69ad10b..c1a120efa4 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -299,6 +299,40 @@ func Test_WinClosed()
unlet g:triggered
endfunc
+func Test_WinClosed_throws()
+ vnew
+ let bnr = bufnr()
+ call assert_equal(1, bufloaded(bnr))
+ augroup test-WinClosed
+ autocmd WinClosed * throw 'foo'
+ augroup END
+ try
+ close
+ catch /.*/
+ endtry
+ call assert_equal(0, bufloaded(bnr))
+
+ autocmd! test-WinClosed
+ augroup! test-WinClosed
+endfunc
+
+func Test_WinClosed_throws_with_tabs()
+ tabnew
+ let bnr = bufnr()
+ call assert_equal(1, bufloaded(bnr))
+ augroup test-WinClosed
+ autocmd WinClosed * throw 'foo'
+ augroup END
+ try
+ close
+ catch /.*/
+ endtry
+ call assert_equal(0, bufloaded(bnr))
+
+ autocmd! test-WinClosed
+ augroup! test-WinClosed
+endfunc
+
func s:AddAnAutocmd()
augroup vimBarTest
au BufReadCmd * echo 'hello'
diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim
index 10eb979b45..be9a77ee75 100644
--- a/src/nvim/testdir/test_diffmode.vim
+++ b/src/nvim/testdir/test_diffmode.vim
@@ -1295,4 +1295,41 @@ func Test_diff_filler_cursorcolumn()
endfunc
+func Test_diff_binary()
+ CheckScreendump
+
+ let content =<< trim END
+ call setline(1, ['a', 'b', "c\n", 'd', 'e', 'f', 'g'])
+ vnew
+ call setline(1, ['A', 'b', 'c', 'd', 'E', 'f', 'g'])
+ windo diffthis
+ wincmd p
+ norm! gg0
+ redraw!
+ END
+ call writefile(content, 'Xtest_diff_bin')
+ let buf = RunVimInTerminal('-S Xtest_diff_bin', {})
+
+ " Test using internal diff
+ call VerifyScreenDump(buf, 'Test_diff_bin_01', {})
+
+ " Test using internal diff and case folding
+ call term_sendkeys(buf, ":set diffopt+=icase\<cr>")
+ call term_sendkeys(buf, "\<C-l>")
+ call VerifyScreenDump(buf, 'Test_diff_bin_02', {})
+ " Test using external diff
+ call term_sendkeys(buf, ":set diffopt=filler\<cr>")
+ call term_sendkeys(buf, "\<C-l>")
+ call VerifyScreenDump(buf, 'Test_diff_bin_03', {})
+ " Test using external diff and case folding
+ call term_sendkeys(buf, ":set diffopt=filler,icase\<cr>")
+ call term_sendkeys(buf, "\<C-l>")
+ call VerifyScreenDump(buf, 'Test_diff_bin_04', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('Xtest_diff_bin')
+ set diffopt&vim
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim
index 360b3aaaa0..eea5d190b2 100644
--- a/src/nvim/testdir/test_edit.vim
+++ b/src/nvim/testdir/test_edit.vim
@@ -1627,6 +1627,29 @@ func Test_edit_is_a_directory()
call delete(dirname, 'rf')
endfunc
+" Using :edit without leaving 'insertmode' should not cause Insert mode to be
+" re-entered immediately after <C-L>
+func Test_edit_insertmode_ex_edit()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ set insertmode noruler
+ inoremap <C-B> <Cmd>edit Xfoo<CR>
+ END
+ call writefile(lines, 'Xtest_edit_insertmode_ex_edit')
+
+ let buf = RunVimInTerminal('-S Xtest_edit_insertmode_ex_edit', #{rows: 6})
+ call TermWait(buf, 50)
+ call assert_match('^-- INSERT --\s*$', term_getline(buf, 6))
+ call term_sendkeys(buf, "\<C-B>\<C-L>")
+ call TermWait(buf, 50)
+ call assert_notmatch('^-- INSERT --\s*$', term_getline(buf, 6))
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('Xtest_edit_insertmode_ex_edit')
+endfunc
+
func Test_edit_browse()
" in the GUI this opens a file picker, we only test the terminal behavior
CheckNotGui
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index a31ff50a48..42271a014d 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -395,7 +395,7 @@ let s:filename_checks = {
\ 'perl': ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc'],
\ 'pf': ['pf.conf'],
\ 'pfmain': ['main.cf'],
- \ 'php': ['file.php', 'file.php9', 'file.phtml', 'file.ctp'],
+ \ 'php': ['file.php', 'file.php9', 'file.phtml', 'file.ctp', 'file.phpt'],
\ 'lpc': ['file.lpc', 'file.ulpc'],
\ 'pike': ['file.pike', 'file.pmod'],
\ 'cmod': ['file.cmod'],
diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim
index 5588e515e1..efdf44a0d6 100644
--- a/src/nvim/testdir/test_highlight.vim
+++ b/src/nvim/testdir/test_highlight.vim
@@ -615,6 +615,14 @@ func Test_cursorcolumn_insert_on_tab()
call TermWait(buf)
call VerifyScreenDump(buf, 'Test_cursorcolumn_insert_on_tab_2', {})
+ call term_sendkeys(buf, "\<C-O>")
+ call TermWait(buf)
+ call VerifyScreenDump(buf, 'Test_cursorcolumn_insert_on_tab_3', {})
+
+ call term_sendkeys(buf, 'i')
+ call TermWait(buf)
+ call VerifyScreenDump(buf, 'Test_cursorcolumn_insert_on_tab_2', {})
+
call StopVimInTerminal(buf)
call delete('Xcuc_insert_on_tab')
endfunc
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index 186fa8871f..24eaf9e8b1 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -707,4 +707,23 @@ func Test_z1_complete_no_history()
close!
endfunc
+func FooBarComplete(findstart, base)
+ if a:findstart
+ return col('.') - 1
+ else
+ return ["Foo", "Bar", "}"]
+ endif
+endfunc
+
+func Test_complete_smartindent()
+ new
+ setlocal smartindent completefunc=FooBarComplete
+
+ exe "norm! o{\<cr>\<c-x>\<c-u>\<c-p>}\<cr>\<esc>"
+ let result = getline(1,'$')
+ call assert_equal(['', '{','}',''], result)
+ bw!
+ delfunction! FooBarComplete
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_registers.vim b/src/nvim/testdir/test_registers.vim
index f78b748d71..c623edd5a1 100644
--- a/src/nvim/testdir/test_registers.vim
+++ b/src/nvim/testdir/test_registers.vim
@@ -690,5 +690,23 @@ func Test_record_in_select_mode()
bwipe!
endfunc
+func Test_end_reg_executing()
+ nnoremap s <Nop>
+ let @a = 's'
+ call feedkeys("@aqaq\<Esc>", 'tx')
+ call assert_equal('', @a)
+ call assert_equal('', getline(1))
+
+ call setline(1, 'aaa')
+ nnoremap s qa
+ let @a = 'fa'
+ call feedkeys("@asq\<Esc>", 'tx')
+ call assert_equal('', @a)
+ call assert_equal('aaa', getline(1))
+
+ nunmap s
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_trycatch.vim b/src/nvim/testdir/test_trycatch.vim
index 7e513180a3..adc1745b39 100644
--- a/src/nvim/testdir/test_trycatch.vim
+++ b/src/nvim/testdir/test_trycatch.vim
@@ -1972,6 +1972,29 @@ func Test_builtin_func_error()
call assert_equal('jlmnpqrtueghivyzACD', g:Xpath)
endfunc
-" Modelines {{{1
+func Test_reload_in_try_catch()
+ call writefile(['x'], 'Xreload')
+ set autoread
+ edit Xreload
+ tabnew
+ call writefile(['xx'], 'Xreload')
+ augroup ReLoad
+ au FileReadPost Xreload let x = doesnotexist
+ au BufReadPost Xreload let x = doesnotexist
+ augroup END
+ try
+ edit Xreload
+ catch
+ endtry
+ tabnew
+
+ tabclose
+ tabclose
+ autocmd! ReLoad
+ set noautoread
+ bwipe! Xreload
+ call delete('Xreload')
+endfunc
+
+" Modeline {{{1
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
-"-------------------------------------------------------------------------------
diff --git a/src/nvim/window.c b/src/nvim/window.c
index cc21bf25b0..9aa2f947cb 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -2541,6 +2541,41 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
return true;
}
+/// Close the buffer of "win" and unload it if "free_buf" is true.
+/// "abort_if_last" is passed to close_buffer(): abort closing if all other
+/// windows are closed.
+static void win_close_buffer(win_T *win, bool free_buf, bool abort_if_last)
+{
+ // Free independent synblock before the buffer is freed.
+ if (win->w_buffer != NULL) {
+ reset_synblock(win);
+ }
+
+ // When a quickfix/location list window is closed and the buffer is
+ // displayed in only one window, then unlist the buffer.
+ if (win->w_buffer != NULL && bt_quickfix(win->w_buffer)
+ && win->w_buffer->b_nwindows == 1) {
+ win->w_buffer->b_p_bl = false;
+ }
+
+ // Close the link to the buffer.
+ if (win->w_buffer != NULL) {
+ bufref_T bufref;
+ set_bufref(&bufref, curbuf);
+ win->w_closing = true;
+ close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, abort_if_last, true);
+ if (win_valid_any_tab(win)) {
+ win->w_closing = false;
+ }
+
+ // Make sure curbuf is valid. It can become invalid if 'bufhidden' is
+ // "wipe".
+ if (!bufref_valid(&bufref)) {
+ curbuf = firstbuf;
+ }
+ }
+}
+
// Close window "win". Only works for the current tab page.
// If "free_buf" is true related buffer may be unloaded.
//
@@ -2679,36 +2714,7 @@ int win_close(win_T *win, bool free_buf, bool force)
return OK;
}
- // Free independent synblock before the buffer is freed.
- if (win->w_buffer != NULL) {
- reset_synblock(win);
- }
-
- // When a quickfix/location list window is closed and the buffer is
- // displayed in only one window, then unlist the buffer.
- if (win->w_buffer != NULL && bt_quickfix(win->w_buffer)
- && win->w_buffer->b_nwindows == 1) {
- win->w_buffer->b_p_bl = false;
- }
-
- /*
- * Close the link to the buffer.
- */
- if (win->w_buffer != NULL) {
- bufref_T bufref;
- set_bufref(&bufref, curbuf);
- win->w_closing = true;
- close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, true);
- if (win_valid_any_tab(win)) {
- win->w_closing = false;
- }
-
- // Make sure curbuf is valid. It can become invalid if 'bufhidden' is
- // "wipe".
- if (!bufref_valid(&bufref)) {
- curbuf = firstbuf;
- }
- }
+ win_close_buffer(win, free_buf, true);
if (only_one_window() && win_valid(win) && win->w_buffer == NULL
&& (last_window(win) || curtab != prev_curtab
@@ -2879,7 +2885,7 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
if (win->w_buffer != NULL) {
// 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, true);
}
// Careful: Autocommands may have closed the tab page or made it the