diff src/window.c @ 779:fb913578cbf5

updated for version 7.0228
author vimboss
date Sat, 18 Mar 2006 21:30:13 +0000
parents 59971e227f8c
children b5aed52a4881
line wrap: on
line diff
--- a/src/window.c
+++ b/src/window.c
@@ -36,8 +36,9 @@ static int frame_has_win __ARGS((frame_T
 static void frame_new_height __ARGS((frame_T *topfrp, int height, int topfirst, int wfh));
 static int frame_fixed_height __ARGS((frame_T *frp));
 #ifdef FEAT_VERTSPLIT
+static int frame_fixed_width __ARGS((frame_T *frp));
 static void frame_add_statusline __ARGS((frame_T *frp));
-static void frame_new_width __ARGS((frame_T *topfrp, int width, int leftfirst));
+static void frame_new_width __ARGS((frame_T *topfrp, int width, int leftfirst, int wfw));
 static void frame_add_vsep __ARGS((frame_T *frp));
 static int frame_minwidth __ARGS((frame_T *topfrp, win_T *next_curwin));
 static void frame_fix_width __ARGS((win_T *wp));
@@ -723,6 +724,12 @@ win_split_ins(size, flags, newwin, dir)
 	/* if it doesn't fit in the current window, need win_equal() */
 	if (oldwin->w_width - new_size - 1 < p_wmw)
 	    do_equal = TRUE;
+
+	/* We don't like to take lines for the new window from a
+	 * 'winfixwidth' window.  Take them from a window to the left or right
+	 * instead, if possible. */
+	if (oldwin->w_p_wfw)
+	    win_setwidth_win(oldwin->w_width + new_size, oldwin);
     }
     else
 #endif
@@ -937,10 +944,11 @@ win_split_ins(size, flags, newwin, dir)
 		frame_add_vsep(curfrp);
 	    /* Set width of neighbor frame */
 	    frame_new_width(curfrp, curfrp->fr_width
-		    - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP);
+		     - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP,
+								       FALSE);
 	}
 	else
-	    oldwin->w_width -= new_size + 1;
+	    win_new_width(oldwin, oldwin->w_width - (new_size + 1));
 	if (before)	/* new window left of current one */
 	{
 	    wp->w_wincol = oldwin->w_wincol;
@@ -1588,7 +1596,7 @@ win_equal_rec(next_curwin, current, topf
 	    frame_new_height(topfr, height, FALSE, FALSE);
 #ifdef FEAT_VERTSPLIT
 	    topfr->fr_win->w_wincol = col;
-	    frame_new_width(topfr, width, FALSE);
+	    frame_new_width(topfr, width, FALSE, FALSE);
 #endif
 	    redraw_all_later(CLEAR);
 	}
@@ -1610,8 +1618,13 @@ win_equal_rec(next_curwin, current, topf
 	    else
 		extra_sep = 0;
 	    totwincount = (n + extra_sep) / (p_wmw + 1);
-
-	    /* Compute room available for windows other than "next_curwin" */
+	    has_next_curwin = frame_has_win(topfr, next_curwin);
+
+	    /*
+	     * Compute width for "next_curwin" window and room available for
+	     * other windows.
+	     * "m" is the minimal width when counting p_wiw for "next_curwin".
+	     */
 	    m = frame_minwidth(topfr, next_curwin);
 	    room = width - m;
 	    if (room < 0)
@@ -1619,18 +1632,56 @@ win_equal_rec(next_curwin, current, topf
 		next_curwin_size = p_wiw + room;
 		room = 0;
 	    }
-	    else if (n == m)		/* doesn't contain curwin */
-		next_curwin_size = 0;
 	    else
 	    {
-		next_curwin_size = (room + p_wiw + (totwincount - 1) * p_wmw
+		next_curwin_size = -1;
+		for (fr = topfr->fr_child; fr != NULL; fr = fr->fr_next)
+		{
+		    /* If 'winfixwidth' set keep the window width if
+		     * possible.
+		     * Watch out for this window being the next_curwin. */
+		    if (frame_fixed_width(fr))
+		    {
+			n = frame_minwidth(fr, NOWIN);
+			new_size = fr->fr_width;
+			if (frame_has_win(fr, next_curwin))
+			{
+			    room += p_wiw - p_wmw;
+			    next_curwin_size = 0;
+			    if (new_size < p_wiw)
+				new_size = p_wiw;
+			}
+			else
+			    /* These windows don't use up room. */
+			    totwincount -= (n + (fr->fr_next == NULL
+					      ? extra_sep : 0)) / (p_wmw + 1);
+			room -= new_size - n;
+			if (room < 0)
+			{
+			    new_size += room;
+			    room = 0;
+			}
+			fr->fr_newwidth = new_size;
+		    }
+		}
+		if (next_curwin_size == -1)
+		{
+		    if (!has_next_curwin)
+			next_curwin_size = 0;
+		    else if (totwincount > 1
+			    && (room + (totwincount - 2))
+						  / (totwincount - 1) > p_wiw)
+		    {
+			next_curwin_size = (room + p_wiw + totwincount * p_wmw
 					   + (totwincount - 1)) / totwincount;
-		if (next_curwin_size  > p_wiw)
-		    room -= next_curwin_size - p_wiw;
-		else
-		    next_curwin_size = p_wiw;
+			room -= next_curwin_size - p_wiw;
+		    }
+		    else
+			next_curwin_size = p_wiw;
+		}
 	    }
-	    if (n != m)
+
+	    if (has_next_curwin)
 		--totwincount;		/* don't count curwin */
 	}
 
@@ -1643,6 +1694,11 @@ win_equal_rec(next_curwin, current, topf
 		new_size = width;
 	    else if (dir == 'v')
 		new_size = fr->fr_width;
+	    else if (frame_fixed_width(fr))
+	    {
+		new_size = fr->fr_newwidth;
+		wincount = 0;	    /* doesn't count as a sizeable window */
+	    }
 	    else
 	    {
 		/* Compute the maximum number of windows horiz. in "fr". */
@@ -1650,30 +1706,37 @@ win_equal_rec(next_curwin, current, topf
 		wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
 								/ (p_wmw + 1);
 		m = frame_minwidth(fr, next_curwin);
-		if (n != m)	    /* don't count next_curwin */
+		if (has_next_curwin)
+		    hnc = frame_has_win(fr, next_curwin);
+		else
+		    hnc = FALSE;
+		if (hnc)	    /* don't count next_curwin */
 		    --wincount;
-		new_size = (wincount * room + ((unsigned)totwincount >> 1))
+		if (totwincount == 0)
+		    new_size = room;
+		else
+		    new_size = (wincount * room + ((unsigned)totwincount >> 1))
 								/ totwincount;
-		if (n != m)	    /* add next_curwin size */
+		if (hnc)	    /* add next_curwin size */
 		{
 		    next_curwin_size -= p_wiw - (m - n);
 		    new_size += next_curwin_size;
+		    room -= new_size - next_curwin_size;
 		}
+		else
+		    room -= new_size;
+		new_size += n;
 	    }
 
-	    /* Skip frame that is full height when splitting or closing a
+	    /* Skip frame that is full width when splitting or closing a
 	     * window, unless equalizing all frames. */
 	    if (!current || dir != 'v' || topfr->fr_parent != NULL
 		    || (new_size != fr->fr_width)
 		    || frame_has_win(fr, next_curwin))
 		win_equal_rec(next_curwin, current, fr, dir, col, row,
-							new_size + n, height);
-	    col += new_size + n;
-	    width -= new_size + n;
-	    if (n != m)	    /* contains curwin */
-		room -= new_size - next_curwin_size;
-	    else
-		room -= new_size;
+							    new_size, height);
+	    col += new_size;
+	    width -= new_size;
 	    totwincount -= wincount;
 	}
     }
@@ -2172,7 +2235,7 @@ winframe_remove(win, dirp, tp)
     frame_T	*frp, *frp2, *frp3;
     frame_T	*frp_close = win->w_frame;
     win_T	*wp;
-    int		old_height = 0;
+    int		old_size = 0;
 
     /*
      * If there is only one window there is nothing to remove.
@@ -2199,18 +2262,27 @@ winframe_remove(win, dirp, tp)
 	if (frp2->fr_win != NULL
 		&& (frp2->fr_next != NULL || frp2->fr_prev != NULL)
 		&& frp2->fr_win->w_p_wfh)
-	    old_height = frp2->fr_win->w_height;
+	    old_size = frp2->fr_win->w_height;
 	frame_new_height(frp2, frp2->fr_height + frp_close->fr_height,
 			    frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
-	if (old_height != 0)
-	    win_setheight_win(old_height, frp2->fr_win);
+	if (old_size != 0)
+	    win_setheight_win(old_size, frp2->fr_win);
 #ifdef FEAT_VERTSPLIT
 	*dirp = 'v';
     }
     else
     {
+	/* When 'winfixwidth' is set, remember its old size and restore
+	 * it later (it's a simplistic solution...).  Don't do this if the
+	 * window will occupy the full width of the screen. */
+	if (frp2->fr_win != NULL
+		&& (frp2->fr_next != NULL || frp2->fr_prev != NULL)
+		&& frp2->fr_win->w_p_wfw)
+	    old_size = frp2->fr_win->w_width;
 	frame_new_width(frp2, frp2->fr_width + frp_close->fr_width,
-				   frp2 == frp_close->fr_next ? TRUE : FALSE);
+			    frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
+	if (old_size != 0)
+	    win_setwidth_win(old_size, frp2->fr_win);
 	*dirp = 'h';
     }
 #endif
@@ -2390,7 +2462,7 @@ frame_new_height(topfrp, height, topfirs
 	while (frp != NULL);
     }
 #endif
-    else
+    else    /* fr_layout == FR_COL */
     {
 	/* Complicated case: Resize a column of frames.  Resize the bottom
 	 * frame first, frames above that when needed. */
@@ -2491,6 +2563,36 @@ frame_fixed_height(frp)
 
 #ifdef FEAT_VERTSPLIT
 /*
+ * Return TRUE if width of frame "frp" should not be changed because of
+ * the 'winfixwidth' option.
+ */
+    static int
+frame_fixed_width(frp)
+    frame_T	*frp;
+{
+    /* frame with one window: fixed width if 'winfixwidth' set. */
+    if (frp->fr_win != NULL)
+	return frp->fr_win->w_p_wfw;
+
+    if (frp->fr_layout == FR_COL)
+    {
+	/* The frame is fixed width if one of the frames in the row is fixed
+	 * width. */
+	for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+	    if (frame_fixed_width(frp))
+		return TRUE;
+	return FALSE;
+    }
+
+    /* frp->fr_layout == FR_ROW: The frame is fixed width if all of the
+     * frames in the row are fixed width. */
+    for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+	if (!frame_fixed_width(frp))
+	    return FALSE;
+    return TRUE;
+}
+
+/*
  * Add a status line to windows at the bottom of "frp".
  * Note: Does not check if there is room!
  */
@@ -2530,10 +2632,12 @@ frame_add_statusline(frp)
  * May remove separator line for windows at the right side (for win_close()).
  */
     static void
-frame_new_width(topfrp, width, leftfirst)
+frame_new_width(topfrp, width, leftfirst, wfw)
     frame_T	*topfrp;
     int		width;
     int		leftfirst;	/* resize leftmost contained frame first */
+    int		wfw;		/* obey 'winfixwidth' when there is a choice;
+				   may cause the width not to be set */
 {
     frame_T	*frp;
     int		extra_cols;
@@ -2554,20 +2658,45 @@ frame_new_width(topfrp, width, leftfirst
     }
     else if (topfrp->fr_layout == FR_COL)
     {
-	/* All frames in this column get the same new width. */
-	for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
-	    frame_new_width(frp, width, leftfirst);
+	do
+	{
+	    /* All frames in this column get the same new width. */
+	    for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
+	    {
+		frame_new_width(frp, width, leftfirst, wfw);
+		if (frp->fr_width > width)
+		{
+		    /* Could not fit the windows, make whole column wider. */
+		    width = frp->fr_width;
+		    break;
+		}
+	    }
+	} while (frp != NULL);
     }
     else    /* fr_layout == FR_ROW */
     {
 	/* Complicated case: Resize a row of frames.  Resize the rightmost
 	 * frame first, frames left of it when needed. */
 
-	/* Find the rightmost frame of this row */
 	frp = topfrp->fr_child;
+	if (wfw)
+	    /* Advance past frames with one window with 'wfw' set. */
+	    while (frame_fixed_width(frp))
+	    {
+		frp = frp->fr_next;
+		if (frp == NULL)
+		    return;	    /* no frame without 'wfw', give up */
+	    }
 	if (!leftfirst)
+	{
+	    /* Find the rightmost frame of this row */
 	    while (frp->fr_next != NULL)
 		frp = frp->fr_next;
+	    if (wfw)
+		/* Advance back for frames with one window with 'wfw' set. */
+		while (frame_fixed_width(frp))
+		    frp = frp->fr_prev;
+	}
 
 	extra_cols = width - topfrp->fr_width;
 	if (extra_cols < 0)
@@ -2579,23 +2708,35 @@ frame_new_width(topfrp, width, leftfirst
 		if (frp->fr_width + extra_cols < w)
 		{
 		    extra_cols += frp->fr_width - w;
-		    frame_new_width(frp, w, leftfirst);
+		    frame_new_width(frp, w, leftfirst, wfw);
 		}
 		else
 		{
-		    frame_new_width(frp, frp->fr_width + extra_cols, leftfirst);
+		    frame_new_width(frp, frp->fr_width + extra_cols,
+							      leftfirst, wfw);
 		    break;
 		}
 		if (leftfirst)
-		    frp = frp->fr_next;
+		{
+		    do
+			frp = frp->fr_next;
+		    while (wfw && frp != NULL && frame_fixed_width(frp));
+		}
 		else
-		    frp = frp->fr_prev;
+		{
+		    do
+			frp = frp->fr_prev;
+		    while (wfw && frp != NULL && frame_fixed_width(frp));
+		}
+		/* Increase "width" if we could not reduce enough frames. */
+		if (frp == NULL)
+		    width -= extra_cols;
 	    }
 	}
 	else if (extra_cols > 0)
 	{
 	    /* increase width of rightmost frame */
-	    frame_new_width(frp, frp->fr_width + extra_cols, leftfirst);
+	    frame_new_width(frp, frp->fr_width + extra_cols, leftfirst, wfw);
 	}
     }
     topfrp->fr_width = width;
@@ -3689,7 +3830,7 @@ win_enter_ext(wp, undo_sync, curwin_inva
 
 #ifdef FEAT_VERTSPLIT
     /* set window width to desired minimal value */
-    if (curwin->w_width < p_wiw)
+    if (curwin->w_width < p_wiw && !curwin->w_p_wfw)
 	win_setwidth((int)p_wiw);
 #endif
 
@@ -4012,7 +4153,8 @@ shell_new_rows()
 #ifdef FEAT_WINDOWS
     if (h < frame_minheight(topframe, NULL))
 	h = frame_minheight(topframe, NULL);
-    /* First try setting the heights of windows without 'winfixheight'.  If
+
+    /* First try setting the heights of windows with 'winfixheight'.  If
      * that doesn't result in the right height, forget about that option. */
     frame_new_height(topframe, h, FALSE, TRUE);
     if (topframe->fr_height != h)
@@ -4045,7 +4187,13 @@ shell_new_columns()
 {
     if (firstwin == NULL)	/* not initialized yet */
 	return;
-    frame_new_width(topframe, (int)Columns, FALSE);
+
+    /* First try setting the widths of windows with 'winfixwidth'.  If that
+     * doesn't result in the right width, forget about that option. */
+    frame_new_width(topframe, (int)Columns, FALSE, TRUE);
+    if (topframe->fr_width != Columns)
+	frame_new_width(topframe, (int)Columns, FALSE, FALSE);
+
     (void)win_comp_pos();		/* recompute w_winrow and w_wincol */
 #if 0
     /* Disabled: don't want making the screen smaller make a window larger. */
@@ -4480,6 +4628,7 @@ frame_setwidth(curfrp, width)
     int		run;
     frame_T	*frp;
     int		w;
+    int		room_reserved;
 
     /* If the width already is the desired value, nothing to do. */
     if (curfrp->fr_width == width)
@@ -4511,9 +4660,14 @@ frame_setwidth(curfrp, width)
 	for (run = 1; run <= 2; ++run)
 	{
 	    room = 0;
+	    room_reserved = 0;
 	    for (frp = curfrp->fr_parent->fr_child; frp != NULL;
 							   frp = frp->fr_next)
 	    {
+		if (frp != curfrp
+			&& frp->fr_win != NULL
+			&& frp->fr_win->w_p_wfw)
+		    room_reserved += frp->fr_width;
 		room += frp->fr_width;
 		if (frp != curfrp)
 		    room -= frame_minwidth(frp, NULL);
@@ -4531,17 +4685,25 @@ frame_setwidth(curfrp, width)
 		 + frame_minwidth(curfrp->fr_parent, NOWIN) - (int)p_wmw - 1);
 	}
 
-
 	/*
 	 * Compute the number of lines we will take from others frames (can be
 	 * negative!).
 	 */
 	take = width - curfrp->fr_width;
 
+	/* If there is not enough room, also reduce the width of a window
+	 * with 'winfixwidth' set. */
+	if (width > room - room_reserved)
+	    room_reserved = room - width;
+	/* If there is only a 'winfixwidth' window and making the
+	 * window smaller, need to make the other window narrower. */
+	if (take < 0 && room - curfrp->fr_width < room_reserved)
+	    room_reserved = 0;
+
 	/*
 	 * set the current frame to the new width
 	 */
-	frame_new_width(curfrp, width, FALSE);
+	frame_new_width(curfrp, width, FALSE, FALSE);
 
 	/*
 	 * First take lines from the frames right of the current frame.  If
@@ -4557,15 +4719,34 @@ frame_setwidth(curfrp, width)
 	    while (frp != NULL && take != 0)
 	    {
 		w = frame_minwidth(frp, NULL);
-		if (frp->fr_width - take < w)
+		if (room_reserved > 0
+			&& frp->fr_win != NULL
+			&& frp->fr_win->w_p_wfw)
 		{
-		    take -= frp->fr_width - w;
-		    frame_new_width(frp, w, FALSE);
+		    if (room_reserved >= frp->fr_width)
+			room_reserved -= frp->fr_width;
+		    else
+		    {
+			if (frp->fr_width - room_reserved > take)
+			    room_reserved = frp->fr_width - take;
+			take -= frp->fr_width - room_reserved;
+			frame_new_width(frp, room_reserved, FALSE, FALSE);
+			room_reserved = 0;
+		    }
 		}
 		else
 		{
-		    frame_new_width(frp, frp->fr_width - take, FALSE);
-		    take = 0;
+		    if (frp->fr_width - take < w)
+		    {
+			take -= frp->fr_width - w;
+			frame_new_width(frp, w, FALSE, FALSE);
+		    }
+		    else
+		    {
+			frame_new_width(frp, frp->fr_width - take,
+								FALSE, FALSE);
+			take = 0;
+		    }
 		}
 		if (run == 0)
 		    frp = frp->fr_next;
@@ -4811,7 +4992,7 @@ win_drag_vsep_line(dragwin, offset)
 	return;
 
     /* grow frame fr by offset lines */
-    frame_new_width(fr, fr->fr_width + offset, left);
+    frame_new_width(fr, fr->fr_width + offset, left, FALSE);
 
     /* shrink other frames: current and at the left or at the right */
     if (left)
@@ -4825,11 +5006,11 @@ win_drag_vsep_line(dragwin, offset)
 	if (fr->fr_width - offset <= n)
 	{
 	    offset -= fr->fr_width - n;
-	    frame_new_width(fr, n, !left);
+	    frame_new_width(fr, n, !left, FALSE);
 	}
 	else
 	{
-	    frame_new_width(fr, fr->fr_width - offset, !left);
+	    frame_new_width(fr, fr->fr_width - offset, !left, FALSE);
 	    break;
 	}
 	if (left)
@@ -5762,7 +5943,7 @@ restore_snapshot_rec(sn, fr)
     {
 	frame_new_height(fr, fr->fr_height, FALSE, FALSE);
 # ifdef FEAT_VERTSPLIT
-	frame_new_width(fr, fr->fr_width, FALSE);
+	frame_new_width(fr, fr->fr_width, FALSE, FALSE);
 # endif
 	wp = sn->fr_win;
     }