This patch improves upon the ":close" command by attempting to have it
respect the 'winfixheight' and 'winfixwidth' settings whenever possible.

Two files are attached:
  * example.vim - gives a summary of the bug
  * fix_wf_close.patch - fixes both cases of the bug ('wfw' for 'wfh')

Tests are included to ensure that both versions of the problem remain
fixed.  The example shows the problem using 'wfw', and the similar case
for 'wfh' is then easy to deduce.

Best,
Jason

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Attachment: example.vim
Description: Binary data

>From 9002f09dc8f89ba67d8b45e8ec3c5cb7b78dcecb Mon Sep 17 00:00:00 2001
From: Jason Franklin <[email protected]>
Date: Fri, 4 May 2018 09:07:46 -0400
Subject: [PATCH] Make win_altframe() obey 'wfw' and 'wfh'

---
 src/testdir/test_winbuf_close.vim | 38 +++++++++++++++++++++++++++++++
 src/window.c                      | 48 +++++++++++++++++++++++++++------------
 2 files changed, 71 insertions(+), 15 deletions(-)

diff --git a/src/testdir/test_winbuf_close.vim b/src/testdir/test_winbuf_close.vim
index ed64dd7..408b049 100644
--- a/src/testdir/test_winbuf_close.vim
+++ b/src/testdir/test_winbuf_close.vim
@@ -122,3 +122,41 @@ func Test_winbuf_close()
   call delete('Xtest2')
   call delete('Xtest3')
 endfunc
+
+" Test that ":close" will respect 'winfixheight' when possible.
+func Test_winfixheight_on_close()
+    %bwipeout!
+    set nosplitbelow nosplitright
+
+    split | split | vsplit
+
+    $wincmd w
+    setlocal winfixheight
+    let l:height = winheight(0)
+
+    3close
+
+    call assert_equal(l:height, winheight(0))
+
+    %bwipeout!
+    setlocal nowinfixheight
+endfunc
+
+" Test that ":close" will respect 'winfixwidth' when possible.
+func Test_winfixwidth_on_close()
+    %bwipeout!
+    set nosplitbelow nosplitright
+
+    vsplit | vsplit | split
+
+    $wincmd w
+    setlocal winfixwidth
+    let l:width = winwidth(0)
+
+    3close
+
+    call assert_equal(l:width, winwidth(0))
+
+    %bwipeout!
+    setlocal nowinfixwidth
+endfunction
diff --git a/src/window.c b/src/window.c
index 333663b..1d93586 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2740,12 +2740,14 @@ winframe_remove(
 }
 
 /*
- * Find out which frame is going to get the freed up space when "win" is
- * closed.
- * if 'splitbelow'/'splitleft' the space goes to the window above/left.
- * if 'nosplitbelow'/'nosplitleft' the space goes to the window below/right.
- * This makes opening a window and closing it immediately keep the same window
- * layout.
+ * Return a pointer to the frame that will receive the empty screen space that
+ * is left over after "win" is closed.
+ *
+ * If 'splitbelow' or 'splitright' is set, the space goes above or to the left
+ * by default.  Otherwise, the free space goes below or to the right.  The
+ * result is that opening a window and then immediately closing it will
+ * preserve the initial window layout.  The 'wfh' and 'wfw' settings are
+ * respected when possible.
  */
     static frame_T *
 win_altframe(
@@ -2753,20 +2755,36 @@ win_altframe(
     tabpage_T	*tp)		/* tab page "win" is in, NULL for current */
 {
     frame_T	*frp;
-    int		b;
+    frame_T	*other_fr, *target_fr;
 
     if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin)
-	/* Last window in this tab page, will go to next tab page. */
 	return alt_tabpage()->tp_curwin->w_frame;
 
     frp = win->w_frame;
-    if (frp->fr_parent != NULL && frp->fr_parent->fr_layout == FR_ROW)
-	b = p_spr;
-    else
-	b = p_sb;
-    if ((!b && frp->fr_next != NULL) || frp->fr_prev == NULL)
-	return frp->fr_next;
-    return frp->fr_prev;
+
+    if (frp->fr_next == NULL || frp->fr_prev == NULL)
+	return frp->fr_next ? frp->fr_next : frp->fr_prev;
+
+    other_fr  = frp->fr_prev;
+    target_fr = frp->fr_next;
+
+    if (p_spr || p_sb) {
+	other_fr  = frp->fr_next;
+	target_fr = frp->fr_prev;
+    }
+
+    /* If 'wfh' or 'wfw' is set for the target and not for the alternate
+     * window, reverse the selection. */
+    if (frp->fr_parent != NULL && frp->fr_parent->fr_layout == FR_ROW) {
+	if (frame_fixed_width(target_fr) && !frame_fixed_width(other_fr))
+	    target_fr = other_fr;
+    }
+    else {
+	if (frame_fixed_height(target_fr) && !frame_fixed_height(other_fr))
+	    target_fr = other_fr;
+    }
+
+    return target_fr;
 }
 
 /*
-- 
2.7.4

Raspunde prin e-mail lui