aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/autocmd.c2
-rw-r--r--src/nvim/api/keysets.lua2
-rw-r--r--src/nvim/buffer.c4
-rw-r--r--src/nvim/diff.c2
-rw-r--r--src/nvim/eval.c3
-rw-r--r--src/nvim/ex_docmd.c2
-rw-r--r--src/nvim/testdir/test_autocmd.vim17
-rw-r--r--src/nvim/window.c126
8 files changed, 86 insertions, 72 deletions
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 9aaa0418dc..49f6f98ba4 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -695,7 +695,7 @@ void nvim_del_augroup_by_name(String name)
/// - modeline (bool) optional: defaults to true. Process the
/// modeline after the autocommands |<nomodeline>|.
/// @see |:doautocmd|
-void nvim_do_autocmd(Object event, Dict(do_autocmd) *opts, Error *err)
+void nvim_exec_autocmd(Object event, Dict(exec_autocmd) *opts, Error *err)
FUNC_API_SINCE(9)
{
int au_group = AUGROUP_ALL;
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index b6264cdfab..6a29b0fb59 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -133,7 +133,7 @@ return {
"nested";
"pattern";
};
- do_autocmd = {
+ exec_autocmd = {
"buffer";
"group";
"modeline";
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 4ca752e747..bf592a626d 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -590,6 +590,10 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
// Remove the buffer from the list.
if (wipe_buf) {
+ // Do not wipe out the buffer if it is used in a window.
+ if (buf->b_nwindows > 0) {
+ return false;
+ }
if (buf->b_sfname != buf->b_ffname) {
XFREE_CLEAR(buf->b_sfname);
} else {
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 1b8a9f41e9..a6bbe40999 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -1536,7 +1536,7 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
long off;
int i;
int notset = true; // block "*dp" not set yet
- diffhunk_T *hunk;
+ diffhunk_T *hunk = NULL; // init to avoid gcc warning
enum {
DIFF_ED,
DIFF_UNIFIED,
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index fbbc543893..6c72c2866e 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -9217,6 +9217,8 @@ dictitem_T *find_var_in_ht(hashtab_T *const ht, int htname, const char *const va
/// Finds the dict (g:, l:, s:, …) and hashtable used for a variable.
///
+/// Assigns SID if s: scope is accessed from Lua or anonymous Vimscript. #15994
+///
/// @param[in] name Variable name, possibly with scope prefix.
/// @param[in] name_len Variable name length.
/// @param[out] varname Will be set to the start of the name without scope
@@ -9304,6 +9306,7 @@ static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, cons
}
}
if (current_sctx.sc_sid == SID_STR || current_sctx.sc_sid == SID_LUA) {
+ // Create SID if s: scope is accessed from Lua or anon Vimscript. #15994
new_script_item(NULL, &current_sctx.sc_sid);
}
*d = &SCRIPT_SV(current_sctx.sc_sid)->sv_dict;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 0dbc9d6b14..20325509c4 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -6839,7 +6839,7 @@ void tabpage_close_other(tabpage_T *tp, int forceit)
// Autocommands may delete the tab page under our fingers and we may
// fail to close a window with a modified buffer.
- if (!valid_tabpage(tp) || tp->tp_firstwin == wp) {
+ if (!valid_tabpage(tp) || tp->tp_lastwin == wp) {
break;
}
}
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index d4005e41e8..76c69ad10b 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -2611,4 +2611,21 @@ func Test_autocmd_closing_cmdwin()
only
endfunc
+func Test_bufwipeout_changes_window()
+ " This should not crash, but we don't have any expectations about what
+ " happens, changing window in BufWipeout has unpredictable results.
+ tabedit
+ let g:window_id = win_getid()
+ topleft new
+ setlocal bufhidden=wipe
+ autocmd BufWipeout <buffer> call win_gotoid(g:window_id)
+ tabprevious
+ +tabclose
+
+ unlet g:window_id
+ au! BufWipeout
+ %bwipe!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/window.c b/src/nvim/window.c
index fa71a08b94..6bd2ef3ef6 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -971,7 +971,6 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
int before;
int minheight;
int wmh1;
- int hsep_height;
bool did_set_fraction = false;
// aucmd_win should always remain floating
@@ -1084,7 +1083,6 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
}
} else {
- hsep_height = STATUS_HEIGHT;
layout = FR_COL;
/*
@@ -1093,7 +1091,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
*/
// Current window requires at least 1 space.
wmh1 = p_wmh == 0 ? 1 : p_wmh;
- needed = wmh1 + hsep_height;
+ needed = wmh1 + STATUS_HEIGHT;
if (flags & WSP_ROOM) {
needed += p_wh - wmh1;
}
@@ -1135,15 +1133,15 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
new_size = oldwin_height / 2;
}
- if (new_size > available - minheight - hsep_height) {
- new_size = available - minheight - hsep_height;
+ if (new_size > available - minheight - STATUS_HEIGHT) {
+ new_size = available - minheight - STATUS_HEIGHT;
}
if (new_size < wmh1) {
new_size = wmh1;
}
// if it doesn't fit in the current window, need win_equal()
- if (oldwin_height - new_size - hsep_height < p_wmh) {
+ if (oldwin_height - new_size - STATUS_HEIGHT < p_wmh) {
do_equal = true;
}
@@ -1156,7 +1154,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
set_fraction(oldwin);
did_set_fraction = true;
- win_setheight_win(oldwin->w_height + new_size + hsep_height,
+ win_setheight_win(oldwin->w_height + new_size + STATUS_HEIGHT,
oldwin);
oldwin_height = oldwin->w_height;
if (need_status) {
@@ -1173,7 +1171,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
while (frp != NULL) {
if (frp->fr_win != oldwin && frp->fr_win != NULL
&& (frp->fr_win->w_height > new_size
- || frp->fr_win->w_height > oldwin_height - new_size - hsep_height)) {
+ || frp->fr_win->w_height > oldwin_height - new_size - STATUS_HEIGHT)) {
do_equal = true;
break;
}
@@ -2021,7 +2019,6 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
int room = 0;
int new_size;
int has_next_curwin = 0;
- int hsep_height;
bool hnc;
if (topfr->fr_layout == FR_LEAF) {
@@ -2167,7 +2164,6 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
totwincount -= wincount;
}
} else { // topfr->fr_layout == FR_COL
- hsep_height = STATUS_HEIGHT;
topfr->fr_width = width;
topfr->fr_height = height;
@@ -2182,7 +2178,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
} else {
extra_sep = 0;
}
- totwincount = (n + extra_sep) / (p_wmh + hsep_height);
+ totwincount = (n + extra_sep) / (p_wmh + STATUS_HEIGHT);
has_next_curwin = frame_has_win(topfr, next_curwin);
/*
@@ -2217,7 +2213,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
} else {
// These windows don't use up room.
totwincount -= (n + (fr->fr_next == NULL
- ? extra_sep : 0)) / (p_wmh + hsep_height);
+ ? extra_sep : 0)) / (p_wmh + STATUS_HEIGHT);
}
room -= new_size - n;
if (room < 0) {
@@ -2263,7 +2259,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
// Compute the maximum number of windows vert. in "fr".
n = frame_minheight(fr, NOWIN);
wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
- / (p_wmh + hsep_height);
+ / (p_wmh + STATUS_HEIGHT);
m = frame_minheight(fr, next_curwin);
if (has_next_curwin) {
hnc = frame_has_win(fr, next_curwin);
@@ -2350,6 +2346,30 @@ void entering_window(win_T *const win)
}
}
+void win_init_empty(win_T *wp)
+{
+ redraw_later(wp, NOT_VALID);
+ wp->w_lines_valid = 0;
+ wp->w_cursor.lnum = 1;
+ wp->w_curswant = wp->w_cursor.col = 0;
+ wp->w_cursor.coladd = 0;
+ wp->w_pcmark.lnum = 1; // pcmark not cleared but set to line 1
+ wp->w_pcmark.col = 0;
+ wp->w_prev_pcmark.lnum = 0;
+ wp->w_prev_pcmark.col = 0;
+ wp->w_topline = 1;
+ wp->w_topfill = 0;
+ wp->w_botline = 2;
+ wp->w_s = &wp->w_buffer->b_s;
+}
+
+/// Init the current window "curwin".
+/// Called when a new file is being edited.
+void curwin_init(void)
+{
+ win_init_empty(curwin);
+}
+
/// Closes all windows for buffer `buf` unless there is only one non-floating window.
///
/// @param keep_curwin don't close `curwin`
@@ -2867,6 +2887,13 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next) {
}
if (ptp == NULL || tp == curtab) {
+ // If the buffer was removed from the window we have to give it any
+ // buffer.
+ if (win_valid_any_tab(win) && win->w_buffer == NULL) {
+ win->w_buffer = firstbuf;
+ firstbuf->b_nwindows++;
+ win_init_empty(win);
+ }
return;
}
@@ -3793,33 +3820,6 @@ void close_others(int message, int forceit)
}
}
-
-/*
- * Init the current window "curwin".
- * Called when a new file is being edited.
- */
-void curwin_init(void)
-{
- win_init_empty(curwin);
-}
-
-void win_init_empty(win_T *wp)
-{
- redraw_later(wp, NOT_VALID);
- wp->w_lines_valid = 0;
- wp->w_cursor.lnum = 1;
- wp->w_curswant = wp->w_cursor.col = 0;
- wp->w_cursor.coladd = 0;
- wp->w_pcmark.lnum = 1; // pcmark not cleared but set to line 1
- wp->w_pcmark.col = 0;
- wp->w_prev_pcmark.lnum = 0;
- wp->w_prev_pcmark.col = 0;
- wp->w_topline = 1;
- wp->w_topfill = 0;
- wp->w_botline = 2;
- wp->w_s = &wp->w_buffer->b_s;
-}
-
/*
* Allocate the first window and put an empty buffer in it.
* Called from main().
@@ -6510,38 +6510,32 @@ void last_status(bool morewin)
}
// Look for resizable frames and take lines from them to make room for the statusline
-static void resize_frame_for_status(frame_T *fr, int resize_amount)
+static void resize_frame_for_status(frame_T *fr)
{
// Find a frame to take a line from.
frame_T *fp = fr;
win_T *wp = fr->fr_win;
- int n;
- while (resize_amount > 0) {
- while (fp->fr_height <= frame_minheight(fp, NULL)) {
- if (fp == topframe) {
- emsg(_(e_noroom));
- return;
- }
- // In a column of frames: go to frame above. If already at
- // the top or in a row of frames: go to parent.
- if (fp->fr_parent->fr_layout == FR_COL && fp->fr_prev != NULL) {
- fp = fp->fr_prev;
- } else {
- fp = fp->fr_parent;
- }
+ while (fp->fr_height <= frame_minheight(fp, NULL)) {
+ if (fp == topframe) {
+ emsg(_(e_noroom));
+ return;
}
- n = MIN(fp->fr_height - frame_minheight(fp, NULL), resize_amount);
- resize_amount -= n;
-
- if (fp != fr) {
- frame_new_height(fp, fp->fr_height - n, false, false);
- frame_fix_height(wp);
- (void)win_comp_pos();
+ // In a column of frames: go to frame above. If already at
+ // the top or in a row of frames: go to parent.
+ if (fp->fr_parent->fr_layout == FR_COL && fp->fr_prev != NULL) {
+ fp = fp->fr_prev;
} else {
- win_new_height(wp, wp->w_height - n);
+ fp = fp->fr_parent;
}
}
+ if (fp != fr) {
+ frame_new_height(fp, fp->fr_height - 1, false, false);
+ frame_fix_height(wp);
+ (void)win_comp_pos();
+ } else {
+ win_new_height(wp, wp->w_height - 1);
+ }
}
static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
@@ -6562,15 +6556,12 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
} else if (wp->w_status_height == 0 && !is_stl_global && statusline) {
// Add statusline to window if needed
wp->w_status_height = STATUS_HEIGHT;
- resize_frame_for_status(fr, STATUS_HEIGHT);
+ resize_frame_for_status(fr);
comp_col();
}
} else if (wp->w_status_height != 0 && is_stl_global) {
// If statusline is global and the window has a statusline, replace it with a horizontal
// separator
- if (STATUS_HEIGHT - 1 != 0) {
- win_new_height(wp, wp->w_height + STATUS_HEIGHT - 1);
- }
wp->w_status_height = 0;
wp->w_hsep_height = 1;
comp_col();
@@ -6578,7 +6569,6 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
// If statusline isn't global and the window doesn't have a statusline, re-add it
wp->w_status_height = STATUS_HEIGHT;
wp->w_hsep_height = 0;
- resize_frame_for_status(fr, STATUS_HEIGHT - 1);
comp_col();
}
redraw_all_later(SOME_VALID);