aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2025-01-20 11:02:58 +0100
committerGitHub <noreply@github.com>2025-01-20 11:02:58 +0100
commit71922cd1dc3bb6e040d7ab1ecd4d457f979a98fa (patch)
tree73b996f8b40ec429f76cad646464972920e26f4d
parent5b025b499ec430f1733409f0fb5ba3f88ce25a88 (diff)
parent59da82abd91e3be7eb5403c14de012cd149a1c84 (diff)
downloadrneovim-71922cd1dc3bb6e040d7ab1ecd4d457f979a98fa.tar.gz
rneovim-71922cd1dc3bb6e040d7ab1ecd4d457f979a98fa.tar.bz2
rneovim-71922cd1dc3bb6e040d7ab1ecd4d457f979a98fa.zip
Merge pull request #31597 from bfredl/deletionism
fix(wininfo): when freeing windows, free the lowest priority wininfo
-rw-r--r--src/nvim/window.c11
-rw-r--r--test/functional/api/window_spec.lua42
2 files changed, 49 insertions, 4 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 1c0d8c1027..fa2bfec138 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5243,11 +5243,13 @@ void win_free(win_T *wp, tabpage_T *tp)
// freed memory is re-used for another window.
FOR_ALL_BUFFERS(buf) {
WinInfo *wip_wp = NULL;
+ size_t pos_wip = kv_size(buf->b_wininfo);
size_t pos_null = kv_size(buf->b_wininfo);
for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) {
WinInfo *wip = kv_A(buf->b_wininfo, i);
if (wip->wi_win == wp) {
wip_wp = wip;
+ pos_wip = i;
} else if (wip->wi_win == NULL) {
pos_null = i;
}
@@ -5255,11 +5257,12 @@ void win_free(win_T *wp, tabpage_T *tp)
if (wip_wp) {
wip_wp->wi_win = NULL;
- // If there already is an entry with "wi_win" set to NULL it
- // must be removed, it would never be used.
+ // If there already is an entry with "wi_win" set to NULL, only
+ // the first entry with NULL will ever be used, delete the other one.
if (pos_null < kv_size(buf->b_wininfo)) {
- free_wininfo(kv_A(buf->b_wininfo, pos_null), buf);
- kv_shift(buf->b_wininfo, pos_null, 1);
+ size_t pos_delete = MAX(pos_null, pos_wip);
+ free_wininfo(kv_A(buf->b_wininfo, pos_delete), buf);
+ kv_shift(buf->b_wininfo, pos_delete, 1);
}
}
}
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 078d581b6f..028f0beb38 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -506,6 +506,48 @@ describe('API/win', function()
assert_alive()
end)
+ describe('after closing', function()
+ local buf, win0, win1, win2
+
+ before_each(function()
+ win0 = api.nvim_get_current_win()
+ command('new')
+ buf = api.nvim_get_current_buf()
+ win1 = api.nvim_get_current_win()
+ command('set numberwidth=10')
+ command('split')
+ win2 = api.nvim_get_current_win()
+ command('set numberwidth=15')
+ command('enew')
+ api.nvim_set_current_win(win1)
+ command('normal ix')
+ command('enew')
+ api.nvim_set_current_win(win0)
+ eq(4, api.nvim_get_option_value('numberwidth', {}))
+ end)
+
+ -- at this point buffer `buf` is current in no windows. Closing shouldn't affect its defaults
+ it('0 windows', function()
+ api.nvim_set_current_buf(buf)
+ eq(10, api.nvim_get_option_value('numberwidth', {}))
+ end)
+
+ it('1 window', function()
+ api.nvim_win_close(win1, false)
+
+ api.nvim_set_current_buf(buf)
+ eq(10, api.nvim_get_option_value('numberwidth', {}))
+ end)
+
+ it('2 windows', function()
+ api.nvim_win_close(win1, false)
+ api.nvim_win_close(win2, false)
+
+ api.nvim_set_current_buf(buf)
+ eq(10, api.nvim_get_option_value('numberwidth', {}))
+ end)
+ end)
+
it('returns values for unset local options', function()
eq(-1, api.nvim_get_option_value('scrolloff', { win = 0, scope = 'local' }))
end)