diff options
-rw-r--r-- | src/nvim/ex_docmd.c | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 20 | ||||
-rw-r--r-- | src/nvim/window.c | 21 | ||||
-rw-r--r-- | test/functional/editor/tabpage_spec.lua | 42 | ||||
-rw-r--r-- | test/functional/terminal/buffer_spec.lua | 6 |
5 files changed, 77 insertions, 18 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index b01a262f84..085948f7b1 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4696,7 +4696,6 @@ void tabpage_close(int forceit) void tabpage_close_other(tabpage_T *tp, int forceit) { int done = 0; - int h = tabline_height(); char prev_idx[NUMBUFLEN]; // Limit to 1000 windows, autocommands may add a window while we close @@ -4712,11 +4711,6 @@ void tabpage_close_other(tabpage_T *tp, int forceit) break; } } - - redraw_tabline = true; - if (h != tabline_height()) { - win_new_screen_rows(); - } } /// ":only". diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 1be2d11034..d766256d4b 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -447,6 +447,26 @@ func Test_WinClosed_throws_with_tabs() augroup! test-WinClosed endfunc +" This used to trigger WinClosed twice for the same window, and the window's +" buffer was NULL in the second autocommand. +func Test_WinClosed_switch_tab() + edit Xa + split Xb + split Xc + tab split + new + augroup test-WinClosed + autocmd WinClosed * tabprev | bwipe! + augroup END + close + " Check that the tabline has been fully removed + call assert_equal([1, 1], win_screenpos(0)) + + autocmd! test-WinClosed + augroup! test-WinClosed + %bwipe! +endfunc + func s:AddAnAutocmd() augroup vimBarTest au BufReadCmd * echo 'hello' diff --git a/src/nvim/window.c b/src/nvim/window.c index 236663dfea..22c1b77570 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2439,7 +2439,6 @@ void curwin_init(void) void close_windows(buf_T *buf, bool keep_curwin) { tabpage_T *tp, *nexttp; - int h = tabline_height(); RedrawingDisabled++; @@ -2480,11 +2479,6 @@ void close_windows(buf_T *buf, bool keep_curwin) } RedrawingDisabled--; - - redraw_tabline = true; - if (h != tabline_height()) { - win_new_screen_rows(); - } } /// Check that the specified window is the last one. @@ -2575,7 +2569,6 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev // Don't trigger autocommands yet, they may use wrong values, so do // that below. goto_tabpage_tp(alt_tabpage(), false, true); - redraw_tabline = true; // save index for tabclosed event char_u prev_idx[NUMBUFLEN]; @@ -2584,12 +2577,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev // Safety check: Autocommands may have closed the window when jumping // to the other tab page. if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win) { - int h = tabline_height(); - win_close_othertab(win, free_buf, prev_curtab); - if (h != tabline_height()) { - win_new_screen_rows(); - } } entering_window(curwin); @@ -2793,7 +2781,10 @@ int win_close(win_T *win, bool free_buf, bool force) if (curtab != prev_curtab && win_valid_any_tab(win) && win->w_buffer == NULL) { // Need to close the window anyway, since the buffer is NULL. + // Don't trigger autocmds with a NULL buffer. + block_autocmds(); win_close_othertab(win, false, prev_curtab); + unblock_autocmds(); return FAIL; } @@ -2990,6 +2981,8 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) vim_snprintf(prev_idx, NUMBUFLEN, "%i", tabpage_index(tp)); } + int h = tabline_height(); + if (tp == first_tabpage) { first_tabpage = tp->tp_next; } else { @@ -3004,6 +2997,10 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) ptp->tp_next = tp->tp_next; } free_tp = true; + redraw_tabline = true; + if (h != tabline_height()) { + win_new_screen_rows(); + } if (has_event(EVENT_TABCLOSED)) { apply_autocmds(EVENT_TABCLOSED, prev_idx, prev_idx, false, win->w_buffer); diff --git a/test/functional/editor/tabpage_spec.lua b/test/functional/editor/tabpage_spec.lua index 849a02c28b..01779a9a92 100644 --- a/test/functional/editor/tabpage_spec.lua +++ b/test/functional/editor/tabpage_spec.lua @@ -9,6 +9,9 @@ local feed = helpers.feed local eval = helpers.eval local exec = helpers.exec local funcs = helpers.funcs +local meths = helpers.meths +local curwin = helpers.curwin +local assert_alive = helpers.assert_alive describe('tabpage', function() before_each(clear) @@ -54,6 +57,45 @@ describe('tabpage', function() neq(999, eval('g:win_closed')) end) + it('no segfault with strange WinClosed autocommand #20290', function() + pcall(exec, [[ + set nohidden + edit Xa + split Xb + tab split + new + autocmd WinClosed * tabprev | bwipe! + close + ]]) + assert_alive() + end) + + it('nvim_win_close and nvim_win_hide update tabline #20285', function() + eq(1, #meths.list_tabpages()) + eq({1, 1}, funcs.win_screenpos(0)) + local win1 = curwin().id + + command('tabnew') + eq(2, #meths.list_tabpages()) + eq({2, 1}, funcs.win_screenpos(0)) + local win2 = curwin().id + + meths.win_close(win1, true) + eq(win2, curwin().id) + eq(1, #meths.list_tabpages()) + eq({1, 1}, funcs.win_screenpos(0)) + + command('tabnew') + eq(2, #meths.list_tabpages()) + eq({2, 1}, funcs.win_screenpos(0)) + local win3 = curwin().id + + meths.win_close(win2, true) + eq(win3, curwin().id) + eq(1, #meths.list_tabpages()) + eq({1, 1}, funcs.win_screenpos(0)) + end) + it('switching tabpage after setting laststatus=3 #19591', function() local screen = Screen.new(40, 8) screen:set_default_attr_ids({ diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index 23430a620b..9d10f43ec6 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -4,6 +4,7 @@ local assert_alive = helpers.assert_alive local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim local poke_eventloop = helpers.poke_eventloop local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source +local pcall_err = helpers.pcall_err local eq, neq = helpers.eq, helpers.neq local meths = helpers.meths local retry = helpers.retry @@ -339,6 +340,11 @@ describe(':terminal buffer', function() ]]} eq('t', funcs.mode(1)) end) + + it('writing to an existing file with :w fails #13549', function() + eq('Vim(write):E13: File exists (add ! to override)', + pcall_err(command, 'write test/functional/fixtures/tty-test.c')) + end) end) describe('No heap-buffer-overflow when using', function() |