]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1831: stray vseps in right-most 'winfixwidth' window v9.1.1831
authorSean Dewar <6256228+seandewar@users.noreply.github.com>
Sun, 5 Oct 2025 17:00:58 +0000 (17:00 +0000)
committerChristian Brabandt <cb@256bit.org>
Sun, 5 Oct 2025 17:00:58 +0000 (17:00 +0000)
Problem:  vertical separator of 'winfixwidth' windows may remain if they
          become right-most windows from closing windows to the right.
Solution: Don't implicitly rely on frame_new_width to fix vseps, as the
          call may be skipped for 'winfixwidth' windows to preserve
          their width; do it explicitly in winframe_remove (Sean Dewar).

Note that I prefer win_new_width here over setting w_width directly, which
would've previously been done by win_split_ins after frame_add_vsep, as this
wasn't true for winframe_remove.

Though the equivalent issue of bottom 'winfixheight' windows leaving stray
statuslines with &ls=0 doesn't seem to exist, test it anyway.

closes: #18481

Signed-off-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/testdir/dumps/Test_winfixsize_vsep_statusline_1.dump [new file with mode: 0644]
src/testdir/dumps/Test_winfixsize_vsep_statusline_2.dump [new file with mode: 0644]
src/testdir/test_window_cmd.vim
src/version.c
src/window.c

diff --git a/src/testdir/dumps/Test_winfixsize_vsep_statusline_1.dump b/src/testdir/dumps/Test_winfixsize_vsep_statusline_1.dump
new file mode 100644 (file)
index 0000000..60dbb3b
--- /dev/null
@@ -0,0 +1,8 @@
+> +0&#ffffff0@35||+1&&| +0&&@37
+|~+0#4040ff13&| @34||+1#0000000&|~+0#4040ff13&| @36
+|~| @34||+1#0000000&|~+0#4040ff13&| @36
+|~| @34||+1#0000000&|~+0#4040ff13&| @36
+|~| @34||+1#0000000&|~+0#4040ff13&| @36
+|~| @34||+1#0000000&|~+0#4040ff13&| @36
+|[+3#0000000&|N|o| |N|a|m|e|]| @8|0|,|0|-|1| @9|A|l@1| |[+1&&|N|o| |N|a|m|e|]| @10|0|,|0|-|1| @9|A|l@1
+|:+0&&|q|u|i|t| @69
diff --git a/src/testdir/dumps/Test_winfixsize_vsep_statusline_2.dump b/src/testdir/dumps/Test_winfixsize_vsep_statusline_2.dump
new file mode 100644 (file)
index 0000000..f22090b
--- /dev/null
@@ -0,0 +1,8 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|[+3#0000000&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1
+| +0&&@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|:+0#0000000&|q|u|i|t| @51|0|,|0|-|1| @8|A|l@1| 
index 2e00ab453888d7dccbb7df1c8ac5d74c8de951f0..c00f60e394ac3d1a05698803e29e7cd3db610328 100644 (file)
@@ -2305,4 +2305,50 @@ func Test_winfixsize_positions()
   %bwipe
 endfunc
 
+func Test_winfixsize_vsep_statusline()
+  CheckScreendump
+  let lines =<< trim END
+    set noequalalways splitbelow splitright
+    vsplit
+    setlocal winfixwidth
+    vsplit
+    func SetupWfh()
+      set laststatus=0
+      only
+      split
+      set winfixheight
+      split
+    endfunc
+  END
+  call writefile(lines, 'XTestWinfixsizeVsepStatusline', 'D')
+  let buf = RunVimInTerminal('-S XTestWinfixsizeVsepStatusline', #{rows: 8})
+
+  call term_sendkeys(buf, ":echo winwidth(1) winwidth(2) winwidth(3)\n")
+  call WaitForAssert({-> assert_match('^16 37 20\>', term_getline(buf, 8))})
+
+  call term_sendkeys(buf, ":quit\n")
+  call VerifyScreenDump(buf, 'Test_winfixsize_vsep_statusline_1', {})
+
+  " Reported widths should be consistent with the screen dump.
+  call term_sendkeys(buf, ":echo winwidth(1) winwidth(2)\n")
+  " (May be better if 'wfw' window remains at 37 columns, but the resize is
+  " consistent with how things currently work for 'winfix*' windows)
+  call WaitForAssert({-> assert_match('^36 38\>', term_getline(buf, 8))})
+
+  " For good measure, also check bottom-most 'winfixheight' windows don't leave
+  " stray statuslines with &laststatus=0.
+  call term_sendkeys(buf,
+        \ ":call SetupWfh() | echo winheight(1) winheight(2) winheight(3)\n")
+  call WaitForAssert({-> assert_match('^1 3 1\>', term_getline(buf, 8))})
+
+  call term_sendkeys(buf, ":quit\n")
+  call VerifyScreenDump(buf, 'Test_winfixsize_vsep_statusline_2', {})
+
+  call term_sendkeys(buf, ":echo winheight(1) winheight(2)\n")
+  " (Likewise, may be better if 'wfh' window remains at 3 rows)
+  call WaitForAssert({-> assert_match('^2 4\>', term_getline(buf, 8))})
+
+  call StopVimInTerminal(buf)
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 8e65ddf1a2a8d18ab7e607b5f57f81a8e496308b..27edfb16ce9026d13ff3744c497feab11f39c512 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1831,
 /**/
     1830,
 /**/
index f071a0e7d77596c85f2a42dbd9caf474a837f9df..364b532b15ccd1f5331770d3d7d659124de81d74 100644 (file)
@@ -32,7 +32,7 @@ static int frame_fixed_height(frame_T *frp);
 static int frame_fixed_width(frame_T *frp);
 static void frame_add_statusline(frame_T *frp);
 static void frame_new_width(frame_T *topfrp, int width, int leftfirst, int wfw);
-static void frame_add_vsep(frame_T *frp);
+static void frame_set_vsep(frame_T *frp, int add);
 static int frame_minwidth(frame_T *topfrp, win_T *next_curwin);
 static void frame_fix_width(win_T *wp);
 static int win_alloc_firstwin(win_T *oldwin);
@@ -1363,7 +1363,7 @@ win_split_ins(
        if (flags & (WSP_TOP | WSP_BOT))
        {
            if (flags & WSP_BOT)
-               frame_add_vsep(curfrp);
+               frame_set_vsep(curfrp, TRUE);
            // Set width of neighbor frame
            frame_new_width(curfrp, curfrp->fr_width
                     - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP,
@@ -3577,6 +3577,11 @@ winframe_remove(
     frp2 = win_altframe(win, tp);
     wp = frame2win(frp2);
 
+    // If this is a rightmost window, remove vertical separators to the left.
+    if (win->w_vsep_width == 0 && frp_close->fr_parent->fr_layout == FR_ROW &&
+           frp_close->fr_prev != NULL)
+       frame_set_vsep(frp_close->fr_prev, FALSE);
+
     // Remove this frame from the list of frames.
     frame_remove(frp_close);
 
@@ -3742,7 +3747,7 @@ winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr)
     // Vertical separators to the left may have been lost.  Restore them.
     if (wp->w_vsep_width == 0
            && frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL)
-       frame_add_vsep(frp->fr_prev);
+       frame_set_vsep(frp->fr_prev, TRUE);
 
     // Statuslines above may have been lost.  Restore them.
     if (wp->w_status_height == 0
@@ -4223,29 +4228,34 @@ frame_new_width(
 }
 
 /*
- * Add the vertical separator to windows at the right side of "frp".
+ * Add or remove the vertical separator of windows to the right side of "frp".
  * Note: Does not check if there is room!
  */
     static void
-frame_add_vsep(frame_T *frp)
+frame_set_vsep(frame_T *frp, int add)
 {
     win_T      *wp;
 
     if (frp->fr_layout == FR_LEAF)
     {
        wp = frp->fr_win;
-       if (wp->w_vsep_width == 0)
+       if (add && wp->w_vsep_width == 0)
        {
            if (wp->w_width > 0)        // don't make it negative
-               --wp->w_width;
+               win_new_width(wp, wp->w_width - 1);
            wp->w_vsep_width = 1;
        }
+       else if (!add && wp->w_vsep_width == 1)
+       {
+           win_new_width(wp, wp->w_width + 1);
+           wp->w_vsep_width = 0;
+       }
     }
     else if (frp->fr_layout == FR_COL)
     {
        // Handle all the frames in the column.
        FOR_ALL_FRAMES(frp, frp->fr_child)
-           frame_add_vsep(frp);
+           frame_set_vsep(frp, add);
     }
     else // frp->fr_layout == FR_ROW
     {
@@ -4253,7 +4263,7 @@ frame_add_vsep(frame_T *frp)
        frp = frp->fr_child;
        while (frp->fr_next != NULL)
            frp = frp->fr_next;
-       frame_add_vsep(frp);
+       frame_set_vsep(frp, add);
     }
 }