From 950a88d4c2a9c17b5a679b4e41fab9f64b8cf9df Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 29 Jan 2022 20:37:28 +0800 Subject: vim-patch:8.2.4248: no proper test for moving the window separator Problem: No proper test for moving the window separator. Solution: Add a test. Add comment in code. (closes vim/vim#9656) https://github.com/vim/vim/commit/a0c4e2f2d7aa164d9d7692702c752ea063bd3a8c Remove the assertion as it is now possible for `fr` to be `NULL`. The test fails without clearing messages. Not sure if this is a bug. --- src/nvim/window.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 1e747a67e9..8e44fd5014 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5795,7 +5795,6 @@ void win_drag_vsep_line(win_T *dragwin, int offset) } fr = curfr; // put fr at window that grows } - assert(fr); // Not enough room if (room < offset) { @@ -5808,7 +5807,9 @@ void win_drag_vsep_line(win_T *dragwin, int offset) } if (fr == NULL) { - return; // Safety check, should not happen. + // This can happen when calling win_move_separator() on the rightmost + // window. Just don't do anything. + return; } // grow frame fr by offset lines -- cgit From f326c9a77da3aef052ce6af0f851344f2479c844 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Thu, 6 Jan 2022 13:48:37 +0000 Subject: vim-patch:8.2.4018: ml_get error when win_execute redraws with Visual selection Problem: ml_get error when win_execute redraws with Visual selection. Solution: Disable Visual area temporarily. (closes vim/vim#9479) https://github.com/vim/vim/commit/18f4740f043b353abe47b7a00131317052457686 {switch_to/restore}_win_for_buf is N/A (marked as such in v8.0.0860; currently only used in Vim's if_py). Add a modeline to test_execute_func.vim. --- src/nvim/window.c | 53 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 8e44fd5014..6996a93928 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -577,18 +577,19 @@ static void cmd_with_count(char *cmd, char_u *bufp, size_t bufsize, int64_t Pren void win_set_buf(Window window, Buffer buffer, bool noautocmd, Error *err) { - win_T *win = find_window_by_handle(window, err), *save_curwin = curwin; + win_T *win = find_window_by_handle(window, err); buf_T *buf = find_buffer_by_handle(buffer, err); - tabpage_T *tab = win_find_tabpage(win), *save_curtab = curtab; + tabpage_T *tab = win_find_tabpage(win); if (!win || !buf) { return; } - if (noautocmd) { block_autocmds(); } - if (switch_win_noblock(&save_curwin, &save_curtab, win, tab, false) == FAIL) { + + switchwin_T switchwin; + if (switch_win_noblock(&switchwin, win, tab, false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to switch to window %d", @@ -608,7 +609,7 @@ void win_set_buf(Window window, Buffer buffer, bool noautocmd, Error *err) // So do it now. validate_cursor(); - restore_win_noblock(save_curwin, save_curtab, false); + restore_win_noblock(&switchwin, false); if (noautocmd) { unblock_autocmds(); } @@ -6631,20 +6632,27 @@ static win_T *get_snapshot_focus(int idx) /// triggered, another tabpage access is limited. /// /// @return FAIL if switching to "win" failed. -int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp, - bool no_display) +int switch_win(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_display) { block_autocmds(); - return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display); + return switch_win_noblock(switchwin, win, tp, no_display); } // As switch_win() but without blocking autocommands. -int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp, - bool no_display) +int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_display) { - *save_curwin = curwin; + memset(switchwin, 0, sizeof(switchwin_T)); + switchwin->sw_curwin = curwin; + if (win == curwin) { + switchwin->sw_same_win = true; + } else { + // Disable Visual selection, because redrawing may fail. + switchwin->sw_visual_active = VIsual_active; + VIsual_active = false; + } + if (tp != NULL) { - *save_curtab = curtab; + switchwin->sw_curtab = curtab; if (no_display) { curtab->tp_firstwin = firstwin; curtab->tp_lastwin = lastwin; @@ -6666,28 +6674,33 @@ int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, // Restore current tabpage and window saved by switch_win(), if still valid. // When "no_display" is true the display won't be affected, no redraw is // triggered. -void restore_win(win_T *save_curwin, tabpage_T *save_curtab, bool no_display) +void restore_win(switchwin_T *switchwin, bool no_display) { - restore_win_noblock(save_curwin, save_curtab, no_display); + restore_win_noblock(switchwin, no_display); unblock_autocmds(); } // As restore_win() but without unblocking autocommands. -void restore_win_noblock(win_T *save_curwin, tabpage_T *save_curtab, bool no_display) +void restore_win_noblock(switchwin_T *switchwin, bool no_display) { - if (save_curtab != NULL && valid_tabpage(save_curtab)) { + if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab)) { if (no_display) { curtab->tp_firstwin = firstwin; curtab->tp_lastwin = lastwin; - curtab = save_curtab; + curtab = switchwin->sw_curtab; firstwin = curtab->tp_firstwin; lastwin = curtab->tp_lastwin; } else { - goto_tabpage_tp(save_curtab, false, false); + goto_tabpage_tp(switchwin->sw_curtab, false, false); } } - if (win_valid(save_curwin)) { - curwin = save_curwin; + + if (!switchwin->sw_same_win) { + VIsual_active = switchwin->sw_visual_active; + } + + if (win_valid(switchwin->sw_curwin)) { + curwin = switchwin->sw_curwin; curbuf = curwin->w_buffer; } // If called by win_execute() and executing the command changed the -- cgit From 85ae04dbfd405343b10c400d40e95334a44cc978 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 17 Apr 2021 17:33:59 -0400 Subject: fix: close floating windows when calling win_close() --- src/nvim/window.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 6996a93928..83d5910400 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -304,7 +304,7 @@ newwindow: newtab = curtab; goto_tabpage_tp(oldtab, true, true); if (curwin == wp) { - win_close(curwin, false); + win_close(curwin, false, false); } if (valid_tabpage(newtab)) { goto_tabpage_tp(newtab, true, true); @@ -449,7 +449,7 @@ wingotofile: RESET_BINDING(curwin); if (do_ecmd(0, ptr, NULL, NULL, ECMD_LASTL, ECMD_HIDE, NULL) == FAIL) { // Failed to open the file, close the window opened for it. - win_close(curwin, false); + win_close(curwin, false, false); goto_tabpage_win(oldtab, oldwin); } else if (nchar == 'F' && lnum >= 0) { curwin->w_cursor.lnum = lnum; @@ -2290,7 +2290,7 @@ void close_windows(buf_T *buf, int keep_curwin) for (win_T *wp = firstwin; wp != NULL && !ONE_WINDOW;) { if (wp->w_buffer == buf && (!keep_curwin || wp != curwin) && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { - if (win_close(wp, false) == FAIL) { + if (win_close(wp, false, false) == FAIL) { // If closing the window fails give up, to avoid looping forever. break; } @@ -2368,6 +2368,22 @@ bool last_nonfloat(win_T *wp) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT return wp != NULL && firstwin == wp && !(wp->w_next && !wp->w_floating); } +/// Check if floating windows can be closed. +/// +/// @return true if all floating windows can be closed +static bool can_close_floating_windows(tabpage_T *tab) +{ + FOR_ALL_WINDOWS_IN_TAB(wp, tab) { + buf_T *buf = wp->w_buffer; + int need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1); + + if (need_hide && !buf_hide(buf)) { + return false; + } + } + return true; +} + /// Close the possibly last window in a tab page. /// /// @param win window to close @@ -2432,7 +2448,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev // // Called by :quit, :close, :xit, :wq and findtag(). // Returns FAIL when the window was not closed. -int win_close(win_T *win, bool free_buf) +int win_close(win_T *win, bool free_buf, bool force) { win_T *wp; bool other_buffer = false; @@ -2462,9 +2478,18 @@ int win_close(win_T *win, bool free_buf) } if ((firstwin == win && lastwin_nofloating() == win) && lastwin->w_floating) { - // TODO(bfredl): we might close the float also instead - emsg(e_floatonly); - return FAIL; + if (force || can_close_floating_windows(curtab)) { + win_T *nextwp; + for (win_T *wpp = firstwin; wpp != NULL; wpp = nextwp) { + nextwp = wpp->w_next; + if (wpp->w_floating) { + win_close(wpp, free_buf, force); + } + } + } else { + emsg(e_floatonly); + return FAIL; + } } // When closing the last window in a tab page first go to another tab page @@ -3611,7 +3636,9 @@ void close_others(int message, int forceit) continue; } } - win_close(wp, !buf_hide(wp->w_buffer) && !bufIsChanged(wp->w_buffer)); + win_close(wp, + !buf_hide(wp->w_buffer) && !bufIsChanged(wp->w_buffer), + false); } if (message && !ONE_WINDOW) { -- cgit From 059d36e326e31fc9bc6055d7c999f86d94fa9bd5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 11 Feb 2022 12:44:47 +0800 Subject: feat(events): add DirChangedPre In Nvim, like DirChanged, this also triggers when switching windows. This marks Vim patch 8.2.4335 as ported. vim-patch:8.2.4335: no autocommand event triggered before changing directory Problem: No autocommand event triggered before changing directory. (Ronnie Magatti) Solution: Add DirChangedPre. (closes vim/vim#9721) https://github.com/vim/vim/commit/28e8f73ae2d90009fd62cd60f97c2643ba44de68 --- src/nvim/window.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 6996a93928..83495801e8 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4645,20 +4645,29 @@ void fix_current_dir(void) globaldir = (char_u *)xstrdup(cwd); } } + bool dir_differs = pathcmp(new_dir, cwd, -1) != 0; + if (!p_acd && dir_differs) { + do_autocmd_dirchanged(new_dir, curwin->w_localdir ? kCdScopeWindow : kCdScopeTabpage, + kCdCauseWindow, true); + } if (os_chdir(new_dir) == 0) { - if (!p_acd && pathcmp(new_dir, cwd, -1) != 0) { - do_autocmd_dirchanged(new_dir, curwin->w_localdir - ? kCdScopeWindow : kCdScopeTabpage, kCdCauseWindow); + if (!p_acd && dir_differs) { + do_autocmd_dirchanged(new_dir, curwin->w_localdir ? kCdScopeWindow : kCdScopeTabpage, + kCdCauseWindow, false); } - last_chdir_reason = NULL; - shorten_fnames(true); } + last_chdir_reason = NULL; + shorten_fnames(true); } else if (globaldir != NULL) { // Window doesn't have a local directory and we are not in the global // directory: Change to the global directory. + bool dir_differs = pathcmp((char *)globaldir, cwd, -1) != 0; + if (!p_acd && dir_differs) { + do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow, true); + } if (os_chdir((char *)globaldir) == 0) { - if (!p_acd && pathcmp((char *)globaldir, cwd, -1) != 0) { - do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow); + if (!p_acd && dir_differs) { + do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow, false); } } XFREE_CLEAR(globaldir); -- cgit From 612696bedc8f178cb08645dfb056f01efacf5122 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 12 Feb 2022 06:36:17 +0800 Subject: vim-patch:8.1.2073: when editing a buffer 'colorcolumn' may not work Problem: When editing a buffer 'colorcolumn' may not work. Solution: Set the buffer before copying option values. Call check_colorcolumn() after copying window options. https://github.com/vim/vim/commit/010ee9657acf1a9f799079d718998c94e50ccadc --- src/nvim/window.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 83d5910400..4861b71995 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1482,8 +1482,6 @@ static void win_init(win_T *newp, win_T *oldp, int flags) copyFoldingState(oldp, newp); win_init_some(newp, oldp); - - didset_window_options(newp); } /* -- cgit From c23ec9d86e41e9dd03ab33ef8a80640e1366c476 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 12 Feb 2022 21:16:53 +0800 Subject: vim-patch:8.2.0580: window size wrong if 'ea' is off and 'splitright' is on Problem: Window size wrong if 'ea' is off and 'splitright' is on and splitting then closing a window. Solution: Put abandoned window space in the right place. (Mark Waggoner) https://github.com/vim/vim/commit/edd327cc070d9a05c12e88bc5c43a1e2a3086ae6 --- src/nvim/window.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 4861b71995..e09af7a7bb 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3079,9 +3079,21 @@ static frame_T *win_altframe(win_T *win, tabpage_T *tp) return frp->fr_prev; } + // By default the next window will get the space that was abandoned by this + // window frame_T *target_fr = frp->fr_next; frame_T *other_fr = frp->fr_prev; - if (p_spr || p_sb) { + + // If this is part of a column of windows and 'splitbelow' is true then the + // previous window will get the space. + if (frp->fr_parent != NULL && frp->fr_parent->fr_layout == FR_COL && p_sb) { + target_fr = frp->fr_prev; + other_fr = frp->fr_next; + } + + // If this is part of a row of windows, and 'splitright' is true then the + // previous window will get the space. + if (frp->fr_parent != NULL && frp->fr_parent->fr_layout == FR_ROW && p_spr) { target_fr = frp->fr_prev; other_fr = frp->fr_next; } -- cgit From 6eec30ccfc09f0ea45c9ef86a77ca92a5fc4a1b9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 15 Feb 2022 10:23:27 +0800 Subject: vim-patch:8.2.4154: ml_get error when exchanging windows in Visual mode Problem: ml_get error when exchanging windows in Visual mode. Solution: Correct end of Visual area when entering another buffer. https://github.com/vim/vim/commit/05b27615481e72e3b338bb12990fb3e0c2ecc2a9 --- src/nvim/window.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index e09af7a7bb..1e737d2083 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1727,6 +1727,12 @@ static void win_exchange(long Prenum) (void)win_comp_pos(); // recompute window positions + if (wp->w_buffer != curbuf) { + reset_VIsual_and_resel(); + } else if (VIsual_active) { + wp->w_cursor = curwin->w_cursor; + } + win_enter(wp, true); redraw_later(curwin, NOT_VALID); redraw_later(wp, NOT_VALID); -- cgit From 2deffb5ea8e2fc8dec2cc805dbed849ad6afa4b4 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Fri, 31 Dec 2021 09:32:04 +0000 Subject: fix(aucmd_win): ensure aucmd_win stays floating Nvim uses a floating window for the autocmd window, but in certain situations, it can be made non-floating (`:wincmd J`), which can cause issues due to the previous setup and cleanup logic for a non-floating aucmd_win being removed from aucmd_prepbuf and aucmd_restbuf. This can cause glitchiness and crashes due to the aucmd_win's frame being invalid after closing its tabpage, for example. Ensure aucmd_win cannot be made non-floating. The only place this happens is in win_split_ins if new_wp != NULL. --- src/nvim/window.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 43667377c5..549dd18e4f 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -958,6 +958,11 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) int wmh1; bool did_set_fraction = false; + // aucmd_win should always remain floating + if (new_wp != NULL && new_wp == aucmd_win) { + return FAIL; + } + if (flags & WSP_TOP) { oldwin = firstwin; } else if (flags & WSP_BOT || curwin->w_floating) { -- cgit From 430371da5ba40a791873b30a900ff34da95a9de4 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Tue, 22 Feb 2022 21:06:53 +0000 Subject: refactor(aucmd_win): remove need to restore window layout There are some places that mess with the window layout in preparation for moving a window to a different split (win_split_ins called with new_wp != NULL). This means the window layout can change slightly even if win_split_ins fails. This is why it was still needed to restore the window layout in aucmd_{prep,rest}buf even if we disallow win_split_ins from making aucmd_win non-floating by moving it into a split. We can just skip messing with the layout in such places if we're dealing with the aucmd_win. --- src/nvim/window.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 549dd18e4f..83048d911f 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1838,6 +1838,9 @@ static void win_totop(int size, int flags) beep_flush(); return; } + if (curwin == aucmd_win) { + return; + } if (curwin->w_floating) { ui_comp_remove_grid(&curwin->w_grid_alloc); -- cgit From 8262de0b489d5b9b5f6c99c1016b62d4e72a899b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 6 Mar 2022 07:57:31 +0800 Subject: vim-patch:8.2.3739: in wrong directory when using win_execute() with 'acd' set Problem: In wrong directory when using win_execute() with 'acd' set. Solution: Restore the directory when returning to the window. (closes vim/vim#9276) https://github.com/vim/vim/commit/dea4a616376c6500894c16e26057ce16d7ef9f0e --- src/nvim/window.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 83048d911f..c4002e93e0 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4680,6 +4680,10 @@ static void win_enter_ext(win_T *const wp, const int flags) /// Used after making another window the current one: change directory if needed. void fix_current_dir(void) { + if (p_acd) { + do_autochdir(); + return; + } // New directory is either the local directory of the window, tab or NULL. char *new_dir = (char *)(curwin->w_localdir ? curwin->w_localdir : curtab->tp_localdir); -- cgit From da9bc96152efedfa80fabf0d1aabe52b7269181e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 6 Mar 2022 08:11:52 +0800 Subject: vim-patch:8.2.3920: restoring directory after using another window is inefficient Problem: Restoring directory after using another window is inefficient. Solution: Only restore the directory for win_execute(). Apply 'autochdir' only when needed. https://github.com/vim/vim/commit/90c317f2246a7fb4bd4e3feb0778b53627bc9fad --- src/nvim/window.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index c4002e93e0..f04204fafe 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6767,9 +6767,6 @@ void restore_win_noblock(switchwin_T *switchwin, bool no_display) curwin = switchwin->sw_curwin; curbuf = curwin->w_buffer; } - // If called by win_execute() and executing the command changed the - // directory, it now has to be restored. - fix_current_dir(); } /// Make "buf" the current buffer. -- cgit From eb70540ff0385f3929b39f26faceaa2765f6949a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 6 Mar 2022 09:11:23 +0800 Subject: vim-patch:8.2.4513: window-local directory is not applied if 'acd' fails Problem: Window-local directory is not applied if 'acd' fails. Solution: Don't call do_autochdir(). (closes vim/vim#9891) https://github.com/vim/vim/commit/b29ae159777028bb3266835b55716749ab0515be --- src/nvim/window.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index f04204fafe..d5299202b0 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4680,10 +4680,6 @@ static void win_enter_ext(win_T *const wp, const int flags) /// Used after making another window the current one: change directory if needed. void fix_current_dir(void) { - if (p_acd) { - do_autochdir(); - return; - } // New directory is either the local directory of the window, tab or NULL. char *new_dir = (char *)(curwin->w_localdir ? curwin->w_localdir : curtab->tp_localdir); -- cgit From 0cf2dc63bf9e3c94e1373142a6198635efd1c514 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 14 Feb 2022 20:40:58 +0800 Subject: fix(win_split_ins): do not fail when oldwin is not valid Ref #14240 --- src/nvim/window.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index d5299202b0..faf4b117f4 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1420,13 +1420,11 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) p_wh = i; } - if (!win_valid(oldwin)) { - return FAIL; + if (win_valid(oldwin)) { + // Send the window positions to the UI + oldwin->w_pos_changed = true; } - // Send the window positions to the UI - oldwin->w_pos_changed = true; - return OK; } -- cgit From 6c26ab71ceb9f4f12c55492ba7ab33a5e61af079 Mon Sep 17 00:00:00 2001 From: VVKot Date: Sun, 19 Dec 2021 07:46:28 +0000 Subject: vim-patch:8.1.0892: failure when closing a window when location list is in use Problem: Failure when closing a window when location list is in use. Solution: Handle the situation gracefully. Make sure memory for 'switchbuf' is not freed at the wrong time. (Yegappan Lakshmanan, closes vim/vim#3928) https://github.com/vim/vim/commit/eeb1b9c7ed33c152e041a286d79bf3ed00d80e40 --- src/nvim/window.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index faf4b117f4..f80f1f1a65 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -7195,16 +7195,14 @@ void win_id2tabwin(typval_T *const argvars, typval_T *const rettv) tv_list_append_number(list, winnr); } -win_T *win_id2wp(typval_T *argvars) +win_T *win_id2wp(int id) { - return win_id2wp_tp(argvars, NULL); + return win_id2wp_tp(id, NULL); } // Return the window and tab pointer of window "id". -win_T *win_id2wp_tp(typval_T *argvars, tabpage_T **tpp) +win_T *win_id2wp_tp(int id, tabpage_T **tpp) { - int id = tv_get_number(&argvars[0]); - FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->handle == id) { if (tpp != NULL) { -- cgit From 163ec00f44c99b08a932144164b8c467ec672c3c Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 10 Oct 2020 15:42:25 -0400 Subject: vim-patch:8.1.1015: quickfix buffer shows up in list, can't get buffer number Problem: Quickfix buffer shows up in list, can't get buffer number. Solution: Make the quickfix buffer unlisted when the quickfix window is closed. get the quickfix buffer number with getqflist(). (Yegappan Lakshmanan, closes vim/vim#4113) https://github.com/vim/vim/commit/647e24ba3dbf7ff448aa471b1a659a18267ae056 --- src/nvim/window.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index f80f1f1a65..0f6aa3b2d5 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2596,6 +2596,11 @@ int win_close(win_T *win, bool free_buf, bool force) reset_synblock(win); } + // When the quickfix/location list window is closed, unlist the buffer. + if (win->w_buffer != NULL && bt_quickfix(win->w_buffer)) { + win->w_buffer->b_p_bl = false; + } + /* * Close the link to the buffer. */ -- cgit From c5e47e44aa139fa4f9e2f31fe591ddd6b5ca4909 Mon Sep 17 00:00:00 2001 From: VVKot Date: Sun, 19 Dec 2021 11:00:04 +0000 Subject: vim-patch:8.2.3759: quickfix buffer becomes hidden while still in a window Problem: Quickfix buffer becomes hidden while still in a window. Solution: Check if the closed window is the last window showing the quickfix buffer. (Yegappan Lakshmanan, closes vim/vim#9303, closes vim/vim#9300) https://github.com/vim/vim/commit/78a61068cf2c83e611d954a0fb413a09ad59dc07 --- src/nvim/window.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 0f6aa3b2d5..d659f60e66 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2596,8 +2596,10 @@ int win_close(win_T *win, bool free_buf, bool force) reset_synblock(win); } - // When the quickfix/location list window is closed, unlist the buffer. - if (win->w_buffer != NULL && bt_quickfix(win->w_buffer)) { + // 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; } -- cgit From 880d3537d06ef067021c73bc361fa47ab8347992 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Mon, 21 Feb 2022 10:55:36 +0000 Subject: vim-patch:8.2.4428: crash when switching tabpage while in the cmdline window Problem: Crash when switching tabpage while in the cmdline window. Solution: Disallow switching tabpage when in the cmdline window. https://github.com/vim/vim/commit/0f6e28f686dbb59ab3b562408ab9b2234797b9b1 Ensure cmdline window doesn't stop us from closing tabs with EXITFREE. mem_free_all -> win_free_all -> tabpage_close -> ... -> goto_tabpage_tp -> CHECK_CMDWIN can cause an infinite loop if Nvim is exited without using standard methods such as :qa! and friends (e.g: killed via a signal). This issue had caused the ASAN CI's functionaltests to timeout. Cherry-pick Test_cmdwin_tabpage from v8.2.4463. https://github.com/vim/vim/commit/38b85cb4d7216705058708bacbc25ab90cd61595 This bug was already fixed in Nvim. Note that g inside cmdwin is already tested for in tabnewentered_spec.lua anyway. E492 is thrown after E11 when using ":norm" in assert_fails for some reason (except after v8.2.1919, which isn't ported yet). As v8.2.1183 isn't ported yet, so we cannot assert E11 directly. Modify the test to check for E11 and E492 seperately; when v8.2.1183 is ported, the assertion for E492 will fail and the changes can be reverted to match upstream. Remove redundant CHECK_CMDWIN from goto_tabpage; it's handled with text_locked() and text_locked_msg() above: vim-patch:8.2.4434: duplicate check for cmdline window Problem: Duplicate check for cmdline window. Solution: Remove the second check. (Sean Dewar, closes vim/vim#9816) https://github.com/vim/vim/commit/16b51d26fe2cc3afb09afd439069220dea74581d --- src/nvim/window.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index d659f60e66..5878a6ba0b 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -73,6 +73,15 @@ typedef enum { static char *m_onlyone = N_("Already only one window"); +/// @return the current window, unless in the cmdline window and "prevwin" is +/// set, then return "prevwin". +win_T *prevwin_curwin(void) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + // In cmdwin, the alternative buffer should be used. + return is_in_cmdwin() && prevwin != NULL ? prevwin : curwin; +} + /// all CTRL-W window commands are handled here, called from normal_cmd(). /// /// @param xchar extra char from ":wincmd gx" or NUL @@ -3857,6 +3866,11 @@ int win_new_tabpage(int after, char_u *filename) tabpage_T *newtp; int n; + if (cmdwin_type != 0) { + emsg(_(e_cmdwin)); + return FAIL; + } + newtp = alloc_tabpage(); // Remember the current windows in this Tab page. @@ -4255,6 +4269,8 @@ void goto_tabpage(int n) /// @param trigger_leave_autocmds when true trigger *Leave autocommands. void goto_tabpage_tp(tabpage_T *tp, bool trigger_enter_autocmds, bool trigger_leave_autocmds) { + CHECK_CMDWIN; + // Don't repeat a message in another tab page. set_keep_msg(NULL, 0); -- cgit From 490874f3da4c39a36438b6cfa6d79e594b82806f Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Mon, 21 Feb 2022 16:19:49 +0000 Subject: vim-patch:8.2.4432: cannot use settabvar() while the cmdline window is open Problem: Cannot use settabvar() while the cmdline window is open. Solution: Only give an error when actually switching tabpage. (closes vim/vim#9813) https://github.com/vim/vim/commit/592f6250017c31c8996325403e511f4502077ba5 --- src/nvim/window.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 5878a6ba0b..3c34620db4 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4269,7 +4269,9 @@ void goto_tabpage(int n) /// @param trigger_leave_autocmds when true trigger *Leave autocommands. void goto_tabpage_tp(tabpage_T *tp, bool trigger_enter_autocmds, bool trigger_leave_autocmds) { - CHECK_CMDWIN; + if (trigger_enter_autocmds || trigger_leave_autocmds) { + CHECK_CMDWIN; + } // Don't repeat a message in another tab page. set_keep_msg(NULL, 0); -- cgit From 7e19c18a544b5f1f15cec0444385ddae80687a26 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Fri, 25 Feb 2022 00:17:17 +0000 Subject: vim-patch:8.2.4454: resetting cmdwin_type only for one situation Problem: Resetting cmdwin_type only for one situation. Solution: Reset cmdwin_type before closing windows. (closes vim/vim#9822) https://github.com/vim/vim/commit/6a8b13614e5bcb233d20403ae9f008ccba152be3 Move the check to win_free_all to match Vim. --- src/nvim/window.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 3c34620db4..f2b84a4124 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2904,6 +2904,9 @@ void win_free_all(void) { int dummy; + // avoid an error for switching tabpage with the cmdline window open + cmdwin_type = 0; + while (first_tabpage->tp_next != NULL) { tabpage_close(TRUE); } -- cgit From c5f190e0c21b4e8465502fd9f260c3d49a4102ab Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Mon, 14 Mar 2022 11:37:44 +0000 Subject: vim-patch:8.2.1401: cannot jump to the last used tabpage Problem: Cannot jump to the last used tabpage. Solution: Add g and tabpagnr('#'). (Yegappan Lakshmanan, closes vim/vim#6661, neovim #11626) https://github.com/vim/vim/commit/62a232506d06f6d1b3b7271801c907d6294dfe84 Nvim implemented this feature before Vim, but Vim made some useful changes (e.g: beeping on failure). Port the changes to closer match Vim (also makes porting future patches easier). Also note that because CHECK_CMDWIN was added to goto_tabpage_tp, there is no need to do the extra work with tabpage_index and goto_tabpage inside goto_tabpage_lastused to fix cmdwin issues any more (#11692). Note that while goto_tabpage_tp doesn't check for textlock like goto_tabpage does, it shouldn't matter as it is already checked for earlier. Add tags for to tabpage.txt, and refer to over CTRL-Tab to be consistent with other docs like the patch. Remove mention of "previous tabpage" (it can be confused with the tabpage to the left, e.g: `:tabprevious`). Similarly, don't rename old_curtab to last_tab in enter_tabpage (it might be confused with the right-most tabpage, e.g: `:tablast`). Cherry-pick Test_tabpage change from v8.2.0634. https://github.com/vim/vim/commit/92b83ccfda7a1d654ccaaf161a9c8a8e01fbcf76 --- src/nvim/window.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index f2b84a4124..a235b07b47 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -530,10 +530,6 @@ wingotofile: do_nv_ident('g', xchar); break; - case TAB: - goto_tabpage_lastused(); - break; - case 'f': // CTRL-W gf: "gf" in a new tab page case 'F': // CTRL-W gF: "gF" in a new tab page cmdmod.tab = tabpage_index(curtab) + 1; @@ -547,6 +543,12 @@ wingotofile: goto_tabpage(-(int)Prenum1); break; + case TAB: // CTRL-W g: go to last used tab page + if (!goto_tabpage_lastused()) { + beep_flush(); + } + break; + case 'e': if (curwin->w_floating || !ui_has(kUIMultigrid)) { beep_flush(); @@ -4119,8 +4121,8 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a { int old_off = tp->tp_firstwin->w_winrow; win_T *next_prevwin = tp->tp_prevwin; - tabpage_T *old_curtab = curtab; + curtab = tp; firstwin = tp->tp_firstwin; lastwin = tp->tp_lastwin; @@ -4291,13 +4293,15 @@ void goto_tabpage_tp(tabpage_T *tp, bool trigger_enter_autocmds, bool trigger_le } } -// Go to the last accessed tab page, if there is one. -void goto_tabpage_lastused(void) +/// Go to the last accessed tab page, if there is one. +/// @return true if the tab page is valid, false otherwise. +bool goto_tabpage_lastused(void) { - int index = tabpage_index(lastused_tabpage); - if (index < tabpage_index(NULL)) { - goto_tabpage(index); + if (valid_tabpage(lastused_tabpage)) { + goto_tabpage_tp(lastused_tabpage, true, true); + return true; } + return false; } /* -- cgit From 5ab122917474b3f9e88be4ee88bc6d627980cfe0 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 30 Jan 2022 11:57:41 +0600 Subject: feat: add support for global statusline Ref: #9342 Adds the option to have a single global statusline for the current window at the bottom of the screen instead of a statusline at the bottom of every window. Enabled by setting `laststatus = 3`. Due to the fact that statuslines at the bottom of windows are removed when global statusline is enabled, horizontal separators are used instead to separate horizontal splits. The horizontal separator character is configurable through the`horiz` item in `'fillchars'`. Separator connector characters are also used to connect the horizontal and vertical separators together, which are also configurable through the `horizup`, `horizdown`, `vertleft`, `vertright` and `verthoriz` items in `fillchars`. The window separators are highlighted using the `WinSeparator` highlight group, which supersedes `VertSplit` and is linked to `VertSplit` by default in order to maintain backwards compatibility. --- src/nvim/window.c | 334 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 232 insertions(+), 102 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index e09af7a7bb..8cac9f23a1 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -60,7 +60,7 @@ #define NOWIN (win_T *)-1 // non-existing window -#define ROWS_AVAIL (Rows - p_ch - tabline_height()) +#define ROWS_AVAIL (Rows - p_ch - tabline_height() - global_stl_height()) /// flags for win_enter_ext() typedef enum { @@ -647,6 +647,7 @@ win_T *win_new_float(win_T *wp, FloatConfig fconfig, Error *err) } wp->w_floating = 1; wp->w_status_height = 0; + wp->w_hsep_height = 0; wp->w_vsep_width = 0; win_config_float(wp, fconfig); @@ -956,6 +957,7 @@ 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; if (flags & WSP_TOP) { @@ -1063,6 +1065,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } } } else { + hsep_height = global_stl_height() > 0 ? 1 : STATUS_HEIGHT; layout = FR_COL; /* @@ -1071,7 +1074,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 + STATUS_HEIGHT; + needed = wmh1 + hsep_height; if (flags & WSP_ROOM) { needed += p_wh - wmh1; } @@ -1113,15 +1116,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 - STATUS_HEIGHT) { - new_size = available - minheight - STATUS_HEIGHT; + if (new_size > available - minheight - hsep_height) { + new_size = available - minheight - hsep_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 - STATUS_HEIGHT < p_wmh) { + if (oldwin_height - new_size - hsep_height < p_wmh) { do_equal = true; } @@ -1134,7 +1137,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 + STATUS_HEIGHT, + win_setheight_win(oldwin->w_height + new_size + hsep_height, oldwin); oldwin_height = oldwin->w_height; if (need_status) { @@ -1151,8 +1154,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 - - STATUS_HEIGHT)) { + || frp->fr_win->w_height > oldwin_height - new_size - hsep_height)) { do_equal = true; break; } @@ -1278,13 +1280,15 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) if (flags & (WSP_TOP | WSP_BOT)) { // set height and row of new window to full height wp->w_winrow = tabline_height(); - win_new_height(wp, curfrp->fr_height - (p_ls > 0)); - wp->w_status_height = (p_ls > 0); + win_new_height(wp, curfrp->fr_height - (p_ls == 1 || p_ls == 2)); + wp->w_status_height = (p_ls == 1 || p_ls == 2); + wp->w_hsep_height = 0; } else { // height and row of new window is same as current window wp->w_winrow = oldwin->w_winrow; win_new_height(wp, oldwin->w_height); wp->w_status_height = oldwin->w_status_height; + wp->w_hsep_height = oldwin->w_hsep_height; } frp->fr_height = curfrp->fr_height; @@ -1317,6 +1321,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) frame_fix_width(oldwin); frame_fix_width(wp); } else { + bool is_stl_global = global_stl_height() > 0; // width and column of new window is same as current window if (flags & (WSP_TOP | WSP_BOT)) { wp->w_wincol = 0; @@ -1332,28 +1337,53 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) // "new_size" of the current window goes to the new window, use // one row for the status line win_new_height(wp, new_size); + if (before) { + wp->w_hsep_height = is_stl_global ? 1 : 0; + } else { + wp->w_hsep_height = oldwin->w_hsep_height; + oldwin->w_hsep_height = is_stl_global ? 1 : 0; + } if (flags & (WSP_TOP | WSP_BOT)) { int new_fr_height = curfrp->fr_height - new_size; - if (!((flags & WSP_BOT) && p_ls == 0)) { + if (!((flags & WSP_BOT) && p_ls == 0) && global_stl_height() == 0) { new_fr_height -= STATUS_HEIGHT; + } else if (global_stl_height() > 0) { + if (flags & WSP_BOT) { + frame_add_hsep(curfrp); + } else { + new_fr_height -= 1; + } } frame_new_height(curfrp, new_fr_height, flags & WSP_TOP, false); } else { - win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT)); + win_new_height(oldwin, oldwin_height - (new_size + + (global_stl_height() > 0 ? 1 : STATUS_HEIGHT))); } + if (before) { // new window above current one wp->w_winrow = oldwin->w_winrow; - wp->w_status_height = STATUS_HEIGHT; - oldwin->w_winrow += wp->w_height + STATUS_HEIGHT; + + if (is_stl_global) { + wp->w_status_height = 0; + oldwin->w_winrow += wp->w_height + 1; + } else { + wp->w_status_height = STATUS_HEIGHT; + oldwin->w_winrow += wp->w_height + STATUS_HEIGHT; + } } else { // new window below current one - wp->w_winrow = oldwin->w_winrow + oldwin->w_height + STATUS_HEIGHT; - wp->w_status_height = oldwin->w_status_height; - if (!(flags & WSP_BOT)) { - oldwin->w_status_height = STATUS_HEIGHT; + if (is_stl_global) { + wp->w_winrow = oldwin->w_winrow + oldwin->w_height + 1; + wp->w_status_height = 0; + } else { + wp->w_winrow = oldwin->w_winrow + oldwin->w_height + STATUS_HEIGHT; + wp->w_status_height = oldwin->w_status_height; + if (!(flags & WSP_BOT)) { + oldwin->w_status_height = STATUS_HEIGHT; + } } } - if (flags & WSP_BOT) { + if ((flags & WSP_BOT) && global_stl_height() == 0) { frame_add_statusline(curfrp); } frame_fix_height(wp); @@ -1595,10 +1625,10 @@ int make_windows(int count, bool vertical) maxcount = (curwin->w_width + curwin->w_vsep_width - (p_wiw - p_wmw)) / (p_wmw + 1); } else { - // Each window needs at least 'winminheight' lines and a status line. - maxcount = (curwin->w_height - + curwin->w_status_height - - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT); + // Each window needs at least 'winminheight' lines + // If statusline isn't global, each window also needs a statusline + maxcount = (curwin->w_height + curwin->w_hsep_height + curwin->w_status_height + - (p_wh - p_wmh)) / (p_wmh + (global_stl_height() > 0 ? 1 : STATUS_HEIGHT)); } if (maxcount < 2) { @@ -1693,7 +1723,7 @@ static void win_exchange(long Prenum) * if wp != wp2 * 3. remove wp from the list * 4. insert wp after wp2 - * 5. exchange the status line height and vsep width. + * 5. exchange the status line height, hsep height and vsep width. */ wp2 = curwin->w_prev; frp2 = curwin->w_frame->fr_prev; @@ -1719,6 +1749,9 @@ static void win_exchange(long Prenum) temp = curwin->w_vsep_width; curwin->w_vsep_width = wp->w_vsep_width; wp->w_vsep_width = temp; + temp = curwin->w_hsep_height; + curwin->w_hsep_height = wp->w_hsep_height; + wp->w_hsep_height = temp; frame_fix_height(curwin); frame_fix_height(wp); @@ -1793,10 +1826,13 @@ static void win_rotate(bool upwards, int count) frame_insert(frp->fr_parent->fr_child, frp); } - // exchange status height and vsep width of old and new last window + // exchange status height, hsep height and vsep width of old and new last window n = wp2->w_status_height; wp2->w_status_height = wp1->w_status_height; wp1->w_status_height = n; + n = wp2->w_hsep_height; + wp2->w_hsep_height = wp1->w_hsep_height; + wp1->w_hsep_height = n; frame_fix_height(wp1); frame_fix_height(wp2); n = wp2->w_vsep_width; @@ -1870,11 +1906,16 @@ void win_move_after(win_T *win1, win_T *win2) // check if there is something to do if (win2->w_next != win1) { - // may need move the status line/vertical separator of the last window + // may need move the status line, horizontal or vertical separator of the last window if (win1 == lastwin) { height = win1->w_prev->w_status_height; win1->w_prev->w_status_height = win1->w_status_height; win1->w_status_height = height; + + height = win1->w_prev->w_hsep_height; + win1->w_prev->w_hsep_height = win1->w_hsep_height; + win1->w_hsep_height = height; + if (win1->w_prev->w_vsep_width == 1) { // Remove the vertical separator from the last-but-one window, // add it to the last window. Adjust the frame widths. @@ -1887,6 +1928,11 @@ void win_move_after(win_T *win1, win_T *win2) height = win1->w_status_height; win1->w_status_height = win2->w_status_height; win2->w_status_height = height; + + height = win1->w_hsep_height; + win1->w_hsep_height = win2->w_hsep_height; + win2->w_hsep_height = height; + if (win1->w_vsep_width == 1) { // Remove the vertical separator from win1, add it to the last // window, win2. Adjust the frame widths. @@ -1950,6 +1996,7 @@ 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) { @@ -2095,19 +2142,22 @@ 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 = global_stl_height() > 0 ? 1 : STATUS_HEIGHT; topfr->fr_width = width; topfr->fr_height = height; if (dir != 'h') { // equalize frame heights // Compute maximum number of windows vertically in this frame. n = frame_minheight(topfr, NOWIN); - // add one for the bottom window if it doesn't have a statusline + // add one for the bottom window if it doesn't have a statusline or separator if (row + height == cmdline_row && p_ls == 0) { + extra_sep = STATUS_HEIGHT; + } else if (global_stl_height() > 0) { extra_sep = 1; } else { extra_sep = 0; } - totwincount = (n + extra_sep) / (p_wmh + 1); + totwincount = (n + extra_sep) / (p_wmh + hsep_height); has_next_curwin = frame_has_win(topfr, next_curwin); /* @@ -2142,7 +2192,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 + 1); + ? extra_sep : 0)) / (p_wmh + hsep_height); } room -= new_size - n; if (room < 0) { @@ -2188,7 +2238,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 + 1); + / (p_wmh + hsep_height); m = frame_minheight(fr, next_curwin); if (has_next_curwin) { hnc = frame_has_win(fr, next_curwin); @@ -3134,7 +3184,7 @@ static tabpage_T *alt_tabpage(void) /* * Find the left-upper window in frame "frp". */ -static win_T *frame2win(frame_T *frp) +win_T *frame2win(frame_T *frp) { while (frp->fr_win == NULL) { frp = frp->fr_child; @@ -3161,23 +3211,40 @@ static bool frame_has_win(const frame_T *frp, const win_T *wp) return false; } +/// Check if current window is at the bottom +/// Returns true if there are no windows below current window +static bool is_bottom_win(win_T *wp) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + frame_T *frp; + for (frp = wp->w_frame; frp->fr_parent != NULL; frp = frp->fr_parent) { + if (frp->fr_parent->fr_layout == FR_COL && frp->fr_next != NULL) { + return false; + } + } + return true; +} /// Set a new height for a frame. Recursively sets the height for contained /// frames and windows. Caller must take care of positions. /// /// @param topfirst resize topmost contained frame first. /// @param wfh obey 'winfixheight' when there is a choice; /// may cause the height not to be set. -static void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh) +void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh) FUNC_ATTR_NONNULL_ALL { frame_T *frp; int extra_lines; int h; + win_T *wp; if (topfrp->fr_win != NULL) { // Simple case: just one window. - win_new_height(topfrp->fr_win, - height - topfrp->fr_win->w_status_height); + wp = topfrp->fr_win; + if (is_bottom_win(wp)) { + wp->w_hsep_height = 0; + } + win_new_height(wp, height - wp->w_hsep_height - wp->w_status_height); } else if (topfrp->fr_layout == FR_ROW) { do { // All frames in this row get the same new height. @@ -3333,8 +3400,8 @@ static void frame_add_statusline(frame_T *frp) if (frp->fr_layout == FR_LEAF) { wp = frp->fr_win; if (wp->w_status_height == 0) { - if (wp->w_height > 0) { // don't make it negative - --wp->w_height; + if (wp->w_height - STATUS_HEIGHT >= 0) { // don't make it negative + wp->w_height -= STATUS_HEIGHT; } wp->w_status_height = STATUS_HEIGHT; } @@ -3454,10 +3521,8 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw topfrp->fr_width = width; } -/* - * Add the vertical separator to windows at the right side of "frp". - * Note: Does not check if there is room! - */ +/// Add the vertical separator to windows at the right side of "frp". +/// Note: Does not check if there is room! static void frame_add_vsep(const frame_T *frp) FUNC_ATTR_NONNULL_ARG(1) { @@ -3487,6 +3552,37 @@ static void frame_add_vsep(const frame_T *frp) } } +/// Add the horizontal separator to windows at the bottom of "frp". +/// Note: Does not check if there is room or whether the windows have a statusline! +static void frame_add_hsep(const frame_T *frp) + FUNC_ATTR_NONNULL_ARG(1) +{ + win_T *wp; + + if (frp->fr_layout == FR_LEAF) { + wp = frp->fr_win; + if (wp->w_hsep_height == 0) { + if (wp->w_height > 0) { // don't make it negative + wp->w_height++; + } + wp->w_hsep_height = 1; + } + } else if (frp->fr_layout == FR_ROW) { + // Handle all the frames in the row. + FOR_ALL_FRAMES(frp, frp->fr_child) { + frame_add_hsep(frp); + } + } else { + assert(frp->fr_layout == FR_COL); + // Only need to handle the last frame in the column. + frp = frp->fr_child; + while (frp->fr_next != NULL) { + frp = frp->fr_next; + } + frame_add_hsep(frp); + } +} + /* * Set frame width from the window it contains. */ @@ -3501,7 +3597,7 @@ static void frame_fix_width(win_T *wp) static void frame_fix_height(win_T *wp) FUNC_ATTR_NONNULL_ALL { - wp->w_frame->fr_height = wp->w_height + wp->w_status_height; + wp->w_frame->fr_height = wp->w_height + wp->w_hsep_height + wp->w_status_height; } /* @@ -3519,10 +3615,11 @@ static int frame_minheight(frame_T *topfrp, win_T *next_curwin) if (topfrp->fr_win != NULL) { if (topfrp->fr_win == next_curwin) { - m = p_wh + topfrp->fr_win->w_status_height; + m = p_wh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height; } else { - // window: minimal height of the window plus status line - m = p_wmh + topfrp->fr_win->w_status_height; + // window: minimal height of the window plus separator column or status line + // depending on whether global statusline is enabled + m = p_wmh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height; if (topfrp->fr_win == curwin && next_curwin == NULL) { // Current window is minimal one line high. if (p_wmh == 0) { @@ -3751,7 +3848,7 @@ static int win_alloc_firstwin(win_T *oldwin) new_frame(curwin); topframe = curwin->w_frame; topframe->fr_width = Columns; - topframe->fr_height = Rows - p_ch; + topframe->fr_height = Rows - p_ch - global_stl_height(); return OK; } @@ -5147,11 +5244,8 @@ void win_size_restore(garray_T *gap) } } -/* - * Update the position for all windows, using the width and height of the - * frames. - * Returns the row just after the last window. - */ +// Update the position for all windows, using the width and height of the frames. +// Returns the row just after the last window and global statusline (if there is one). int win_comp_pos(void) { int row = tabline_height(); @@ -5166,7 +5260,7 @@ int win_comp_pos(void) } } - return row; + return row + global_stl_height(); } void win_reconfig_floats(void) @@ -5200,7 +5294,7 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col) wp->w_redr_status = true; wp->w_pos_changed = true; } - const int h = wp->w_height + wp->w_status_height; + const int h = wp->w_height + wp->w_hsep_height + wp->w_status_height; *row += h > topfrp->fr_height ? topfrp->fr_height : h; *col += wp->w_width + wp->w_vsep_width; } else { @@ -5249,7 +5343,7 @@ void win_setheight_win(int height, win_T *win) win_config_float(win, win->w_float_config); redraw_later(win, NOT_VALID); } else { - frame_setheight(win->w_frame, height + win->w_status_height); + frame_setheight(win->w_frame, height + win->w_hsep_height + win->w_status_height); // recompute the window positions int row = win_comp_pos(); @@ -5340,8 +5434,8 @@ static void frame_setheight(frame_T *curfrp, int height) room_cmdline = 0; } else { win_T *wp = lastwin_nofloating(); - room_cmdline = Rows - p_ch - - (wp->w_winrow + wp->w_height + wp->w_status_height); + room_cmdline = Rows - p_ch - global_stl_height() + - (wp->w_winrow + wp->w_height + wp->w_hsep_height + wp->w_status_height); if (room_cmdline < 0) { room_cmdline = 0; } @@ -5703,7 +5797,7 @@ void win_drag_status_line(win_T *dragwin, int offset) } else { // drag down up = false; // Only dragging the last status line can reduce p_ch. - room = Rows - cmdline_row; + room = Rows - cmdline_row - global_stl_height(); if (curfr->fr_next == NULL) { room -= 1; } else { @@ -6344,72 +6438,104 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u return find_file_name_in_path(ptr, len, options, count, rel_fname); } -/// Add or remove a status line for the bottom window(s), according to the +/// Add or remove a status line from window(s), according to the /// value of 'laststatus'. /// /// @param morewin pretend there are two or more windows if true. void last_status(bool morewin) { // Don't make a difference between horizontal or vertical split. - last_status_rec(topframe, (p_ls == 2 - || (p_ls == 1 && (morewin || !one_window())))); + last_status_rec(topframe, (p_ls == 2 || (p_ls == 1 && (morewin || !one_window()))), + global_stl_height() > 0); } -static void last_status_rec(frame_T *fr, bool statusline) +// 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) +{ + // 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; + } + } + 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(); + } else { + win_new_height(wp, wp->w_height - n); + } + } +} + +static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) { frame_T *fp; win_T *wp; if (fr->fr_layout == FR_LEAF) { wp = fr->fr_win; - if (wp->w_status_height != 0 && !statusline) { - // remove status line - win_new_height(wp, wp->w_height + 1); + bool is_last = is_bottom_win(wp); + + if (is_last) { + if (wp->w_status_height != 0 && (!statusline || is_stl_global)) { + // Remove status line + wp->w_status_height = 0; + win_new_height(wp, wp->w_height + STATUS_HEIGHT); + comp_col(); + } 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); + 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(); - } else if (wp->w_status_height == 0 && statusline) { - // Find a frame to take a line from. - fp = fr; - 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; - } - } - wp->w_status_height = 1; - 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); - } + } else if (wp->w_status_height == 0 && !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); } - } else if (fr->fr_layout == FR_ROW) { - // vertically split windows, set status line for each one + redraw_all_later(SOME_VALID); + } else if (fr->fr_layout == FR_COL) { + // For a column frame, recursively call this function for all child frames FOR_ALL_FRAMES(fp, fr->fr_child) { - last_status_rec(fp, statusline); + last_status_rec(fp, statusline, is_stl_global); } } else { - // horizontally split window, set status line for last one - for (fp = fr->fr_child; fp->fr_next != NULL; fp = fp->fr_next) { + // For a row frame, recursively call this function for all child frames + FOR_ALL_FRAMES(fp, fr->fr_child) { + last_status_rec(fp, statusline, is_stl_global); } - last_status_rec(fp, statusline); } } -/* - * Return the number of lines used by the tab page line. - */ +/// Return the number of lines used by the tab page line. int tabline_height(void) { if (ui_has(kUITabline)) { @@ -6425,10 +6551,14 @@ int tabline_height(void) return 1; } -/* - * Return the minimal number of rows that is needed on the screen to display - * the current number of windows. - */ +/// Return the number of lines used by the global statusline +int global_stl_height(void) +{ + return (p_ls == 3) ? STATUS_HEIGHT : 0; +} + +/// Return the minimal number of rows that is needed on the screen to display +/// the current number of windows. int min_rows(void) { if (firstwin == NULL) { // not initialized yet @@ -6442,7 +6572,7 @@ int min_rows(void) total = n; } } - total += tabline_height(); + total += tabline_height() + global_stl_height(); total += 1; // count the room for the command line return total; } -- cgit From 00effff56944d5b59440dcdb5e3496d49a76d3e2 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 18 Mar 2022 04:47:08 +0000 Subject: vim-patch:8.1.1693: syntax coloring and highlighting is in one big file (#17721) Problem: Syntax coloring and highlighting is in one big file. Solution: Move the highlighting to a separate file. (Yegappan Lakshmanan, closes vim/vim#4674) https://github.com/vim/vim/commit/f9cc9f209ede9f15959e4c2351e970477c139614 Name the new file highlight_group.c instead. Co-authored-by: zeertzjq --- src/nvim/window.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index e9c7d0d8e2..8b9f1e024d 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -25,6 +25,7 @@ #include "nvim/getchar.h" #include "nvim/globals.h" #include "nvim/hashtab.h" +#include "nvim/highlight_group.h" #include "nvim/main.h" #include "nvim/mark.h" #include "nvim/memline.h" -- cgit From 6566a4bdbd800ff1850a001a5c40f65b3dc13e46 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 18 Mar 2022 10:51:38 +0000 Subject: vim-patch:8.1.1734: the evalfunc.c file is too big Problem: The evalfunc.c file is too big. Solution: Move some functions to other files. https://github.com/vim/vim/commit/29b7d7a9aac591f920edb89241c8cde27378e50b --- src/nvim/window.c | 280 ------------------------------------------------------ 1 file changed, 280 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 8b9f1e024d..1f9cfbf4fd 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6953,286 +6953,6 @@ void restore_buffer(bufref_T *save_curbuf) } } - -/// Add match to the match list of window 'wp'. The pattern 'pat' will be -/// highlighted with the group 'grp' with priority 'prio'. -/// Optionally, a desired ID 'id' can be specified (greater than or equal to 1). -/// -/// @param[in] id a desired ID 'id' can be specified -/// (greater than or equal to 1). -1 must be specified if no -/// particular ID is desired -/// @param[in] conceal_char pointer to conceal replacement char -/// @return ID of added match, -1 on failure. -int match_add(win_T *wp, const char *const grp, const char *const pat, int prio, int id, - list_T *pos_list, const char *const conceal_char) - FUNC_ATTR_NONNULL_ARG(1, 2) -{ - matchitem_T *cur; - matchitem_T *prev; - matchitem_T *m; - int hlg_id; - regprog_T *regprog = NULL; - int rtype = SOME_VALID; - - if (*grp == NUL || (pat != NULL && *pat == NUL)) { - return -1; - } - if (id < -1 || id == 0) { - semsg(_("E799: Invalid ID: %" PRId64 - " (must be greater than or equal to 1)"), - (int64_t)id); - return -1; - } - if (id != -1) { - cur = wp->w_match_head; - while (cur != NULL) { - if (cur->id == id) { - semsg(_("E801: ID already taken: %" PRId64), (int64_t)id); - return -1; - } - cur = cur->next; - } - } - if ((hlg_id = syn_check_group(grp, strlen(grp))) == 0) { - return -1; - } - if (pat != NULL && (regprog = vim_regcomp((char_u *)pat, RE_MAGIC)) == NULL) { - semsg(_(e_invarg2), pat); - return -1; - } - - // Find available match ID. - while (id == -1) { - cur = wp->w_match_head; - while (cur != NULL && cur->id != wp->w_next_match_id) { - cur = cur->next; - } - if (cur == NULL) { - id = wp->w_next_match_id; - } - wp->w_next_match_id++; - } - - // Build new match. - m = xcalloc(1, sizeof(matchitem_T)); - m->id = id; - m->priority = prio; - m->pattern = pat == NULL ? NULL: (char_u *)xstrdup(pat); - m->hlg_id = hlg_id; - m->match.regprog = regprog; - m->match.rmm_ic = FALSE; - m->match.rmm_maxcol = 0; - m->conceal_char = 0; - if (conceal_char != NULL) { - m->conceal_char = utf_ptr2char((const char_u *)conceal_char); - } - - // Set up position matches - if (pos_list != NULL) { - linenr_T toplnum = 0; - linenr_T botlnum = 0; - - int i = 0; - TV_LIST_ITER(pos_list, li, { - linenr_T lnum = 0; - colnr_T col = 0; - int len = 1; - bool error = false; - - if (TV_LIST_ITEM_TV(li)->v_type == VAR_LIST) { - const list_T *const subl = TV_LIST_ITEM_TV(li)->vval.v_list; - const listitem_T *subli = tv_list_first(subl); - if (subli == NULL) { - semsg(_("E5030: Empty list at position %d"), - (int)tv_list_idx_of_item(pos_list, li)); - goto fail; - } - lnum = tv_get_number_chk(TV_LIST_ITEM_TV(subli), &error); - if (error) { - goto fail; - } - if (lnum <= 0) { - continue; - } - m->pos.pos[i].lnum = lnum; - subli = TV_LIST_ITEM_NEXT(subl, subli); - if (subli != NULL) { - col = tv_get_number_chk(TV_LIST_ITEM_TV(subli), &error); - if (error) { - goto fail; - } - if (col < 0) { - continue; - } - subli = TV_LIST_ITEM_NEXT(subl, subli); - if (subli != NULL) { - len = tv_get_number_chk(TV_LIST_ITEM_TV(subli), &error); - if (len < 0) { - continue; - } - if (error) { - goto fail; - } - } - } - m->pos.pos[i].col = col; - m->pos.pos[i].len = len; - } else if (TV_LIST_ITEM_TV(li)->v_type == VAR_NUMBER) { - if (TV_LIST_ITEM_TV(li)->vval.v_number <= 0) { - continue; - } - m->pos.pos[i].lnum = TV_LIST_ITEM_TV(li)->vval.v_number; - m->pos.pos[i].col = 0; - m->pos.pos[i].len = 0; - } else { - semsg(_("E5031: List or number required at position %d"), - (int)tv_list_idx_of_item(pos_list, li)); - goto fail; - } - if (toplnum == 0 || lnum < toplnum) { - toplnum = lnum; - } - if (botlnum == 0 || lnum >= botlnum) { - botlnum = lnum + 1; - } - i++; - if (i >= MAXPOSMATCH) { - break; - } - }); - - // Calculate top and bottom lines for redrawing area - if (toplnum != 0) { - if (wp->w_buffer->b_mod_set) { - if (wp->w_buffer->b_mod_top > toplnum) { - wp->w_buffer->b_mod_top = toplnum; - } - if (wp->w_buffer->b_mod_bot < botlnum) { - wp->w_buffer->b_mod_bot = botlnum; - } - } else { - wp->w_buffer->b_mod_set = true; - wp->w_buffer->b_mod_top = toplnum; - wp->w_buffer->b_mod_bot = botlnum; - wp->w_buffer->b_mod_xlines = 0; - } - m->pos.toplnum = toplnum; - m->pos.botlnum = botlnum; - rtype = VALID; - } - } - - // Insert new match. The match list is in ascending order with regard to - // the match priorities. - cur = wp->w_match_head; - prev = cur; - while (cur != NULL && prio >= cur->priority) { - prev = cur; - cur = cur->next; - } - if (cur == prev) { - wp->w_match_head = m; - } else { - prev->next = m; - } - m->next = cur; - - redraw_later(wp, rtype); - return id; - -fail: - xfree(m); - return -1; -} - - -/// Delete match with ID 'id' in the match list of window 'wp'. -/// -/// @param perr print error messages if true. -int match_delete(win_T *wp, int id, bool perr) -{ - matchitem_T *cur = wp->w_match_head; - matchitem_T *prev = cur; - int rtype = SOME_VALID; - - if (id < 1) { - if (perr) { - semsg(_("E802: Invalid ID: %" PRId64 - " (must be greater than or equal to 1)"), - (int64_t)id); - } - return -1; - } - while (cur != NULL && cur->id != id) { - prev = cur; - cur = cur->next; - } - if (cur == NULL) { - if (perr) { - semsg(_("E803: ID not found: %" PRId64), (int64_t)id); - } - return -1; - } - if (cur == prev) { - wp->w_match_head = cur->next; - } else { - prev->next = cur->next; - } - vim_regfree(cur->match.regprog); - xfree(cur->pattern); - if (cur->pos.toplnum != 0) { - if (wp->w_buffer->b_mod_set) { - if (wp->w_buffer->b_mod_top > cur->pos.toplnum) { - wp->w_buffer->b_mod_top = cur->pos.toplnum; - } - if (wp->w_buffer->b_mod_bot < cur->pos.botlnum) { - wp->w_buffer->b_mod_bot = cur->pos.botlnum; - } - } else { - wp->w_buffer->b_mod_set = true; - wp->w_buffer->b_mod_top = cur->pos.toplnum; - wp->w_buffer->b_mod_bot = cur->pos.botlnum; - wp->w_buffer->b_mod_xlines = 0; - } - rtype = VALID; - } - xfree(cur); - redraw_later(wp, rtype); - return 0; -} - -/* - * Delete all matches in the match list of window 'wp'. - */ -void clear_matches(win_T *wp) -{ - matchitem_T *m; - - while (wp->w_match_head != NULL) { - m = wp->w_match_head->next; - vim_regfree(wp->w_match_head->match.regprog); - xfree(wp->w_match_head->pattern); - xfree(wp->w_match_head); - wp->w_match_head = m; - } - redraw_later(wp, SOME_VALID); -} - -/* - * Get match from ID 'id' in window 'wp'. - * Return NULL if match not found. - */ -matchitem_T *get_match(win_T *wp, int id) -{ - matchitem_T *cur = wp->w_match_head; - - while (cur != NULL && cur->id != id) { - cur = cur->next; - } - return cur; -} - - /// Check that "topfrp" and its children are at the right height. /// /// @param topfrp top frame pointer -- cgit From e9b53f3fb56e91a0d4f15bb36d8068bcc6ea88cf Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 21 Mar 2022 00:25:03 +0100 Subject: fix(PVS/V583): the '?:' operator always returns one and the same value (#17790) --- src/nvim/window.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 1f9cfbf4fd..50a56056bf 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1082,7 +1082,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } } } else { - hsep_height = global_stl_height() > 0 ? 1 : STATUS_HEIGHT; + hsep_height = STATUS_HEIGHT; layout = FR_COL; /* @@ -1374,8 +1374,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } frame_new_height(curfrp, new_fr_height, flags & WSP_TOP, false); } else { - win_new_height(oldwin, oldwin_height - (new_size - + (global_stl_height() > 0 ? 1 : STATUS_HEIGHT))); + win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT)); } if (before) { // new window above current one @@ -1643,7 +1642,7 @@ int make_windows(int count, bool vertical) // Each window needs at least 'winminheight' lines // If statusline isn't global, each window also needs a statusline maxcount = (curwin->w_height + curwin->w_hsep_height + curwin->w_status_height - - (p_wh - p_wmh)) / (p_wmh + (global_stl_height() > 0 ? 1 : STATUS_HEIGHT)); + - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT); } if (maxcount < 2) { @@ -2166,7 +2165,7 @@ 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 = global_stl_height() > 0 ? 1 : STATUS_HEIGHT; + hsep_height = STATUS_HEIGHT; topfr->fr_width = width; topfr->fr_height = height; -- cgit From 7863e6b709976d53d69b8495f1ab4417d965f4b3 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 22 Mar 2022 22:31:50 +0000 Subject: vim-patch:8.2.1078: highlight and match functionality together in one file (#17805) Problem: Highlight and match functionality together in one file. Solution: Move match functionality to a separate file. (Yegappan Lakshmanan, closes vim/vim#6352) https://github.com/vim/vim/commit/06cf97e714fd8bf9b35ff5f8a6f2302c79acdd03 --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 50a56056bf..e0d657af45 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -25,9 +25,9 @@ #include "nvim/getchar.h" #include "nvim/globals.h" #include "nvim/hashtab.h" -#include "nvim/highlight_group.h" #include "nvim/main.h" #include "nvim/mark.h" +#include "nvim/match.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" -- cgit From 89712dcbf8ecc41d6fab9608f684ce199667ed2e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 21 Mar 2022 21:19:09 +0800 Subject: fix(aucmd_win): always make aucmd_win the last window --- src/nvim/window.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index e0d657af45..97664d0870 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -560,7 +560,7 @@ wingotofile: config.height = curwin->w_height; config.external = true; Error err = ERROR_INIT; - if (!win_new_float(curwin, config, &err)) { + if (!win_new_float(curwin, false, config, &err)) { emsg(err.msg); api_clear_error(&err); beep_flush(); @@ -629,16 +629,18 @@ void win_set_buf(Window window, Buffer buffer, bool noautocmd, Error *err) /// Create a new float. /// -/// if wp == NULL allocate a new window, otherwise turn existing window into a -/// float. It must then already belong to the current tabpage! -/// -/// config must already have been validated! -win_T *win_new_float(win_T *wp, FloatConfig fconfig, Error *err) +/// @param wp if NULL, allocate a new window, otherwise turn existing window into a float. +/// It must then already belong to the current tabpage! +/// @param last make the window the last one in the window list. +/// Only used when allocating the autocommand window. +/// @param config must already have been validated! +win_T *win_new_float(win_T *wp, bool last, FloatConfig fconfig, Error *err) { if (wp == NULL) { - wp = win_alloc(lastwin_nofloating(), false); + wp = win_alloc(last ? lastwin : lastwin_nofloating(), false); win_init(wp, curwin, 0); } else { + assert(!last); assert(!wp->w_floating); if (firstwin == wp && lastwin_nofloating() == wp) { // last non-float @@ -2543,7 +2545,7 @@ int win_close(win_T *win, bool free_buf, bool force) emsg(_(e_autocmd_close)); return FAIL; } - if ((firstwin == aucmd_win || lastwin == aucmd_win) && one_window()) { + if (lastwin == aucmd_win && one_window()) { emsg(_("E814: Cannot close window, only autocmd window would remain")); return FAIL; } @@ -3844,7 +3846,7 @@ void win_alloc_aucmd_win(void) fconfig.width = Columns; fconfig.height = 5; fconfig.focusable = false; - aucmd_win = win_new_float(NULL, fconfig, &err); + aucmd_win = win_new_float(NULL, true, fconfig, &err); aucmd_win->w_buffer->b_nwindows--; RESET_BINDING(aucmd_win); } -- cgit From 3539456f4923b4afbc7fa160aabf19c07108758f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 21 Mar 2022 21:54:44 +0800 Subject: fix(win_close): count the window the be closed instead of curwin --- src/nvim/window.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 97664d0870..73c4acf45b 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -300,7 +300,7 @@ newwindow: // move window to new tab page case 'T': - if (one_window()) { + if (one_window(curwin)) { msg(_(m_onlyone)); } else { tabpage_T *oldtab = curtab; @@ -2401,23 +2401,24 @@ void close_windows(buf_T *buf, int keep_curwin) } } -/// Check that current window is the last one. +/// Check that the specified window is the last one. +/// @param win counted even if floating /// -/// @return true if the current window is the only window that exists, false if -/// there is another, possibly in another tab page. -static bool last_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +/// @return true if the specified window is the only window that exists, +/// false if there is another, possibly in another tab page. +static bool last_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - return one_window() && first_tabpage->tp_next == NULL; + return one_window(win) && first_tabpage->tp_next == NULL; } -/// Check that current tab page contains no more then one window other than -/// "aucmd_win". Only counts floating window if it is current. -bool one_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +/// Check that current tab page contains no more then one window other than `aucmd_win`. +/// @param counted_float counted even if floating, but not if it is `aucmd_win` +bool one_window(win_T *counted_float) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { bool seen_one = false; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (wp != aucmd_win && (!wp->w_floating || wp == curwin)) { + if (wp != aucmd_win && (!wp->w_floating || wp == counted_float)) { if (seen_one) { return false; } @@ -2532,7 +2533,7 @@ int win_close(win_T *win, bool free_buf, bool force) frame_T *win_frame = win->w_floating ? NULL : win->w_frame->fr_parent; const bool had_diffmode = win->w_p_diff; - if (last_window() && !win->w_floating) { + if (last_window(win)) { emsg(_("E444: Cannot close last window")); return FAIL; } @@ -2545,7 +2546,7 @@ int win_close(win_T *win, bool free_buf, bool force) emsg(_(e_autocmd_close)); return FAIL; } - if (lastwin == aucmd_win && one_window()) { + if (lastwin == aucmd_win && one_window(win)) { emsg(_("E814: Cannot close window, only autocmd window would remain")); return FAIL; } @@ -2607,7 +2608,7 @@ int win_close(win_T *win, bool free_buf, bool force) return FAIL; } win->w_closing = false; - if (last_window()) { + if (last_window(win)) { return FAIL; } } @@ -2617,7 +2618,7 @@ int win_close(win_T *win, bool free_buf, bool force) return FAIL; } win->w_closing = false; - if (last_window()) { + if (last_window(win)) { return FAIL; } // autocmds may abort script processing @@ -2686,7 +2687,7 @@ int win_close(win_T *win, bool free_buf, bool force) } if (only_one_window() && win_valid(win) && win->w_buffer == NULL - && (last_window() || curtab != prev_curtab + && (last_window(win) || curtab != prev_curtab || close_last_window_tabpage(win, free_buf, prev_curtab)) && !win->w_floating) { // Autocommands have closed all windows, quit now. Restore @@ -2706,7 +2707,7 @@ int win_close(win_T *win, bool free_buf, bool force) // Autocommands may have closed the window already, or closed the only // other window or moved to another tab page. - if (!win_valid(win) || (!win->w_floating && last_window()) + if (!win_valid(win) || (!win->w_floating && last_window(win)) || close_last_window_tabpage(win, free_buf, prev_curtab)) { return FAIL; } @@ -3745,7 +3746,7 @@ void close_others(int message, int forceit) return; } - if (one_window() && !lastwin->w_floating) { + if (one_nonfloat() && !lastwin->w_floating) { if (message && !autocmd_busy) { msg(_(m_onlyone)); @@ -6500,7 +6501,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u void last_status(bool morewin) { // Don't make a difference between horizontal or vertical split. - last_status_rec(topframe, (p_ls == 2 || (p_ls == 1 && (morewin || !one_window()))), + last_status_rec(topframe, (p_ls == 2 || (p_ls == 1 && (morewin || !one_window(curwin)))), global_stl_height() > 0); } -- cgit From 3fdb7b528d9d066ccce8b1cb5d2225c338acfbb8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 21 Mar 2022 23:38:48 +0800 Subject: fix(float): handle buffer deletion with floating windows --- src/nvim/window.c | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 73c4acf45b..7df22c16d3 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2350,17 +2350,21 @@ void entering_window(win_T *const win) } } -/// Closes all windows for buffer `buf`. +/// Closes all windows for buffer `buf` until there is only one non-floating window. /// -/// @param keep_curwin don't close `curwin` -void close_windows(buf_T *buf, int keep_curwin) +/// @param keep_curwin don't close `curwin`, but caller must ensure `curwin` is non-floating. +void close_windows(buf_T *buf, bool keep_curwin) { tabpage_T *tp, *nexttp; int h = tabline_height(); ++RedrawingDisabled; - for (win_T *wp = firstwin; wp != NULL && !ONE_WINDOW;) { + assert(!keep_curwin || !curwin->w_floating); + + // Start from lastwin to close floating windows with the same buffer first. + // When the autocommand window is involved win_close() may need to print an error message. + for (win_T *wp = lastwin; wp != NULL && (lastwin == aucmd_win || !one_window(wp));) { if (wp->w_buffer == buf && (!keep_curwin || wp != curwin) && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { if (win_close(wp, false, false) == FAIL) { @@ -2369,9 +2373,9 @@ void close_windows(buf_T *buf, int keep_curwin) } // Start all over, autocommands may change the window layout. - wp = firstwin; + wp = lastwin; } else { - wp = wp->w_next; + wp = wp->w_prev; } } @@ -2406,7 +2410,7 @@ void close_windows(buf_T *buf, int keep_curwin) /// /// @return true if the specified window is the only window that exists, /// false if there is another, possibly in another tab page. -static bool last_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +bool last_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { return one_window(win) && first_tabpage->tp_next == NULL; } @@ -2442,12 +2446,14 @@ bool last_nonfloat(win_T *wp) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT return wp != NULL && firstwin == wp && !(wp->w_next && !wp->w_floating); } -/// Check if floating windows can be closed. +/// Check if floating windows in the current tab can be closed. +/// Do not call this when the autocommand window is in use! /// /// @return true if all floating windows can be closed -static bool can_close_floating_windows(tabpage_T *tab) +static bool can_close_floating_windows(void) { - FOR_ALL_WINDOWS_IN_TAB(wp, tab) { + assert(lastwin != aucmd_win); + for (win_T *wp = lastwin; wp->w_floating; wp = wp->w_prev) { buf_T *buf = wp->w_buffer; int need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1); @@ -2546,18 +2552,18 @@ int win_close(win_T *win, bool free_buf, bool force) emsg(_(e_autocmd_close)); return FAIL; } - if (lastwin == aucmd_win && one_window(win)) { - emsg(_("E814: Cannot close window, only autocmd window would remain")); - return FAIL; - } - if ((firstwin == win && lastwin_nofloating() == win) - && lastwin->w_floating) { - if (force || can_close_floating_windows(curtab)) { - win_T *nextwp; - for (win_T *wpp = firstwin; wpp != NULL; wpp = nextwp) { - nextwp = wpp->w_next; - if (wpp->w_floating) { - win_close(wpp, free_buf, force); + if (lastwin->w_floating && one_window(win)) { + if (lastwin == aucmd_win) { + emsg(_("E814: Cannot close window, only autocmd window would remain")); + return FAIL; + } + if (force || can_close_floating_windows()) { + // close the last window until the there are no floating windows + while (lastwin->w_floating) { + // `force` flag isn't actually used when closing a floating window. + if (win_close(lastwin, free_buf, true) == FAIL) { + // If closing the window fails give up, to avoid looping forever. + return FAIL; } } } else { -- cgit From a9359dca3794754ac3d4caff1bb86fe5d4dad547 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 22 Mar 2022 07:05:06 +0800 Subject: fix(float): make laststatus=1 behave consistently with floating windows --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 7df22c16d3..bcc7a92b33 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6507,7 +6507,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u void last_status(bool morewin) { // Don't make a difference between horizontal or vertical split. - last_status_rec(topframe, (p_ls == 2 || (p_ls == 1 && (morewin || !one_window(curwin)))), + last_status_rec(topframe, (p_ls == 2 || (p_ls == 1 && (morewin || !one_nonfloat()))), global_stl_height() > 0); } -- cgit From ff82b2785f161fc14ff6bd8eae497f37ecd14564 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 24 Mar 2022 11:56:22 +0800 Subject: fix(float): don't always switch window when deleting last listed buffer (#17836) --- src/nvim/window.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index bcc7a92b33..fb7878c2f4 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2350,9 +2350,9 @@ void entering_window(win_T *const win) } } -/// Closes all windows for buffer `buf` until there is only one non-floating window. +/// Closes all windows for buffer `buf` unless there is only one non-floating window. /// -/// @param keep_curwin don't close `curwin`, but caller must ensure `curwin` is non-floating. +/// @param keep_curwin don't close `curwin` void close_windows(buf_T *buf, bool keep_curwin) { tabpage_T *tp, *nexttp; @@ -2360,8 +2360,6 @@ void close_windows(buf_T *buf, bool keep_curwin) ++RedrawingDisabled; - assert(!keep_curwin || !curwin->w_floating); - // Start from lastwin to close floating windows with the same buffer first. // When the autocommand window is involved win_close() may need to print an error message. for (win_T *wp = lastwin; wp != NULL && (lastwin == aucmd_win || !one_window(wp));) { -- cgit From fcd57980f91ca01227b46de1659e6228115e1278 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 24 Mar 2022 11:14:04 +0000 Subject: chore: add additional compiler flags (#17815) Added: - -Wdouble-promotion - -Wmissing-noreturn - -Wmissing-format-attribute - -Wsuggest-attribute={pure,const,malloc,cold} Resolves: #343 --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index fb7878c2f4..fa71a08b94 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -836,7 +836,7 @@ void ui_ext_win_position(win_T *wp) FloatConfig c = wp->w_float_config; if (!c.external) { ScreenGrid *grid = &default_grid; - float row = c.row, col = c.col; + Float row = c.row, col = c.col; if (c.relative == kFloatRelativeWindow) { Error dummy = ERROR_INIT; win_T *win = find_window_by_handle(c.window, &dummy); -- cgit From f4f18a983305d3cf8a6028333e9b99e86283032b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 27 Mar 2022 08:57:57 +0800 Subject: vim-patch:8.2.4631: crash when switching window in BufWipeout autocommand Problem: Crash when switching window in BufWipeout autocommand. Solution: Put any buffer in the window to avoid it being NULL. (closes vim/vim#10024) https://github.com/vim/vim/commit/347538fad0c503249ebdedd5884c2081257c9f61 win_init_empty() cannot be made static because it is used in autocmd.c --- src/nvim/window.c | 58 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index fa71a08b94..02b297bcef 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2350,6 +2350,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 +2891,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 +3824,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(). -- cgit From 05edab85d7edad63c3b449689b57f9f658782c11 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 27 Mar 2022 21:33:54 +0600 Subject: refactor: assume `STATUS_HEIGHT` to be 1 (#17804) Since https://github.com/neovim/neovim/pull/17790 being merged means we can assume the value of `STATUS_HEIGHT` to always be 1, this commit removes code that's unnecessary if `STATUS_HEIGHT` is 1. --- src/nvim/window.c | 68 ++++++++++++++++++++++--------------------------------- 1 file changed, 27 insertions(+), 41 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 02b297bcef..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); @@ -6514,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) @@ -6566,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(); @@ -6582,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); -- cgit From 0d4bd420c19e3a81b494ec1f58cffde53d9b84ea Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 31 Mar 2022 08:40:17 +0800 Subject: fix: correct vertical dragging room calculation with global statusline (#17928) This fixes the bug that win_move_statusline() or mouse dragging cannot reduce 'cmdheight' to 1 when global statusline is used. --- src/nvim/window.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 6bd2ef3ef6..632e9b3f44 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5857,11 +5857,11 @@ void win_drag_status_line(win_T *dragwin, int offset) } else { // drag down up = false; // Only dragging the last status line can reduce p_ch. - room = Rows - cmdline_row - global_stl_height(); + room = Rows - cmdline_row; if (curfr->fr_next == NULL) { room -= 1; } else { - room -= p_ch; + room -= p_ch + global_stl_height(); } if (room < 0) { room = 0; -- cgit From 69e11b58b4db0952f11a5ff85aa7150b5f5b8db8 Mon Sep 17 00:00:00 2001 From: Brian Leung Date: Sun, 3 Apr 2022 02:36:01 -0700 Subject: vim-patch:8.2.4402: missing parenthesis may cause unexpected problems Problem: Missing parenthesis may cause unexpected problems. Solution: Add more parenthesis is macros. https://github.com/vim/vim/commit/ae6f1d8b14c2f63811ee83ef14e32086fb3e9b83 --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 632e9b3f44..9ac51bb108 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -59,7 +59,7 @@ #endif -#define NOWIN (win_T *)-1 // non-existing window +#define NOWIN ((win_T *)-1) // non-existing window #define ROWS_AVAIL (Rows - p_ch - tabline_height() - global_stl_height()) -- cgit From 463174b5d76d9a88fab02db144aaaac7fa19efd1 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Tue, 8 Feb 2022 20:28:52 +0600 Subject: fix(ui): make window resize commands manage cmdheight Previously, the window resize commands did not resize the value of `cmdheight` when they caused a change in the topframe height, leaving a gap between the end of topframe and the start of the command line, this commit fixes that by making window resize commands automatically change the value of cmdheight if the resize affects the height of topframe. --- src/nvim/window.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 9ac51bb108..cc21bf25b0 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5412,11 +5412,17 @@ void win_setheight_win(int height, win_T *win) // line, clear it. if (full_screen && msg_scrolled == 0 && row < cmdline_row) { grid_fill(&default_grid, row, cmdline_row, 0, Columns, ' ', ' ', 0); + if (msg_grid.chars) { + clear_cmdline = true; + } } cmdline_row = row; + p_ch = MAX(Rows - cmdline_row, 1); + curtab->tp_ch_used = p_ch; msg_row = row; msg_col = 0; redraw_all_later(NOT_VALID); + showmode(); } } @@ -5452,7 +5458,9 @@ static void frame_setheight(frame_T *curfrp, int height) if (curfrp->fr_parent == NULL) { // topframe: can only change the command line if (height > ROWS_AVAIL) { - height = ROWS_AVAIL; + // If height is greater than the available space, try to create space for the frame by + // reducing 'cmdheight' if possible, while making sure `cmdheight` doesn't go below 1. + height = MIN(ROWS_AVAIL + (p_ch - 1), height); } if (height > 0) { frame_new_height(curfrp, height, false, false); -- cgit From 8f3245dbfa91d384215c78da32e4d1739c8a1f34 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 7 Apr 2022 21:58:35 +0800 Subject: refactor(window): cherry-pick win_close_buffer() from Vim patch 8.1.1391 --- src/nvim/window.c | 66 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 30 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index cc21bf25b0..e471c0b304 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); + 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 -- cgit From 44b59d1a696b35d2520dbea2de3aab01e740a7ca Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 7 Apr 2022 21:46:07 +0800 Subject: vim-patch:8.2.0004: get E685 and E931 if buffer reload is interrupted Problem: Get E685 and E931 if buffer reload is interrupted. Solution: Do not abort deleting a dummy buffer. (closes vim/vim#5361) https://github.com/vim/vim/commit/a6e8f888e7fc31b8ab7233509254fb2e2fe4089f --- src/nvim/window.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index e471c0b304..20f2447bbe 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2563,7 +2563,7 @@ static void win_close_buffer(win_T *win, bool free_buf, bool abort_if_last) 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); + close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, abort_if_last, false); if (win_valid_any_tab(win)) { win->w_closing = false; } @@ -2885,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, false); } // Careful: Autocommands may have closed the tab page or made it the -- cgit From b7bc931f631febeeffee528cc3b5667cfbf60a90 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 8 Apr 2022 07:57:50 +0800 Subject: vim-patch:8.2.4700: buffer remains active if WinClosed event throws an exception Problem: Buffer remains active if a WinClosed event throws an exception. Solution: Ignore aborting() when closing the buffer. (closes vim/vim#10097) https://github.com/vim/vim/commit/c947b9ae419114ebfef9725814ea41a466fcf879 --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 20f2447bbe..21350f1a38 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2563,7 +2563,7 @@ static void win_close_buffer(win_T *win, bool free_buf, bool abort_if_last) 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, false); + 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; } -- cgit From 191f009ab74111bab6e60ffc1dac5484196b7a6b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 8 Apr 2022 07:58:34 +0800 Subject: vim-patch:8.2.4706: buffer remains active with WinClosed and tabpages Problem: Buffer remains active if a WinClosed event throws an exception when there are multiple tabpages. Solution: Ignore aborting() when closing the buffer. (closes vim/vim#10101) https://github.com/vim/vim/commit/6a06940f8ae7283999c83ccdf268540220573105 --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 21350f1a38..9aa2f947cb 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2885,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, 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 -- cgit From 53668a5815099f432a5ecebad1d2982ae6813fe6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 11 Apr 2022 16:24:15 +0800 Subject: vim-patch:8.2.4713: plugins cannot track text scrolling Problem: Plugins cannot track text scrolling. Solution: Add the WinScrolled event. (closes vim/vim#10102) https://github.com/vim/vim/commit/0937182d49fa8db50cec42785f22f1031760a0bd Skip User event in autocmd.txt, not needed unless #10689 is reverted. --- src/nvim/window.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 9aa2f947cb..08cdfa4ebe 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2851,7 +2851,7 @@ static void do_autocmd_winclosed(win_T *win) } recursive = true; char_u winid[NUMBUFLEN]; - vim_snprintf((char *)winid, sizeof(winid), "%i", win->handle); + vim_snprintf((char *)winid, sizeof(winid), "%d", win->handle); apply_autocmds(EVENT_WINCLOSED, winid, winid, false, win->w_buffer); recursive = false; } @@ -5246,25 +5246,31 @@ void shell_new_columns(void) win_reconfig_floats(); // The size of floats might change } -/// Check if "wp" has scrolled since last time it was checked -/// @param wp the window to check -bool win_did_scroll(win_T *wp) +/// Trigger WinScrolled autocmd if window has scrolled. +void may_trigger_winscrolled(win_T *wp) { - return (curwin->w_last_topline != curwin->w_topline - || curwin->w_last_leftcol != curwin->w_leftcol - || curwin->w_last_width != curwin->w_width - || curwin->w_last_height != curwin->w_height); -} + static bool recursive = false; -/// Trigger WinScrolled autocmd -void do_autocmd_winscrolled(win_T *wp) -{ - apply_autocmds(EVENT_WINSCROLLED, NULL, NULL, false, curbuf); + if (recursive || !has_event(EVENT_WINSCROLLED)) { + return; + } + + if (wp->w_last_topline != wp->w_topline + || wp->w_last_leftcol != wp->w_leftcol + || wp->w_last_width != wp->w_width + || wp->w_last_height != wp->w_height) { + char_u winid[NUMBUFLEN]; + vim_snprintf((char *)winid, sizeof(winid), "%d", wp->handle); - wp->w_last_topline = wp->w_topline; - wp->w_last_leftcol = wp->w_leftcol; - wp->w_last_width = wp->w_width; - wp->w_last_height = wp->w_height; + recursive = true; + apply_autocmds(EVENT_WINSCROLLED, winid, winid, false, wp->w_buffer); + recursive = false; + + wp->w_last_topline = wp->w_topline; + wp->w_last_leftcol = wp->w_leftcol; + wp->w_last_width = wp->w_width; + wp->w_last_height = wp->w_height; + } } /* -- cgit From 7e1e906738ae8cf2d38ded4be3bef50d72b7c2a7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 12 Apr 2022 19:16:47 +0800 Subject: vim-patch:8.2.4739: accessing freed memory after WinScrolled autocmd event (#18090) Problem: Accessing freed memory after WinScrolled autocmd event. Solution: Check the window pointer is still valid. (closes vim/vim#10156) Remove the argument from may_trigger_winscrolled(). https://github.com/vim/vim/commit/d58862d18f091d3c14fa3647e724ef7eea1ecefa --- src/nvim/window.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 08cdfa4ebe..2ca5128445 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5246,8 +5246,8 @@ void shell_new_columns(void) win_reconfig_floats(); // The size of floats might change } -/// Trigger WinScrolled autocmd if window has scrolled. -void may_trigger_winscrolled(win_T *wp) +/// Trigger WinScrolled for "curwin" if needed. +void may_trigger_winscrolled(void) { static bool recursive = false; @@ -5255,6 +5255,7 @@ void may_trigger_winscrolled(win_T *wp) return; } + win_T *wp = curwin; if (wp->w_last_topline != wp->w_topline || wp->w_last_leftcol != wp->w_leftcol || wp->w_last_width != wp->w_width @@ -5266,10 +5267,13 @@ void may_trigger_winscrolled(win_T *wp) apply_autocmds(EVENT_WINSCROLLED, winid, winid, false, wp->w_buffer); recursive = false; - wp->w_last_topline = wp->w_topline; - wp->w_last_leftcol = wp->w_leftcol; - wp->w_last_width = wp->w_width; - wp->w_last_height = wp->w_height; + // an autocmd may close the window, "wp" may be invalid now + if (win_valid_any_tab(wp)) { + wp->w_last_topline = wp->w_topline; + wp->w_last_leftcol = wp->w_leftcol; + wp->w_last_width = wp->w_width; + wp->w_last_height = wp->w_height; + } } } -- cgit From 9b10b4cc6463d901b893ad2d522c629d066607d5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 20 Apr 2022 10:26:33 +0800 Subject: vim-patch:8.1.1756: autocommand that splits window messes up window layout Problem: Autocommand that splits window messes up window layout. Solution: Disallow splitting a window while closing one. In ":all" give an error when moving a window will not work. https://github.com/vim/vim/commit/1417c766f55e5959b31da488417b7d9b141404af Expected error number was changed to E242 in Vim in patch 8.2.1183, and patch 8.2.2420 (which has already been ported) made the test no longer throw E249 in Vim, so just use E242 in the test. --- src/nvim/window.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 2ca5128445..d1cc5f245a 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -74,6 +74,35 @@ typedef enum { static char *m_onlyone = N_("Already only one window"); +/// When non-zero splitting a window is forbidden. Used to avoid that nasty +/// autocommands mess up the window structure. +static int split_disallowed = 0; + +// #define WIN_DEBUG +#ifdef WIN_DEBUG +/// Call this method to log the current window layout. +static void log_frame_layout(frame_T *frame) +{ + DLOG("layout %s, wi: %d, he: %d, wwi: %d, whe: %d, id: %d", + frame->fr_layout == FR_LEAF ? "LEAF" : frame->fr_layout == FR_ROW ? "ROW" : "COL", + frame->fr_width, + frame->fr_height, + frame->fr_win == NULL ? -1 : frame->fr_win->w_width, + frame->fr_win == NULL ? -1 : frame->fr_win->w_height, + frame->fr_win == NULL ? -1 : frame->fr_win->w_id); + if (frame->fr_child != NULL) { + DLOG("children"); + log_frame_layout(frame->fr_child); + if (frame->fr_next != NULL) { + DLOG("END of children"); + } + } + if (frame->fr_next != NULL) { + log_frame_layout(frame->fr_next); + } +} +#endif + /// @return the current window, unless in the cmdline window and "prevwin" is /// set, then return "prevwin". win_T *prevwin_curwin(void) @@ -909,6 +938,17 @@ void ui_ext_win_viewport(win_T *wp) } } +/// If "split_disallowed" is set given an error and return FAIL. +/// Otherwise return OK. +static int check_split_disallowed(void) +{ + if (split_disallowed > 0) { + emsg(_("E242: Can't split a window while closing another")); + return FAIL; + } + return OK; +} + /* * split the current window, implements CTRL-W s and :split * @@ -937,6 +977,9 @@ int win_split(int size, int flags) emsg(_("E442: Can't split topleft and botright at the same time")); return FAIL; } + if (check_split_disallowed() == FAIL) { + return FAIL; + } // When creating the help window make a snapshot of the window layout. // Otherwise clear the snapshot, it's now invalid. @@ -1886,6 +1929,9 @@ static void win_totop(int size, int flags) if (curwin == aucmd_win) { return; } + if (check_split_disallowed() == FAIL) { + return; + } if (curwin->w_floating) { ui_comp_remove_grid(&curwin->w_grid_alloc); @@ -1929,6 +1975,11 @@ void win_move_after(win_T *win1, win_T *win2) // check if there is something to do if (win2->w_next != win1) { + if (win1->w_frame->fr_parent != win2->w_frame->fr_parent) { + iemsg("INTERNAL: trying to move a window into another frame"); + return; + } + // may need move the status line, horizontal or vertical separator of the last window if (win1 == lastwin) { height = win1->w_prev->w_status_height; @@ -2742,6 +2793,10 @@ int win_close(win_T *win, bool free_buf, bool force) return FAIL; } + // Now we are really going to close the window. Disallow any autocommand + // to split a window to avoid trouble. + split_disallowed++; + // let terminal buffers know that this window dimensions may be ignored win->w_closing = true; @@ -2809,6 +2864,8 @@ int win_close(win_T *win, bool free_buf, bool force) } } + split_disallowed--; + /* * If last window has a status line now and we don't want one, * remove the status line. -- cgit From 1664e3d4bcc122e6a3b064a3fe20fdc163f6ae9d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 20 Apr 2022 10:05:02 +0800 Subject: vim-patch:8.2.2476: using freed memory when splitting window while closing buffer Problem: Using freed memory when using an autocommand to split a window while a buffer is being closed. Solution: Disallow splitting when the buffer has b_locked_split set. https://github.com/vim/vim/commit/983d83ff1cd796ff321074335fa53fbe7ac45a46 Put the error message in window.c. Cherry-pick a memory leak fix from Vim patch 8.2.0399. Test still fails. --- src/nvim/window.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index d1cc5f245a..f68cfe4c9c 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -72,6 +72,9 @@ typedef enum { WEE_TRIGGER_LEAVE_AUTOCMDS = 0x10, } wee_flags_T; +static char e_cannot_split_window_when_closing_buffer[] + = N_("E1159: Cannot split a window when closing the buffer"); + static char *m_onlyone = N_("Already only one window"); /// When non-zero splitting a window is forbidden. Used to avoid that nasty @@ -946,6 +949,10 @@ static int check_split_disallowed(void) emsg(_("E242: Can't split a window while closing another")); return FAIL; } + if (curwin->w_buffer->b_locked_split) { + emsg(_(e_cannot_split_window_when_closing_buffer)); + return FAIL; + } return OK; } @@ -966,6 +973,10 @@ static int check_split_disallowed(void) */ int win_split(int size, int flags) { + if (check_split_disallowed() == FAIL) { + return FAIL; + } + // When the ":tab" modifier was used open a new tab page instead. if (may_open_tabpage() == OK) { return OK; @@ -977,9 +988,6 @@ int win_split(int size, int flags) emsg(_("E442: Can't split topleft and botright at the same time")); return FAIL; } - if (check_split_disallowed() == FAIL) { - return FAIL; - } // When creating the help window make a snapshot of the window layout. // Otherwise clear the snapshot, it's now invalid. -- cgit From f6afc7c3246db6e5bd8feab717b3c0dbf0226803 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 27 Apr 2022 09:03:09 +0800 Subject: revert: "refactor: Remove allow_keys global (#6346)" --- src/nvim/window.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index f68cfe4c9c..50921c8302 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -534,11 +534,13 @@ wingotofile: case Ctrl_G: CHECK_CMDWIN; no_mapping++; + allow_keys++; // no mapping for xchar, but allow key codes if (xchar == NUL) { xchar = plain_vgetc(); } LANGMAP_ADJUST(xchar, true); no_mapping--; + allow_keys--; (void)add_to_showcmd(xchar); switch (xchar) { case '}': -- cgit From eef8de4df0247157e57f306062b1b86e01a41454 Mon Sep 17 00:00:00 2001 From: Dundar Goc Date: Fri, 29 Apr 2022 13:53:42 +0200 Subject: refactor(uncrustify): change rules to better align with the style guide Add space around arithmetic operators '+' and '-'. Remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. Remove space between '((' or '))' of control statements. Add space between ')' and '{' of control statements. Remove space between function name and '(' on function declaration. Collapse empty blocks between '{' and '}'. Remove newline at the end of the file. Remove newline between 'enum' and '{'. Remove newline between '}' and ')' in a function invocation. Remove newline between '}' and 'while' of 'do' statement. --- src/nvim/window.c | 47 ++++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 50921c8302..7d96532b8e 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -429,7 +429,7 @@ newwindow: // set current window height case Ctrl__: case '_': - win_setheight(Prenum ? (int)Prenum : Rows-1); + win_setheight(Prenum ? (int)Prenum : Rows - 1); break; // increase current window width @@ -881,11 +881,11 @@ void ui_ext_win_position(win_T *wp) row += row_off; col += col_off; if (c.bufpos.lnum >= 0) { - pos_T pos = { c.bufpos.lnum+1, c.bufpos.col, 0 }; + pos_T pos = { c.bufpos.lnum + 1, c.bufpos.col, 0 }; int trow, tcol, tcolc, tcole; textpos2screenpos(win, &pos, &trow, &tcol, &tcolc, &tcole, true); - row += trow-1; - col += tcol-1; + row += trow - 1; + col += tcol - 1; } } api_clear_error(&dummy); @@ -931,13 +931,13 @@ void ui_ext_win_viewport(win_T *wp) if ((wp == curwin || ui_has(kUIMultigrid)) && wp->w_viewport_invalid) { int botline = wp->w_botline; int line_count = wp->w_buffer->b_ml.ml_line_count; - if (botline == line_count+1 && wp->w_empty_rows == 0) { + if (botline == line_count + 1 && wp->w_empty_rows == 0) { // TODO(bfredl): The might be more cases to consider, like how does this // interact with incomplete final line? Diff filler lines? botline = wp->w_buffer->b_ml.ml_line_count; } - ui_call_win_viewport(wp->w_grid_alloc.handle, wp->handle, wp->w_topline-1, - botline, wp->w_cursor.lnum-1, wp->w_cursor.col, + ui_call_win_viewport(wp->w_grid_alloc.handle, wp->handle, wp->w_topline - 1, + botline, wp->w_cursor.lnum - 1, wp->w_cursor.col, line_count); wp->w_viewport_invalid = false; } @@ -1877,8 +1877,7 @@ static void win_rotate(bool upwards, int count) assert(frp->fr_parent->fr_child); // find last frame and append removed window/frame after it - for (; frp->fr_next != NULL; frp = frp->fr_next) { - } + for (; frp->fr_next != NULL; frp = frp->fr_next) {} win_append(frp->fr_win, wp1); frame_append(frp, wp1->w_frame); @@ -1886,8 +1885,7 @@ static void win_rotate(bool upwards, int count) } else { // last window becomes first window // find last window/frame in the list and remove it for (frp = curwin->w_frame; frp->fr_next != NULL; - frp = frp->fr_next) { - } + frp = frp->fr_next) {} wp1 = frp->fr_win; wp2 = wp1->w_prev; // will become last window win_remove(wp1, NULL); @@ -2957,8 +2955,7 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) // Careful: Autocommands may have closed the tab page or made it the // current tab page. - for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next) { - } + 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. @@ -3316,8 +3313,7 @@ static tabpage_T *alt_tabpage(void) } // Find the last but one tab page. - for (tp = first_tabpage; tp->tp_next != curtab; tp = tp->tp_next) { - } + for (tp = first_tabpage; tp->tp_next != curtab; tp = tp->tp_next) {} return tp; } @@ -3440,13 +3436,11 @@ void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh) if (topfirst) { do { frp = frp->fr_next; - } - while (wfh && frp != NULL && frame_fixed_height(frp)); + } while (wfh && frp != NULL && frame_fixed_height(frp)); } else { do { frp = frp->fr_prev; - } - while (wfh && frp != NULL && frame_fixed_height(frp)); + } while (wfh && frp != NULL && frame_fixed_height(frp)); } // Increase "height" if we could not reduce enough frames. if (frp == NULL) { @@ -3553,8 +3547,7 @@ static void frame_add_statusline(frame_T *frp) } else { assert(frp->fr_layout == FR_COL); // Only need to handle the last frame in the column. - for (frp = frp->fr_child; frp->fr_next != NULL; frp = frp->fr_next) { - } + for (frp = frp->fr_child; frp->fr_next != NULL; frp = frp->fr_next) {} frame_add_statusline(frp); } } @@ -3640,13 +3633,11 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw if (leftfirst) { do { frp = frp->fr_next; - } - while (wfw && frp != NULL && frame_fixed_width(frp)); + } while (wfw && frp != NULL && frame_fixed_width(frp)); } else { do { frp = frp->fr_prev; - } - while (wfw && frp != NULL && frame_fixed_width(frp)); + } while (wfw && frp != NULL && frame_fixed_width(frp)); } // Increase "width" if we could not reduce enough frames. if (frp == NULL) { @@ -4424,14 +4415,12 @@ void goto_tabpage(int n) ttp = curtab; for (i = n; i < 0; ++i) { for (tp = first_tabpage; tp->tp_next != ttp && tp->tp_next != NULL; - tp = tp->tp_next) { - } + tp = tp->tp_next) {} ttp = tp; } } else if (n == 9999) { // Go to last tab page. - for (tp = first_tabpage; tp->tp_next != NULL; tp = tp->tp_next) { - } + for (tp = first_tabpage; tp->tp_next != NULL; tp = tp->tp_next) {} } else { // Go to tab page "n". tp = find_tabpage(n); -- cgit From af782a630633ffe0cb082bda974b24d4f577313e Mon Sep 17 00:00:00 2001 From: Dundar Goc Date: Sat, 30 Apr 2022 20:28:04 +0200 Subject: refactor: replace char_u variables and functions with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 7d96532b8e..90f7145f51 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -489,7 +489,7 @@ wingotofile: setpcmark(); if (win_split(0, 0) == OK) { RESET_BINDING(curwin); - if (do_ecmd(0, ptr, NULL, NULL, ECMD_LASTL, ECMD_HIDE, NULL) == FAIL) { + if (do_ecmd(0, (char *)ptr, NULL, NULL, ECMD_LASTL, ECMD_HIDE, NULL) == FAIL) { // Failed to open the file, close the window opened for it. win_close(curwin, false, false); goto_tabpage_win(oldtab, oldwin); -- cgit From b5957c3c3243c247bc5bec44e44cdaf8230a6c5d Mon Sep 17 00:00:00 2001 From: shirasaka Date: Sat, 30 Apr 2022 16:49:29 +0900 Subject: fix: display global statusline correctly with ext_messages --- src/nvim/window.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 90f7145f51..110c5644d9 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5489,7 +5489,7 @@ void win_setheight_win(int height, win_T *win) } } cmdline_row = row; - p_ch = MAX(Rows - cmdline_row, 1); + p_ch = MAX(Rows - cmdline_row, ui_has(kUIMessages) ? 0 : 1); curtab->tp_ch_used = p_ch; msg_row = row; msg_col = 0; @@ -5997,10 +5997,7 @@ void win_drag_status_line(win_T *dragwin, int offset) clear_cmdline = true; } cmdline_row = row; - p_ch = Rows - cmdline_row; - if (p_ch < 1) { - p_ch = 1; - } + p_ch = MAX(Rows - cmdline_row, ui_has(kUIMessages) ? 0 : 1); curtab->tp_ch_used = p_ch; redraw_all_later(SOME_VALID); showmode(); -- cgit From 82c7a82c3585100e73e154c49e3e002b7dc35437 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 5 May 2022 07:26:42 +0800 Subject: vim-patch:8.2.4868: when closing help window autocmds triggered for wrong window (#18420) Problem: When closing help window autocmds triggered for the wrong window. Solution: Figure out the new current window earlier. (closes vim/vim#10348) https://github.com/vim/vim/commit/2a2707d03337d0bb7d5fd1770238809618653d4a --- src/nvim/window.c | 60 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 26 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 90f7145f51..6bae92c909 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2813,10 +2813,11 @@ int win_close(win_T *win, bool free_buf, bool force) wp = win_free_mem(win, &dir, NULL); if (help_window) { - // Closing the help window moves the cursor back to the original window. - win_T *tmpwp = get_snapshot_focus(SNAP_HELP_IDX); - if (tmpwp != NULL) { - wp = tmpwp; + // Closing the help window moves the cursor back to the current window + // of the snapshot. + win_T *prev_win = get_snapshot_curwin(SNAP_HELP_IDX); + if (win_valid(prev_win)) { + wp = prev_win; } } @@ -6827,6 +6828,35 @@ static void clear_snapshot_rec(frame_T *fr) } } +/// Traverse a snapshot to find the previous curwin. +static win_T *get_snapshot_curwin_rec(frame_T *ft) +{ + win_T *wp; + + if (ft->fr_next != NULL) { + if ((wp = get_snapshot_curwin_rec(ft->fr_next)) != NULL) { + return wp; + } + } + if (ft->fr_child != NULL) { + if ((wp = get_snapshot_curwin_rec(ft->fr_child)) != NULL) { + return wp; + } + } + + return ft->fr_win; +} + +/// @return the current window stored in the snapshot or NULL. +static win_T *get_snapshot_curwin(int idx) +{ + if (curtab->tp_snapshot[idx] == NULL) { + return NULL; + } + + return get_snapshot_curwin_rec(curtab->tp_snapshot[idx]); +} + /// Restore a previously created snapshot, if there is any. /// This is only done if the screen size didn't change and the window layout is /// still the same. @@ -6899,28 +6929,6 @@ static win_T *restore_snapshot_rec(frame_T *sn, frame_T *fr) return wp; } -/// Gets the focused window (the one holding the cursor) of the snapshot. -static win_T *get_snapshot_focus(int idx) -{ - if (curtab->tp_snapshot[idx] == NULL) { - return NULL; - } - - frame_T *sn = curtab->tp_snapshot[idx]; - // This should be equivalent to the recursive algorithm found in - // restore_snapshot as far as traveling nodes go. - while (sn->fr_child != NULL || sn->fr_next != NULL) { - while (sn->fr_child != NULL) { - sn = sn->fr_child; - } - if (sn->fr_next != NULL) { - sn = sn->fr_next; - } - } - - return win_valid(sn->fr_win) ? sn->fr_win : NULL; -} - /// Set "win" to be the curwin and "tp" to be the current tab page. /// restore_win() MUST be called to undo, also when FAIL is returned. /// No autocommands will be executed until restore_win() is called. -- cgit From 2a378e6e82cececb12339f2df51ffe107039d867 Mon Sep 17 00:00:00 2001 From: Dundar Goc Date: Wed, 4 May 2022 22:35:50 +0200 Subject: refactor: replace char_u variables and functions with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 887df31650..9cf1e3eca1 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6534,7 +6534,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u // Skip over the "\" in "\ ". ++len; } - len += (size_t)(utfc_ptr2len(ptr + len)); + len += (size_t)(utfc_ptr2len((char *)ptr + len)); } /* -- cgit From df41d884a7b788bb38060e732f1a7abb08de7b1b Mon Sep 17 00:00:00 2001 From: bfredl Date: Sun, 8 May 2022 13:04:18 +0200 Subject: refactor(grid): move out grid_* functions from screen.c Also normalize some types. use "size_t" for unsigned array offsets. Fix -Wconversion issues missed as screen.c is missing this check. --- src/nvim/window.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 9cf1e3eca1..bbae2bfaaf 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -806,7 +806,7 @@ void win_config_float(win_T *wp, FloatConfig fconfig) col += parent->w_wincol; ScreenGrid *grid = &parent->w_grid; int row_off = 0, col_off = 0; - screen_adjust_grid(&grid, &row_off, &col_off); + grid_adjust(&grid, &row_off, &col_off); row += row_off; col += col_off; } @@ -877,7 +877,7 @@ void ui_ext_win_position(win_T *wp) if (win) { grid = &win->w_grid; int row_off = 0, col_off = 0; - screen_adjust_grid(&grid, &row_off, &col_off); + grid_adjust(&grid, &row_off, &col_off); row += row_off; col += col_off; if (c.bufpos.lnum >= 0) { -- cgit From e31b32a293f6ba8708499a176234f8be1df6a145 Mon Sep 17 00:00:00 2001 From: Dundar Goc Date: Thu, 5 May 2022 13:36:14 +0200 Subject: refactor: replace char_u variables and functions with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/window.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index bbae2bfaaf..de57ce7a1d 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6560,13 +6560,13 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u } else if (STRNCMP(p, line_transl, STRLEN(line_transl)) == 0) { p += STRLEN(line_transl); } else { - p = skipwhite(p); + p = (char_u *)skipwhite((char *)p); } if (*p != NUL) { if (!isdigit(*p)) { p++; // skip the separator } - p = skipwhite(p); + p = (char_u *)skipwhite((char *)p); if (isdigit(*p)) { *file_lnum = getdigits_long(&p, false, 0); } -- cgit From 9aa5647e686e5420e5b9b51828ec7d55631f98ed Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 10 May 2022 07:58:58 +0800 Subject: vim-patch:8.2.4911: the mode #defines are not clearly named (#18499) Problem: The mode #defines are not clearly named. Solution: Prepend MODE_. Renumber them to put the mapped modes first. https://github.com/vim/vim/commit/249591057b4840785c50e41dd850efb8a8faf435 A hunk from the patch depends on patch 8.2.4861, which hasn't been ported yet, but that should be easy to notice. --- src/nvim/window.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index de57ce7a1d..3420e5a10d 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2376,7 +2376,7 @@ static void leaving_window(win_T *const win) // When leaving the window (or closing the window) was done from a // callback we need to break out of the Insert mode loop and restart Insert // mode when entering the window again. - if (State & INSERT) { + if (State & MODE_INSERT) { stop_insert_mode = true; if (win->w_buffer->b_prompt_insert == NUL) { win->w_buffer->b_prompt_insert = 'A'; @@ -2400,7 +2400,7 @@ void entering_window(win_T *const win) // When entering the prompt window restart Insert mode if we were in Insert // mode when we left it and not already in Insert mode. - if ((State & INSERT) == 0) { + if ((State & MODE_INSERT) == 0) { restart_edit = win->w_buffer->b_prompt_insert; } } -- cgit From 85aae12a6dea48621ea2d24a946b3e7b86f9014d Mon Sep 17 00:00:00 2001 From: Dundar Goc Date: Sun, 8 May 2022 14:43:16 +0200 Subject: refactor: replace char_u variables and functions with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/window.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 3420e5a10d..9f7e2f8341 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6477,7 +6477,7 @@ char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum) char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u *rel_fname, linenr_T *file_lnum) { - char_u *ptr; + char *ptr; size_t len; bool in_type = true; bool is_url = false; @@ -6485,7 +6485,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u /* * search forward for what could be the start of a file name */ - ptr = line + col; + ptr = (char *)line + col; while (*ptr != NUL && !vim_isfilec(*ptr)) { MB_PTR_ADV(ptr); } @@ -6500,11 +6500,10 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u * Search backward for first char of the file name. * Go one char back to ":" before "//" even when ':' is not in 'isfname'. */ - while (ptr > line) { - if ((len = (size_t)(utf_head_off(line, ptr - 1))) > 0) { + while ((char_u *)ptr > line) { + if ((len = (size_t)(utf_head_off(line, (char_u *)ptr - 1))) > 0) { ptr -= len + 1; - } else if (vim_isfilec(ptr[-1]) - || ((options & FNAME_HYP) && path_is_url((char *)ptr - 1))) { + } else if (vim_isfilec(ptr[-1]) || ((options & FNAME_HYP) && path_is_url(ptr - 1))) { ptr--; } else { break; @@ -6517,13 +6516,13 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u */ len = 0; while (vim_isfilec(ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ') - || ((options & FNAME_HYP) && path_is_url((char *)ptr + len)) + || ((options & FNAME_HYP) && path_is_url(ptr + len)) || (is_url && vim_strchr((char_u *)":?&=", ptr[len]) != NULL)) { // After type:// we also include :, ?, & and = as valid characters, so that // http://google.com:8080?q=this&that=ok works. if ((ptr[len] >= 'A' && ptr[len] <= 'Z') || (ptr[len] >= 'a' && ptr[len] <= 'z')) { - if (in_type && path_is_url((char *)ptr + len + 1)) { + if (in_type && path_is_url(ptr + len + 1)) { is_url = true; } } else { @@ -6534,7 +6533,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u // Skip over the "\" in "\ ". ++len; } - len += (size_t)(utfc_ptr2len((char *)ptr + len)); + len += (size_t)(utfc_ptr2len(ptr + len)); } /* @@ -6547,7 +6546,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u } if (file_lnum != NULL) { - char_u *p; + char *p; const char *line_english = " line "; const char *line_transl = _(line_msg); @@ -6560,20 +6559,20 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u } else if (STRNCMP(p, line_transl, STRLEN(line_transl)) == 0) { p += STRLEN(line_transl); } else { - p = (char_u *)skipwhite((char *)p); + p = skipwhite(p); } if (*p != NUL) { if (!isdigit(*p)) { p++; // skip the separator } - p = (char_u *)skipwhite((char *)p); + p = skipwhite(p); if (isdigit(*p)) { - *file_lnum = getdigits_long(&p, false, 0); + *file_lnum = getdigits_long((char_u **)&p, false, 0); } } } - return find_file_name_in_path(ptr, len, options, count, rel_fname); + return find_file_name_in_path((char_u *)ptr, len, options, count, rel_fname); } /// Add or remove a status line from window(s), according to the -- cgit From f0148de7907ec297647816d51c79745be729439e Mon Sep 17 00:00:00 2001 From: Dundar Goc Date: Mon, 9 May 2022 11:49:32 +0200 Subject: refactor: replace char_u variables and functions with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/window.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 9f7e2f8341..2c27a5d6a5 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2916,8 +2916,8 @@ static void do_autocmd_winclosed(win_T *win) return; } recursive = true; - char_u winid[NUMBUFLEN]; - vim_snprintf((char *)winid, sizeof(winid), "%d", win->handle); + char winid[NUMBUFLEN]; + vim_snprintf(winid, sizeof(winid), "%d", win->handle); apply_autocmds(EVENT_WINCLOSED, winid, winid, false, win->w_buffer); recursive = false; } @@ -2984,9 +2984,9 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) // When closing the last window in a tab page remove the tab page. if (tp->tp_firstwin == tp->tp_lastwin) { - char_u prev_idx[NUMBUFLEN]; + char prev_idx[NUMBUFLEN]; if (has_event(EVENT_TABCLOSED)) { - vim_snprintf((char *)prev_idx, NUMBUFLEN, "%i", tabpage_index(tp)); + vim_snprintf(prev_idx, NUMBUFLEN, "%i", tabpage_index(tp)); } if (tp == first_tabpage) { @@ -4098,7 +4098,7 @@ int win_new_tabpage(int after, char_u *filename) apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf); apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf); - apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf); + apply_autocmds(EVENT_TABNEW, (char *)filename, (char *)filename, false, curbuf); apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf); return OK; @@ -4890,7 +4890,7 @@ void fix_current_dir(void) // (unless that was done already) and change to the local directory. if (globaldir == NULL) { if (cwd[0] != NUL) { - globaldir = (char_u *)xstrdup(cwd); + globaldir = xstrdup(cwd); } } bool dir_differs = pathcmp(new_dir, cwd, -1) != 0; @@ -4909,13 +4909,13 @@ void fix_current_dir(void) } else if (globaldir != NULL) { // Window doesn't have a local directory and we are not in the global // directory: Change to the global directory. - bool dir_differs = pathcmp((char *)globaldir, cwd, -1) != 0; + bool dir_differs = pathcmp(globaldir, cwd, -1) != 0; if (!p_acd && dir_differs) { - do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow, true); + do_autocmd_dirchanged(globaldir, kCdScopeGlobal, kCdCauseWindow, true); } - if (os_chdir((char *)globaldir) == 0) { + if (os_chdir(globaldir) == 0) { if (!p_acd && dir_differs) { - do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow, false); + do_autocmd_dirchanged(globaldir, kCdScopeGlobal, kCdCauseWindow, false); } } XFREE_CLEAR(globaldir); @@ -5317,8 +5317,8 @@ void may_trigger_winscrolled(void) || wp->w_last_leftcol != wp->w_leftcol || wp->w_last_width != wp->w_width || wp->w_last_height != wp->w_height) { - char_u winid[NUMBUFLEN]; - vim_snprintf((char *)winid, sizeof(winid), "%d", wp->handle); + char winid[NUMBUFLEN]; + vim_snprintf(winid, sizeof(winid), "%d", wp->handle); recursive = true; apply_autocmds(EVENT_WINSCROLLED, winid, winid, false, wp->w_buffer); @@ -6517,7 +6517,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u len = 0; while (vim_isfilec(ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ') || ((options & FNAME_HYP) && path_is_url(ptr + len)) - || (is_url && vim_strchr((char_u *)":?&=", ptr[len]) != NULL)) { + || (is_url && vim_strchr(":?&=", ptr[len]) != NULL)) { // After type:// we also include :, ?, & and = as valid characters, so that // http://google.com:8080?q=this&that=ok works. if ((ptr[len] >= 'A' && ptr[len] <= 'Z') @@ -6540,7 +6540,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u * If there is trailing punctuation, remove it. * But don't remove "..", could be a directory name. */ - if (len > 2 && vim_strchr((char_u *)".,:;!", ptr[len - 1]) != NULL + if (len > 2 && vim_strchr(".,:;!", ptr[len - 1]) != NULL && ptr[len - 2] != '.') { --len; } -- cgit From e1bdb2a258cbe6c5cb981acc6bac82cd9e7706fb Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Fri, 13 May 2022 20:47:11 +0600 Subject: feat(ui): add `'winbar'` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for a bar at the top of each window, enabled through the `'winbar'` option. Co-authored-by: Björn Linse --- src/nvim/window.c | 146 +++++++++++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 68 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 2c27a5d6a5..51208e7178 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -695,6 +695,7 @@ win_T *win_new_float(win_T *wp, bool last, FloatConfig fconfig, Error *err) } wp->w_floating = 1; wp->w_status_height = 0; + wp->w_winbar_height = 0; wp->w_hsep_height = 0; wp->w_vsep_width = 0; @@ -780,10 +781,8 @@ void win_config_float(win_T *wp, FloatConfig fconfig) } if (!ui_has(kUIMultigrid)) { - wp->w_height = MIN(wp->w_height, - Rows - 1 - (wp->w_border_adj[0] + wp->w_border_adj[2])); - wp->w_width = MIN(wp->w_width, - Columns - (wp->w_border_adj[1] + wp->w_border_adj[3])); + wp->w_height = MIN(wp->w_height, Rows - 1 - win_extra_height(wp)); + wp->w_width = MIN(wp->w_width, Columns - win_extra_width(wp)); } win_set_inner_size(wp); @@ -1138,15 +1137,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } else { layout = FR_COL; - /* - * Check if we are able to split the current window and compute its - * height. - */ - // Current window requires at least 1 space. - wmh1 = p_wmh == 0 ? 1 : p_wmh; + // Check if we are able to split the current window and compute its height. + // Current window requires at least 1 space plus space for the window bar. + wmh1 = MAX(p_wmh, 1) + oldwin->w_winbar_height; needed = wmh1 + STATUS_HEIGHT; if (flags & WSP_ROOM) { - needed += p_wh - wmh1; + needed += p_wh - wmh1 + oldwin->w_winbar_height; } if (flags & (WSP_BOT | WSP_TOP)) { minheight = frame_minheight(topframe, NOWIN) + need_status; @@ -1155,8 +1151,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } else if (p_ea) { minheight = frame_minheight(oldwin->w_frame, NOWIN) + need_status; prevfrp = oldwin->w_frame; - for (frp = oldwin->w_frame->fr_parent; frp != NULL; - frp = frp->fr_parent) { + for (frp = oldwin->w_frame->fr_parent; frp != NULL; frp = frp->fr_parent) { if (frp->fr_layout == FR_COL) { FOR_ALL_FRAMES(frp2, frp->fr_child) { if (frp2 != prevfrp) { @@ -1339,6 +1334,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) set_fraction(oldwin); } wp->w_fraction = oldwin->w_fraction; + wp->w_winbar_height = oldwin->w_winbar_height; if (flags & WSP_VERT) { wp->w_p_scr = curwin->w_p_scr; @@ -1416,9 +1412,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) if (flags & (WSP_TOP | WSP_BOT)) { int new_fr_height = curfrp->fr_height - new_size; - if (!((flags & WSP_BOT) && p_ls == 0) && global_stl_height() == 0) { + if (!((flags & WSP_BOT) && p_ls == 0) && !is_stl_global) { new_fr_height -= STATUS_HEIGHT; - } else if (global_stl_height() > 0) { + } else if (is_stl_global) { if (flags & WSP_BOT) { frame_add_hsep(curfrp); } else { @@ -1452,7 +1448,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } } } - if ((flags & WSP_BOT) && global_stl_height() == 0) { + if ((flags & WSP_BOT) && !is_stl_global) { frame_add_statusline(curfrp); } frame_fix_height(wp); @@ -1482,10 +1478,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) * equalize the window sizes. */ if (do_equal || dir != 0) { - win_equal(wp, true, - (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') - : dir == 'h' ? 'b' : - 'v'); + win_equal(wp, true, (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v')); } // Don't change the window height/width to 'winheight' / 'winwidth' if a @@ -1675,10 +1668,10 @@ int win_count(void) } /// Make "count" windows on the screen. -/// Must be called when there is just one window, filling the whole screen +/// Must be called when there is just one window, filling the whole screen. /// (excluding the command line). /// -/// @param vertical split windows vertically if true +/// @param vertical split windows vertically if true. /// /// @return actual number of windows on the screen. int make_windows(int count, bool vertical) @@ -1687,15 +1680,15 @@ int make_windows(int count, bool vertical) int todo; if (vertical) { - // Each window needs at least 'winminwidth' lines and a separator - // column. + // Each window needs at least 'winminwidth' lines and a separator column. maxcount = (curwin->w_width + curwin->w_vsep_width - (p_wiw - p_wmw)) / (p_wmw + 1); } else { - // Each window needs at least 'winminheight' lines - // If statusline isn't global, each window also needs a statusline + // Each window needs at least 'winminheight' lines. + // If statusline isn't global, each window also needs a statusline. + // If 'winbar' is set, each window also needs a winbar. maxcount = (curwin->w_height + curwin->w_hsep_height + curwin->w_status_height - - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT); + - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT + global_winbar_height()); } if (maxcount < 2) { @@ -1705,17 +1698,13 @@ int make_windows(int count, bool vertical) count = maxcount; } - /* - * add status line now, otherwise first window will be too big - */ + // add status line now, otherwise first window will be too big if (count > 1) { last_status(true); } - /* - * Don't execute autocommands while creating the windows. Must do that - * when putting the buffers in the windows. - */ + // Don't execute autocommands while creating the windows. Must do that + // when putting the buffers in the windows. block_autocmds(); // todo is number of windows left to create @@ -1790,7 +1779,7 @@ static void win_exchange(long Prenum) * if wp != wp2 * 3. remove wp from the list * 4. insert wp after wp2 - * 5. exchange the status line height, hsep height and vsep width. + * 5. exchange the status line height, winbar height, hsep height and vsep width. */ wp2 = curwin->w_prev; frp2 = curwin->w_frame->fr_prev; @@ -1897,7 +1886,7 @@ static void win_rotate(bool upwards, int count) frame_insert(frp->fr_parent->fr_child, frp); } - // exchange status height, hsep height and vsep width of old and new last window + // exchange status height, winbar height, hsep height and vsep width of old and new last window n = wp2->w_status_height; wp2->w_status_height = wp1->w_status_height; wp1->w_status_height = n; @@ -1988,7 +1977,8 @@ void win_move_after(win_T *win1, win_T *win2) return; } - // may need move the status line, horizontal or vertical separator of the last window + // may need move the status line, window bar, horizontal or vertical separator of the last + // window if (win1 == lastwin) { height = win1->w_prev->w_status_height; win1->w_prev->w_status_height = win1->w_status_height; @@ -2237,7 +2227,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 + STATUS_HEIGHT); + totwincount = (n + extra_sep) / (p_wmh + STATUS_HEIGHT + global_winbar_height()); has_next_curwin = frame_has_win(topfr, next_curwin); /* @@ -2272,7 +2262,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 + STATUS_HEIGHT); + ? extra_sep : 0)) / (p_wmh + STATUS_HEIGHT + global_winbar_height()); } room -= new_size - n; if (room < 0) { @@ -2318,7 +2308,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 + STATUS_HEIGHT); + / (p_wmh + STATUS_HEIGHT + global_winbar_height()); m = frame_minheight(fr, next_curwin); if (has_next_curwin) { hnc = frame_has_win(fr, next_curwin); @@ -3732,13 +3722,9 @@ static void frame_fix_height(win_T *wp) wp->w_frame->fr_height = wp->w_height + wp->w_hsep_height + wp->w_status_height; } -/* - * Compute the minimal height for frame "topfrp". - * Uses the 'winminheight' option. - * When "next_curwin" isn't NULL, use p_wh for this window. - * When "next_curwin" is NOWIN, don't use at least one line for the current - * window. - */ +/// Compute the minimal height for frame "topfrp". Uses the 'winminheight' option. +/// When "next_curwin" isn't NULL, use p_wh for this window. +/// When "next_curwin" is NOWIN, don't use at least one line for the current window. static int frame_minheight(frame_T *topfrp, win_T *next_curwin) { frame_T *frp; @@ -3746,12 +3732,14 @@ static int frame_minheight(frame_T *topfrp, win_T *next_curwin) int n; if (topfrp->fr_win != NULL) { + // Combined height of window bar and separator column or status line. + int extra_height = topfrp->fr_win->w_winbar_height + topfrp->fr_win->w_hsep_height + + topfrp->fr_win->w_status_height; + if (topfrp->fr_win == next_curwin) { - m = p_wh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height; + m = p_wh + extra_height; } else { - // window: minimal height of the window plus separator column or status line - // depending on whether global statusline is enabled - m = p_wmh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height; + m = p_wmh + extra_height; if (topfrp->fr_win == curwin && next_curwin == NULL) { // Current window is minimal one line high. if (p_wmh == 0) { @@ -3976,7 +3964,7 @@ static void new_frame(win_T *wp) void win_init_size(void) { firstwin->w_height = ROWS_AVAIL; - firstwin->w_height_inner = firstwin->w_height; + firstwin->w_height_inner = firstwin->w_height - firstwin->w_winbar_height; firstwin->w_height_outer = firstwin->w_height; topframe->fr_height = ROWS_AVAIL; firstwin->w_width = Columns; @@ -4087,6 +4075,7 @@ int win_new_tabpage(int after, char_u *filename) newtp->tp_topframe = topframe; last_status(false); + set_winbar(); redraw_all_later(NOT_VALID); @@ -5460,16 +5449,9 @@ void win_setheight(int height) */ void win_setheight_win(int height, win_T *win) { - if (win == curwin) { - // Always keep current window at least one line high, even when - // 'winminheight' is zero. - if (height < p_wmh) { - height = p_wmh; - } - if (height == 0) { - height = 1; - } - } + // Always keep current window at least one line high, even when 'winminheight' is zero. + // Keep window at least two lines high if 'winbar' is enabled. + height = MAX(height, (win == curwin ? MAX(p_wmh, 1) : p_wmh) + win->w_winbar_height); if (win->w_floating) { win->w_float_config.height = height; @@ -6262,7 +6244,7 @@ void win_set_inner_size(win_T *wp) int prev_height = wp->w_height_inner; int height = wp->w_height_request; if (height == 0) { - height = wp->w_height; + height = wp->w_height - wp->w_winbar_height; } if (height != prev_height) { @@ -6279,8 +6261,9 @@ void win_set_inner_size(win_T *wp) set_fraction(wp); } } - wp->w_height_inner = height; wp->w_skipcol = 0; + wp->w_height_inner = height; + wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height; // There is no point in adjusting the scroll position when exiting. Some // values might be invalid. @@ -6306,10 +6289,18 @@ void win_set_inner_size(win_T *wp) terminal_check_size(wp->w_buffer->terminal); } - wp->w_height_outer = (wp->w_height_inner - + wp->w_border_adj[0] + wp->w_border_adj[2]); - wp->w_width_outer = (wp->w_width_inner - + wp->w_border_adj[1] + wp->w_border_adj[3]); + wp->w_height_outer = (wp->w_height_inner + win_extra_height(wp)); + wp->w_width_outer = (wp->w_width_inner + win_extra_width(wp)); +} + +static int win_extra_height(win_T *wp) +{ + return wp->w_border_adj[0] + wp->w_border_adj[2]; +} + +static int win_extra_width(win_T *wp) +{ + return wp->w_border_adj[1] + wp->w_border_adj[3]; } /// Set the width of a window. @@ -6662,6 +6653,19 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) } } +// Add or remove window bars from windows depending on the value of 'winbar'. +void set_winbar(void) +{ + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + int winbar_height = (*p_wbr != NUL || *wp->w_p_wbr != NUL) ? 1 : 0; + if (wp->w_winbar_height != winbar_height) { + wp->w_winbar_height = winbar_height; + win_set_inner_size(wp); + wp->w_redr_winbar = winbar_height; + } + } +} + /// Return the number of lines used by the tab page line. int tabline_height(void) { @@ -6678,6 +6682,12 @@ int tabline_height(void) return 1; } +/// Return the number of lines used by default by the window bar. +int global_winbar_height(void) +{ + return *p_wbr != NUL ? 1 : 0; +} + /// Return the number of lines used by the global statusline int global_stl_height(void) { -- cgit From c28192e6f9c16de3add78c5ecf8e732c241f945a Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 18 May 2022 13:29:02 +0200 Subject: refactor: move more grid functions to grid.c. Clean up some variables --- src/nvim/window.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 51208e7178..7e7c639a15 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6263,7 +6263,6 @@ void win_set_inner_size(win_T *wp) } wp->w_skipcol = 0; wp->w_height_inner = height; - wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height; // There is no point in adjusting the scroll position when exiting. Some // values might be invalid. @@ -6291,6 +6290,8 @@ void win_set_inner_size(win_T *wp) wp->w_height_outer = (wp->w_height_inner + win_extra_height(wp)); wp->w_width_outer = (wp->w_width_inner + win_extra_width(wp)); + wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height; + wp->w_wincol_off = wp->w_border_adj[3]; } static int win_extra_height(win_T *wp) -- cgit From 17758fe7ad0d5db54dc43e364d53f637a148e73f Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 18 May 2022 13:51:59 +0200 Subject: fix(ui): make winbar work with floats and multigrid --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 7e7c639a15..5cc24bbb5b 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6296,7 +6296,7 @@ void win_set_inner_size(win_T *wp) static int win_extra_height(win_T *wp) { - return wp->w_border_adj[0] + wp->w_border_adj[2]; + return wp->w_border_adj[0] + wp->w_border_adj[2] + wp->w_winbar_height; } static int win_extra_width(win_T *wp) -- cgit From 341d0ec3b31018ebb38d6ecf9b6f4a2319bbfc18 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 19 May 2022 09:56:44 +0800 Subject: vim-patch:8.2.4979: accessing freed memory when line is flushed (#18634) Problem: Accessing freed memory when line is flushed. Solution: Make a copy of the pattern to search for. https://github.com/vim/vim/commit/28d032cc688ccfda18c5bbcab8b50aba6e18cde5 --- src/nvim/window.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 5cc24bbb5b..9c9b1fe176 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -515,9 +515,14 @@ wingotofile: if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0) { break; } + + // Make a copy, if the line was changed it will be freed. + ptr = vim_strnsave(ptr, len); + find_pattern_in_path(ptr, 0, len, true, Prenum == 0, type, Prenum1, ACTION_SPLIT, 1, MAXLNUM); - curwin->w_set_curswant = TRUE; + xfree(ptr); + curwin->w_set_curswant = true; break; // Quickfix window only: view the result under the cursor in a new split. -- cgit From 643cc94e7e8c0cc970c08a916baebb19075040e2 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 19 May 2022 01:09:52 +0600 Subject: fix(ui): make `winbar` properly equalize window heights for local value Fixes `'winbar'` not properly equalizing window heights for splits when the global value is empty and a window-local value is set instead. --- src/nvim/window.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 51208e7178..1bff5933ea 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2028,6 +2028,37 @@ void win_move_after(win_T *win1, win_T *win2) win2->w_pos_changed = true; } +/// Compute maximum number of windows that can fit within "height" in frame "fr". +static int get_maximum_wincount(frame_T *fr, int height) +{ + if (fr->fr_layout != FR_COL) { + return (height / (p_wmh + STATUS_HEIGHT + frame2win(fr)->w_winbar_height)); + } else if (global_winbar_height()) { + // If winbar is globally enabled, no need to check each window for it. + return (height / (p_wmh + STATUS_HEIGHT + 1)); + } + + frame_T *frp; + int total_wincount = 0; + + // First, try to fit all child frames of "fr" into "height" + FOR_ALL_FRAMES(frp, fr->fr_child) { + win_T *wp = frame2win(frp); + + if (height < (p_wmh + STATUS_HEIGHT + wp->w_winbar_height)) { + break; + } + height -= p_wmh + STATUS_HEIGHT + wp->w_winbar_height; + total_wincount += 1; + } + + // If we still have enough room for more windows, just use the default winbar height (which is 0) + // in order to get the amount of windows that'd fit in the remaining space + total_wincount += height / (p_wmh + STATUS_HEIGHT); + + return total_wincount; +} + /// Make all windows the same height. ///'next_curwin' will soon be the current window, make sure it has enough rows. /// @@ -2227,7 +2258,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 + STATUS_HEIGHT + global_winbar_height()); + totwincount = get_maximum_wincount(topfr, n + extra_sep); has_next_curwin = frame_has_win(topfr, next_curwin); /* @@ -2261,8 +2292,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 + STATUS_HEIGHT + global_winbar_height()); + totwincount -= get_maximum_wincount(fr, (n + (fr->fr_next == NULL ? extra_sep : 0))); } room -= new_size - n; if (room < 0) { @@ -2307,8 +2337,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int } else { // 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 + STATUS_HEIGHT + global_winbar_height()); + wincount = get_maximum_wincount(fr, (n + (fr->fr_next == NULL ? extra_sep : 0))); m = frame_minheight(fr, next_curwin); if (has_next_curwin) { hnc = frame_has_win(fr, next_curwin); -- cgit From 4c6626f03dc645a426c1e63ca372b96f1073581b Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Mon, 23 May 2022 19:11:24 +0600 Subject: feat: click support for 'statusline', 'winbar' #18650 The mouseclick item "%@" is now supported by 'statusline' and 'winbar'. Previously it was only supported by 'tabline'. --- src/nvim/window.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 4076bb2531..835aba204d 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5119,6 +5119,12 @@ static void win_free(win_T *wp, tabpage_T *tp) xfree(wp->w_localdir); xfree(wp->w_prevdir); + stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size); + xfree(wp->w_status_click_defs); + + stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size); + xfree(wp->w_winbar_click_defs); + // Remove the window from the b_wininfo lists, it may happen that the // freed memory is re-used for another window. FOR_ALL_BUFFERS(buf) { @@ -6612,6 +6618,23 @@ void last_status(bool morewin) global_stl_height() > 0); } +// Remove status line from window, replacing it with a horizontal separator if needed. +static void win_remove_status_line(win_T *wp, bool add_hsep) +{ + wp->w_status_height = 0; + if (add_hsep) { + wp->w_hsep_height = 1; + } else { + win_new_height(wp, wp->w_height + STATUS_HEIGHT); + } + comp_col(); + + stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size); + xfree(wp->w_status_click_defs); + wp->w_status_click_defs_size = 0; + wp->w_status_click_defs = NULL; +} + // Look for resizable frames and take lines from them to make room for the statusline static void resize_frame_for_status(frame_T *fr) { @@ -6652,10 +6675,7 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) if (is_last) { if (wp->w_status_height != 0 && (!statusline || is_stl_global)) { - // Remove status line - wp->w_status_height = 0; - win_new_height(wp, wp->w_height + STATUS_HEIGHT); - comp_col(); + win_remove_status_line(wp, false); } else if (wp->w_status_height == 0 && !is_stl_global && statusline) { // Add statusline to window if needed wp->w_status_height = STATUS_HEIGHT; @@ -6665,9 +6685,7 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) } 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 - wp->w_status_height = 0; - wp->w_hsep_height = 1; - comp_col(); + win_remove_status_line(wp, true); } else if (wp->w_status_height == 0 && !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; @@ -6675,13 +6693,8 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) comp_col(); } redraw_all_later(SOME_VALID); - } else if (fr->fr_layout == FR_COL) { - // For a column frame, recursively call this function for all child frames - FOR_ALL_FRAMES(fp, fr->fr_child) { - last_status_rec(fp, statusline, is_stl_global); - } } else { - // For a row frame, recursively call this function for all child frames + // For a column or row frame, recursively call this function for all child frames FOR_ALL_FRAMES(fp, fr->fr_child) { last_status_rec(fp, statusline, is_stl_global); } @@ -6697,6 +6710,14 @@ void set_winbar(void) wp->w_winbar_height = winbar_height; win_set_inner_size(wp); wp->w_redr_winbar = winbar_height; + + if (winbar_height == 0) { + // When removing winbar, deallocate the w_winbar_click_defs array + stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size); + xfree(wp->w_winbar_click_defs); + wp->w_winbar_click_defs_size = 0; + wp->w_winbar_click_defs = NULL; + } } } } -- cgit From 353553f913e5ad7b36182eed473660c92d656656 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Mon, 23 May 2022 18:38:07 +0600 Subject: fix(ui): redraw winbar alongside statusline Remove `w_redr_winbar` and use `w_redr_status` to redraw the winbar to ensure that winbar redraw is triggered alongside the statusline redraw. --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 835aba204d..0ba5bb1889 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6709,7 +6709,7 @@ void set_winbar(void) if (wp->w_winbar_height != winbar_height) { wp->w_winbar_height = winbar_height; win_set_inner_size(wp); - wp->w_redr_winbar = winbar_height; + wp->w_redr_status = wp->w_redr_status || winbar_height; if (winbar_height == 0) { // When removing winbar, deallocate the w_winbar_click_defs array -- cgit From 9fec6dc9a25b5cf9c9a444ac2bd0728e8af3229e Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 25 May 2022 20:31:14 +0200 Subject: refactor(uncrustify): set maximum number of consecutive newlines to 2 (#18695) --- src/nvim/window.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 0ba5bb1889..f42ef874ef 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -53,12 +53,10 @@ #include "nvim/vim.h" #include "nvim/window.h" - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "window.c.generated.h" #endif - #define NOWIN ((win_T *)-1) // non-existing window #define ROWS_AVAIL (Rows - p_ch - tabline_height() - global_stl_height()) @@ -533,7 +531,6 @@ wingotofile: } break; - // CTRL-W g extended commands case 'g': case Ctrl_G: @@ -773,7 +770,6 @@ void win_config_float(win_T *wp, FloatConfig fconfig) wp->w_float_config.border_hl_ids, sizeof fconfig.border_hl_ids)); - wp->w_float_config = fconfig; bool has_border = wp->w_floating && wp->w_float_config.border; @@ -1055,7 +1051,6 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) need_status = STATUS_HEIGHT; } - if (flags & WSP_VERT) { int wmw1; int minwidth; @@ -1520,7 +1515,6 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) return OK; } - /* * Initialize window "newp" from window "oldp". * Used when splitting a window and when creating a new tab page. @@ -1756,7 +1750,6 @@ static void win_exchange(long Prenum) return; } - /* * find window to exchange with */ @@ -3843,7 +3836,6 @@ static int frame_minwidth(frame_T *topfrp, win_T *next_curwin) return m; } - /// Try to close all windows except current one. /// Buffers in the other windows become hidden if 'hidden' is set, or '!' is /// used and the buffer was modified. @@ -4560,7 +4552,6 @@ void tabpage_move(int nr) redraw_tabline = true; } - /* * Go to another window. * When jumping to another buffer, stop Visual mode. Do this before @@ -4598,7 +4589,6 @@ void win_goto(win_T *wp) } } - /* * Find the tabpage for window "win". */ @@ -5061,7 +5051,6 @@ static win_T *win_alloc(win_T *after, bool hidden) return new_wp; } - // Free one wininfo_T. void free_wininfo(wininfo_T *wip, buf_T *bp) { @@ -5072,7 +5061,6 @@ void free_wininfo(wininfo_T *wip, buf_T *bp) xfree(wip); } - /// Remove window 'wp' from the window list and free the structure. /// /// @param tp tab page "win" is in, NULL for current @@ -5283,7 +5271,6 @@ static void frame_remove(frame_T *frp) } } - /* * Called from win_new_shellsize() after Rows changed. * This only does the current tab page, others must be done when made active. @@ -5473,7 +5460,6 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col) } } - /* * Set current window height and take care of repositioning other windows to * fit around it. @@ -5521,7 +5507,6 @@ void win_setheight_win(int height, win_T *win) } } - /* * Set the height of a frame to "height" and take care that all frames and * windows inside it are resized. Also resize frames on the left and right if @@ -6132,7 +6117,6 @@ void win_drag_vsep_line(win_T *dragwin, int offset) redraw_all_later(NOT_VALID); } - #define FRACTION_MULT 16384L // Set wp->w_fraction for the current w_wrow and w_height. -- cgit From 826462a8f0923926066da66d8575f6573ee3f079 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sat, 28 May 2022 04:57:20 +0600 Subject: fix(ui): require window-local value to show winbar on floating windows (#18773) Previously, there was a bug where setting the local value of 'winbar' to itself would cause winbar to appear on a floating window, which is undesirable. This fix makes it so that it's explicitly required for the window-local value of 'winbar' for a floating window to be set in order for winbar to be shown on that window. --- src/nvim/window.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index f42ef874ef..7b49a3b2d8 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6689,7 +6689,10 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) void set_winbar(void) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - int winbar_height = (*p_wbr != NUL || *wp->w_p_wbr != NUL) ? 1 : 0; + // Require the local value to be set in order to show winbar on a floating window. + int winbar_height = wp->w_floating ? ((*wp->w_p_wbr != NUL) ? 1 : 0) + : ((*p_wbr != NUL || *wp->w_p_wbr != NUL) ? 1 : 0); + if (wp->w_winbar_height != winbar_height) { wp->w_winbar_height = winbar_height; win_set_inner_size(wp); -- cgit From 77d9c672f82d260dc5421519a2f78ed1acc95d6a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 28 May 2022 15:12:42 +0800 Subject: fix(winbar): fix winbar disappear or glitch when moving a split (#18775) --- src/nvim/window.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 7b49a3b2d8..58722b1756 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1334,7 +1334,6 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) set_fraction(oldwin); } wp->w_fraction = oldwin->w_fraction; - wp->w_winbar_height = oldwin->w_winbar_height; if (flags & WSP_VERT) { wp->w_p_scr = curwin->w_p_scr; @@ -1571,6 +1570,8 @@ static void win_init(win_T *newp, win_T *oldp, int flags) copyFoldingState(oldp, newp); win_init_some(newp, oldp); + + newp->w_winbar_height = oldp->w_winbar_height; } /* -- cgit From 9cf1ac037749bf3e32455627071cad4f83e5f6b7 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sat, 28 May 2022 12:58:09 +0600 Subject: fix(winbar): only allow adding winbar when there is space --- src/nvim/window.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 8 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 58722b1756..060f498f07 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6620,17 +6620,15 @@ static void win_remove_status_line(win_T *wp, bool add_hsep) wp->w_status_click_defs = NULL; } -// Look for resizable frames and take lines from them to make room for the statusline -static void resize_frame_for_status(frame_T *fr) +// Look for a horizontally resizable frame, starting with frame "fr". +// Returns NULL if there are no resizable frames. +static frame_T *find_horizontally_resizable_frame(frame_T *fr) { - // Find a frame to take a line from. frame_T *fp = fr; - win_T *wp = fr->fr_win; while (fp->fr_height <= frame_minheight(fp, NULL)) { if (fp == topframe) { - emsg(_(e_noroom)); - return; + return NULL; } // In a column of frames: go to frame above. If already at // the top or in a row of frames: go to parent. @@ -6640,13 +6638,49 @@ static void resize_frame_for_status(frame_T *fr) fp = fp->fr_parent; } } - if (fp != fr) { + + return fp; +} + +// Look for resizable frames and take lines from them to make room for the statusline. +// @return Success or failure. +static bool resize_frame_for_status(frame_T *fr) +{ + win_T *wp = fr->fr_win; + frame_T *fp = find_horizontally_resizable_frame(fr); + + if (fp == NULL) { + emsg(_(e_noroom)); + return false; + } else 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); } + + return true; +} + +// Look for resizable frames and take lines from them to make room for the winbar. +// @return Success or failure. +static bool resize_frame_for_winbar(frame_T *fr) +{ + win_T *wp = fr->fr_win; + frame_T *fp = find_horizontally_resizable_frame(fr); + + if (fp == NULL || fp == fr) { + emsg(_(e_noroom)); + return false; + } else { + frame_new_height(fp, fp->fr_height - 1, false, false); + win_new_height(wp, wp->w_height + 1); + frame_fix_height(wp); + win_comp_pos(); + } + + return true; } static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) @@ -6664,7 +6698,9 @@ 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); + if (!resize_frame_for_status(fr)) { + return; + } comp_col(); } } else if (wp->w_status_height != 0 && is_stl_global) { @@ -6695,6 +6731,14 @@ void set_winbar(void) : ((*p_wbr != NUL || *wp->w_p_wbr != NUL) ? 1 : 0); if (wp->w_winbar_height != winbar_height) { + if (winbar_height == 1 && wp->w_height_inner <= 1) { + if (wp->w_floating) { + emsg(_(e_noroom)); + continue; + } else if (!resize_frame_for_winbar(wp->w_frame)) { + return; + } + } wp->w_winbar_height = winbar_height; win_set_inner_size(wp); wp->w_redr_status = wp->w_redr_status || winbar_height; -- cgit From 015656abd72b7ccac966f21218c4d7108800237a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 29 May 2022 16:26:55 +0800 Subject: fix(winbar): set w_winrow_off when initializing firstwin size (#18793) --- src/nvim/window.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 060f498f07..a41f3362d2 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3993,6 +3993,7 @@ void win_init_size(void) firstwin->w_height = ROWS_AVAIL; firstwin->w_height_inner = firstwin->w_height - firstwin->w_winbar_height; firstwin->w_height_outer = firstwin->w_height; + firstwin->w_winrow_off = firstwin->w_winbar_height; topframe->fr_height = ROWS_AVAIL; firstwin->w_width = Columns; firstwin->w_width_inner = firstwin->w_width; -- cgit From 57a296d899d170e7f78aec2225bf8ab2b0dc711c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 2 Jun 2022 03:48:36 +0800 Subject: fix(inccommand): avoid crash if callback changes inccommand option (#18830) clang: Result of operation is garbage or undefined clang: Uninitialized argument value Also check for == 's' instead of != 'n' as it is more straightforward. Also fix another unrelated PVS warning: PVS/V1071: Return value of win_comp_pos() is not always used --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index a41f3362d2..5f4179944d 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6678,7 +6678,7 @@ static bool resize_frame_for_winbar(frame_T *fr) frame_new_height(fp, fp->fr_height - 1, false, false); win_new_height(wp, wp->w_height + 1); frame_fix_height(wp); - win_comp_pos(); + (void)win_comp_pos(); } return true; -- cgit From d6247a575c12f413e21ff5e7e94a86214246579d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 7 Jun 2022 20:01:46 +0800 Subject: vim-patch:8.2.5066: lcs-leadmultispace https://github.com/vim/vim/commit/aca12fd89b082dd9cc12ae085a84f1805747bbdf --- src/nvim/window.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 5f4179944d..f429c493a7 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5085,6 +5085,7 @@ static void win_free(win_T *wp, tabpage_T *tp) clear_winopt(&wp->w_allbuf_opt); xfree(wp->w_p_lcs_chars.multispace); + xfree(wp->w_p_lcs_chars.leadmultispace); vars_clear(&wp->w_vars->dv_hashtab); // free all w: variables hash_init(&wp->w_vars->dv_hashtab); -- cgit From 429c40cce3fce3b5391afef8208d65a80a316018 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 13 Jun 2022 06:02:00 +0800 Subject: fix(buffer): disable buffer-updates before removing from window #18933 There can be other places that access window buffer info (e.g. `tabpagebuflist()`), so checking `w_closing` in `win_findbuf()` doesn't solve the crash in all cases, and may also cause Nvim's behavior to diverge from Vim. Fix #14998 --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index f429c493a7..e09a7cd97e 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -7297,7 +7297,7 @@ void win_findbuf(typval_T *argvars, list_T *list) int bufnr = tv_get_number(&argvars[0]); FOR_ALL_TAB_WINDOWS(tp, wp) { - if (!wp->w_closing && wp->w_buffer->b_fnum == bufnr) { + if (wp->w_buffer->b_fnum == bufnr) { tv_list_append_number(list, wp->handle); } } -- cgit From 663cbe2620278eae658895f82f3eb9bc89310e73 Mon Sep 17 00:00:00 2001 From: Shougo Date: Mon, 13 Jun 2022 18:40:51 +0900 Subject: feat: cmdheight=0 #16251 Fix https://github.com/neovim/neovim/issues/1004 Limitation: All outputs need hit-enter prompt. Related: https://github.com/neovim/neovim/pull/6732 https://github.com/neovim/neovim/pull/4382 --- src/nvim/window.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index e09a7cd97e..e08db2261b 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -907,7 +907,7 @@ void ui_ext_win_position(win_T *wp) int comp_col = (int)col - (east ? wp->w_width_outer : 0); comp_row += grid->comp_row; comp_col += grid->comp_col; - comp_row = MAX(MIN(comp_row, Rows - wp->w_height_outer - 1), 0); + comp_row = MAX(MIN(comp_row, Rows - wp->w_height_outer - (p_ch > 0 ? 1 : 0)), 0); comp_col = MAX(MIN(comp_col, Columns - wp->w_width_outer), 0); wp->w_winrow = comp_row; wp->w_wincol = comp_col; @@ -1144,6 +1144,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) if (flags & WSP_ROOM) { needed += p_wh - wmh1 + oldwin->w_winbar_height; } + if (p_ch < 1) { + needed += 1; // Adjust for cmdheight=0. + } if (flags & (WSP_BOT | WSP_TOP)) { minheight = frame_minheight(topframe, NOWIN) + need_status; available = topframe->fr_height; @@ -5501,7 +5504,7 @@ void win_setheight_win(int height, win_T *win) } } cmdline_row = row; - p_ch = MAX(Rows - cmdline_row, ui_has(kUIMessages) ? 0 : 1); + p_ch = MAX(Rows - cmdline_row, 0); curtab->tp_ch_used = p_ch; msg_row = row; msg_col = 0; @@ -5949,9 +5952,7 @@ void win_drag_status_line(win_T *dragwin, int offset) up = false; // Only dragging the last status line can reduce p_ch. room = Rows - cmdline_row; - if (curfr->fr_next == NULL) { - room -= 1; - } else { + if (curfr->fr_next != NULL) { room -= p_ch + global_stl_height(); } if (room < 0) { @@ -6008,7 +6009,7 @@ void win_drag_status_line(win_T *dragwin, int offset) clear_cmdline = true; } cmdline_row = row; - p_ch = MAX(Rows - cmdline_row, ui_has(kUIMessages) ? 0 : 1); + p_ch = MAX(Rows - cmdline_row, 0); curtab->tp_ch_used = p_ch; redraw_all_later(SOME_VALID); showmode(); -- cgit From 6130b4a84b41b71f4c0c58093a29585c6c67ff16 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 13 Jun 2022 20:20:34 +0800 Subject: vim-patch:8.2.1898: command modifier parsing always uses global cmdmod Problem: Command modifier parsing always uses global cmdmod. Solution: Pass in cmdmod_T to use. Rename struct fields consistently. https://github.com/vim/vim/commit/e10044015841711b989f9a898d427bcc1fdb4c32 --- src/nvim/window.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index e08db2261b..95796b29a1 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -569,7 +569,7 @@ wingotofile: case 'f': // CTRL-W gf: "gf" in a new tab page case 'F': // CTRL-W gF: "gF" in a new tab page - cmdmod.tab = tabpage_index(curtab) + 1; + cmdmod.cmod_tab = tabpage_index(curtab) + 1; nchar = xchar; goto wingotofile; case 't': // CTRL-W gt: go to next tab page @@ -985,7 +985,7 @@ int win_split(int size, int flags) } // Add flags from ":vertical", ":topleft" and ":botright". - flags |= cmdmod.split; + flags |= cmdmod.cmod_split; if ((flags & WSP_TOP) && (flags & WSP_BOT)) { emsg(_("E442: Can't split topleft and botright at the same time")); return FAIL; @@ -3882,7 +3882,7 @@ void close_others(int message, int forceit) continue; } if (!r) { - if (message && (p_confirm || cmdmod.confirm) && p_write) { + if (message && (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write) { dialog_changed(wp->w_buffer, false); if (!win_valid(wp)) { // autocommands messed wp up nextwp = firstwin; @@ -4136,10 +4136,10 @@ int win_new_tabpage(int after, char_u *filename) */ int may_open_tabpage(void) { - int n = (cmdmod.tab == 0) ? postponed_split_tab : cmdmod.tab; + int n = (cmdmod.cmod_tab == 0) ? postponed_split_tab : cmdmod.cmod_tab; if (n != 0) { - cmdmod.tab = 0; // reset it to avoid doing it twice + cmdmod.cmod_tab = 0; // reset it to avoid doing it twice postponed_split_tab = 0; return win_new_tabpage(n, NULL); } -- cgit From 0c6ad03c3f89c2ff26dfd2f2e861cf3ed09f6c87 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 15 Jun 2022 19:41:58 +0800 Subject: fix(ui): do not call showmode() when setting window height (#18969) --- src/nvim/window.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 95796b29a1..1487759d60 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5509,7 +5509,6 @@ void win_setheight_win(int height, win_T *win) msg_row = row; msg_col = 0; redraw_all_later(NOT_VALID); - showmode(); } } -- cgit From 5d6987210578f5f1c3151988b99a9411f9603374 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 8 Jun 2022 22:02:02 +0200 Subject: perf(ui): reduce allocation overhead when encoding "redraw" events Note for external UIs: Nvim can now emit multiple "redraw" event batches before a final "flush" event is received. To retain existing behavior, clients should make sure to update visible state at an explicit "flush" event, not just the end of a "redraw" batch of event. * Get rid of copy_object() blizzard in the auto-generated ui_event layer * Special case "grid_line" by encoding screen state directly to msgpack events with no intermediate API events. * Get rid of the arcane notion of referring to the screen as the "shell" * Array and Dictionary are kvec_t:s, so define them as such. * Allow kvec_t:s, such as Arrays and Dictionaries, to be allocated with a predetermined size within an arena. * Eliminate redundant capacity checking when filling such kvec_t:s with values. --- src/nvim/window.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 1487759d60..1a1f62f2c0 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -893,7 +893,7 @@ void ui_ext_win_position(win_T *wp) wp->w_grid_alloc.zindex = wp->w_float_config.zindex; if (ui_has(kUIMultigrid)) { - String anchor = cstr_to_string(float_anchor_str[c.anchor]); + String anchor = cstr_as_string((char *)float_anchor_str[c.anchor]); ui_call_win_float_pos(wp->w_grid_alloc.handle, wp->handle, anchor, grid->handle, row, col, c.focusable, wp->w_grid_alloc.zindex); @@ -967,8 +967,8 @@ static int check_split_disallowed(void) * "flags": * WSP_ROOM: require enough room for new window * WSP_VERT: vertical split. - * WSP_TOP: open window at the top-left of the shell (help window). - * WSP_BOT: open window at the bottom-right of the shell (quickfix window). + * WSP_TOP: open window at the top-left of the screen (help window). + * WSP_BOT: open window at the bottom-right of the screen (quickfix window). * WSP_HELP: creating the help window, keep layout snapshot * * return FAIL for failure, OK otherwise @@ -2499,7 +2499,7 @@ void close_windows(buf_T *buf, bool keep_curwin) redraw_tabline = true; if (h != tabline_height()) { - shell_new_rows(); + win_new_screen_rows(); } } @@ -2606,7 +2606,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev win_close_othertab(win, free_buf, prev_curtab); if (h != tabline_height()) { - shell_new_rows(); + win_new_screen_rows(); } } entering_window(curwin); @@ -4350,10 +4350,10 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a } if (curtab->tp_old_Rows != Rows || (old_off != firstwin->w_winrow)) { - shell_new_rows(); + win_new_screen_rows(); } if (curtab->tp_old_Columns != Columns && starting == 0) { - shell_new_columns(); // update window widths + win_new_screen_cols(); // update window widths } lastused_tabpage = old_curtab; @@ -5277,11 +5277,29 @@ static void frame_remove(frame_T *frp) } } -/* - * Called from win_new_shellsize() after Rows changed. - * This only does the current tab page, others must be done when made active. - */ -void shell_new_rows(void) +void win_new_screensize(void) +{ + static long old_Rows = 0; + static long old_Columns = 0; + + if (old_Rows != Rows) { + // If 'window' uses the whole screen, keep it using that. + // Don't change it when set with "-w size" on the command line. + if (p_window == old_Rows - 1 || (old_Rows == 0 && p_window == 0)) { + p_window = Rows - 1; + } + old_Rows = Rows; + win_new_screen_rows(); // update window sizes + } + if (old_Columns != Columns) { + old_Columns = Columns; + win_new_screen_cols(); // update window sizes + } +} +/// Called from win_new_screensize() after Rows changed. +/// +/// This only does the current tab page, others must be done when made active. +void win_new_screen_rows(void) { int h = (int)ROWS_AVAIL; @@ -5305,10 +5323,8 @@ void shell_new_rows(void) curtab->tp_ch_used = p_ch; } -/* - * Called from win_new_shellsize() after Columns changed. - */ -void shell_new_columns(void) +/// Called from win_new_screensize() after Columns changed. +void win_new_screen_cols(void) { if (firstwin == NULL) { // not initialized yet return; -- cgit From 7718b758461265d8966468c104ce5454538471e2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 23 Jun 2022 21:17:11 +0800 Subject: refactor: move some mapping-related code to a separate file (#19061) This marks the following Vim patches as ported: vim-patch:8.1.1785: map functionality mixed with character input Problem: Map functionality mixed with character input. Solution: Move the map functionality to a separate file. (Yegappan Lakshmanan, closes vim/vim#4740) Graduate the +localmap feature. https://github.com/vim/vim/commit/b66bab381c8ba71fd6e92327d1d34c6f8a65f2a7 vim-patch:8.2.3643: header for source file is outdated Problem: Header for source file is outdated. Solution: Make the header more accurate. (closes vim/vim#9186) https://github.com/vim/vim/commit/a3f83feb63eae5464a620ae793c002eb45f7a838 Also cherry-pick a change for mappings from patch 8.2.0807. Rename map_clear_mode() to do_mapclear(). --- src/nvim/window.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 1a1f62f2c0..9b9a2126ff 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -26,6 +26,7 @@ #include "nvim/globals.h" #include "nvim/hashtab.h" #include "nvim/main.h" +#include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/match.h" #include "nvim/memline.h" -- cgit From 5a490d838ed3288abcf45e16e6ab79c326a67c17 Mon Sep 17 00:00:00 2001 From: Shougo Date: Fri, 1 Jul 2022 10:59:50 +0900 Subject: cmdheight=0: fix bugs #18961 Continue of #16251 Fix #18953 Fix #18960 Fix #18958 Fix #18955 Fix #18970 Fix #18983 Fix #18995 Fix #19112 --- src/nvim/window.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 9b9a2126ff..9ac027d80f 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5560,9 +5560,10 @@ static void frame_setheight(frame_T *curfrp, int height) if (curfrp->fr_parent == NULL) { // topframe: can only change the command line if (height > ROWS_AVAIL) { - // If height is greater than the available space, try to create space for the frame by - // reducing 'cmdheight' if possible, while making sure `cmdheight` doesn't go below 1. - height = MIN(ROWS_AVAIL + (p_ch - 1), height); + // If height is greater than the available space, try to create space for + // the frame by reducing 'cmdheight' if possible, while making sure + // `cmdheight` doesn't go below 1. + height = MIN((p_ch > 0 ? ROWS_AVAIL + (p_ch - 1) : ROWS_AVAIL), height); } if (height > 0) { frame_new_height(curfrp, height, false, false); -- cgit From 0b15c019124965920c5f2df8c8ee75cd46311d27 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 2 Jul 2022 06:32:24 +0800 Subject: vim-patch:9.0.0017: accessing memory beyond the end of the line Problem: Accessing memory beyond the end of the line. Solution: Stop Visual mode when closing a window. https://github.com/vim/vim/commit/3d51ce18ab1be4f9f6061568a4e7fabf00b21794 --- src/nvim/window.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 9ac027d80f..38597b8b77 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2741,6 +2741,8 @@ int win_close(win_T *win, bool free_buf, bool force) * to be the last one left, return now. */ if (wp->w_buffer != curbuf) { + reset_VIsual_and_resel(); // stop Visual mode + other_buffer = true; win->w_closing = true; apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf); -- cgit From 3b8804571c565a91c9ce729bb487c7ba21b659e0 Mon Sep 17 00:00:00 2001 From: Dundar Goc Date: Tue, 28 Jun 2022 13:03:09 +0200 Subject: refactor: replace char_u Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/window.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 38597b8b77..ee0d19b1fe 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1554,9 +1554,9 @@ static void win_init(win_T *newp, win_T *oldp, int flags) copy_loclist_stack(oldp, newp); } newp->w_localdir = (oldp->w_localdir == NULL) - ? NULL : vim_strsave(oldp->w_localdir); + ? NULL : xstrdup(oldp->w_localdir); newp->w_prevdir = (oldp->w_prevdir == NULL) - ? NULL : vim_strsave(oldp->w_prevdir); + ? NULL : xstrdup(oldp->w_prevdir); // copy tagstack and folds for (i = 0; i < oldp->w_tagstacklen; i++) { @@ -4076,7 +4076,7 @@ int win_new_tabpage(int after, char_u *filename) } newtp->tp_localdir = old_curtab->tp_localdir - ? vim_strsave(old_curtab->tp_localdir) : NULL; + ? xstrdup(old_curtab->tp_localdir) : NULL; curtab = newtp; @@ -4899,8 +4899,7 @@ static void win_enter_ext(win_T *const wp, const int flags) void fix_current_dir(void) { // New directory is either the local directory of the window, tab or NULL. - char *new_dir = (char *)(curwin->w_localdir - ? curwin->w_localdir : curtab->tp_localdir); + char *new_dir = curwin->w_localdir ? curwin->w_localdir : curtab->tp_localdir; char cwd[MAXPATHL]; if (os_dirname((char_u *)cwd, MAXPATHL) != OK) { cwd[0] = NUL; @@ -6484,7 +6483,7 @@ char_u *grab_file_name(long count, linenr_T *file_lnum) *file_lnum = getdigits_long(&p, false, 0); } - return find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname); + return find_file_name_in_path(ptr, len, options, count, (char_u *)curbuf->b_ffname); } return file_name_at_cursor(options | FNAME_HYP, count, file_lnum); } @@ -6505,7 +6504,7 @@ char_u *grab_file_name(long count, linenr_T *file_lnum) char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum) { return file_name_in_line(get_cursor_line_ptr(), - curwin->w_cursor.col, options, count, curbuf->b_ffname, + curwin->w_cursor.col, options, count, (char_u *)curbuf->b_ffname, file_lnum); } -- cgit From 0612101c92f7043e47a1b4e80120582ff538c4f8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 7 Jul 2022 05:37:30 +0800 Subject: vim-patch:8.2.5043: can open a cmdline window from a substitute expression Problem: Can open a cmdline window from a substitute expression. Solution: Disallow opening a command line window when text or buffer is locked. https://github.com/vim/vim/commit/71223e2db87c2bf3b09aecb46266b56cda26191d --- src/nvim/window.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index ee0d19b1fe..771a85479d 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4571,12 +4571,8 @@ void win_goto(win_T *wp) { win_T *owp = curwin; - if (text_locked()) { + if (text_or_buf_locked()) { beep_flush(); - text_locked_msg(); - return; - } - if (curbuf_locked()) { return; } -- cgit From 99e829871173552374822ed922b785f0195f191c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 28 May 2022 10:40:07 +0800 Subject: fix(float): fix float window with winbar cannot have screen height --- src/nvim/window.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 771a85479d..6a80142c57 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -783,8 +783,8 @@ void win_config_float(win_T *wp, FloatConfig fconfig) } if (!ui_has(kUIMultigrid)) { - wp->w_height = MIN(wp->w_height, Rows - 1 - win_extra_height(wp)); - wp->w_width = MIN(wp->w_width, Columns - win_extra_width(wp)); + wp->w_height = MIN(wp->w_height, Rows - 1 - win_border_height(wp)); + wp->w_width = MIN(wp->w_width, Columns - win_border_width(wp)); } win_set_inner_size(wp); @@ -6330,18 +6330,18 @@ void win_set_inner_size(win_T *wp) terminal_check_size(wp->w_buffer->terminal); } - wp->w_height_outer = (wp->w_height_inner + win_extra_height(wp)); - wp->w_width_outer = (wp->w_width_inner + win_extra_width(wp)); + wp->w_height_outer = (wp->w_height_inner + win_border_height(wp) + wp->w_winbar_height); + wp->w_width_outer = (wp->w_width_inner + win_border_width(wp)); wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height; wp->w_wincol_off = wp->w_border_adj[3]; } -static int win_extra_height(win_T *wp) +static int win_border_height(win_T *wp) { - return wp->w_border_adj[0] + wp->w_border_adj[2] + wp->w_winbar_height; + return wp->w_border_adj[0] + wp->w_border_adj[2]; } -static int win_extra_width(win_T *wp) +static int win_border_width(win_T *wp) { return wp->w_border_adj[1] + wp->w_border_adj[3]; } -- cgit From 63f63dd2b7e06f872727d1d9d14ce177dc77ef83 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 28 May 2022 10:53:03 +0800 Subject: fix(float): fix glitch when making float window with border a split --- src/nvim/window.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 6a80142c57..ca99cc8cbc 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1266,8 +1266,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } else if (wp->w_floating) { new_frame(wp); wp->w_floating = false; - // non-floating window doesn't store float config. + // non-floating window doesn't store float config or have a border. wp->w_float_config = FLOAT_CONFIG_INIT; + memset(wp->w_border_adj, 0, sizeof(wp->w_border_adj)); } /* -- cgit From 63f6ecd4196680674504482475459d0ce6f49904 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 28 May 2022 12:01:44 +0800 Subject: fix(float): fix mouse drag position if float window turned to a split --- src/nvim/window.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index ca99cc8cbc..7895391697 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1941,7 +1941,7 @@ static void win_totop(int size, int flags) } else { // No longer a float, a non-multigrid UI shouldn't draw it as such ui_call_win_hide(curwin->w_grid_alloc.handle); - win_free_grid(curwin, false); + win_free_grid(curwin, true); } } else { // Remove the window and frame from the tree of frames. @@ -5179,8 +5179,7 @@ void win_free_grid(win_T *wp, bool reinit) } grid_free(&wp->w_grid_alloc); if (reinit) { - // if a float is turned into a split and back into a float, the grid - // data structure will be reused + // if a float is turned into a split, the grid data structure will be reused memset(&wp->w_grid_alloc, 0, sizeof(wp->w_grid_alloc)); } } -- cgit From 08235b6f2a668285347c7e2c1f1cdf81920cfecb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 14 Jul 2022 20:31:19 +0800 Subject: vim-patch:8.2.0921: CTRL-W T in cmdline window causes trouble Problem: CTRL-W T in cmdline window causes trouble. Solution: Disallow CTRL-W T in the cmdline window. Add more tests. (Naruhiko Nishino, closes vim/vim#6219) https://github.com/vim/vim/commit/4fdb8bd0546ac8d90560a4fad359a48667089d43 Test already passes in Nvim because of later patches. Move Test_cmdwin_jump_to_win() to the right place. --- src/nvim/window.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index 7895391697..cf10e635b6 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -331,6 +331,7 @@ newwindow: // move window to new tab page case 'T': + CHECK_CMDWIN; if (one_window(curwin)) { msg(_(m_onlyone)); } else { -- cgit From 591765c9151980ff4b5e700d384edf6fe0fdd5c5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 16 Jul 2022 11:34:19 +0800 Subject: vim-patch:8.2.1061: insufficient testing for src/window.c (#19384) Problem: Insufficient testing for src/window.c. Solution: Add more tests. (Yegappan Lakshmanan, closes vim/vim#6345) https://github.com/vim/vim/commit/5d3c9f8c2a0fc29ba4ac8e0f052378b64d9e3dd3 Cherry-pick test_tagjump.vim changes from patch 8.1.2373. --- src/nvim/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/window.c') diff --git a/src/nvim/window.c b/src/nvim/window.c index cf10e635b6..06231150d5 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1982,7 +1982,7 @@ void win_move_after(win_T *win1, win_T *win2) return; } - // may need move the status line, window bar, horizontal or vertical separator of the last + // may need to move the status line, window bar, horizontal or vertical separator of the last // window if (win1 == lastwin) { height = win1->w_prev->w_status_height; -- cgit