changeset 25792:80e84cb91f1e

(window_min_size): Add parameter ignore_fixed_p. (change_window_height): Call window_min_size with new parameter. (shrink_window_lowest_first, save_restore_orig_size, grow_mini_window, shrink_mini_window): New. (make_window, replace_window): Initialize orig_top and orig_height. (enlarge_window): Renamed from change_window_height. Make it static. (Fdisplay_buffer, Fenlage_window, Fshrink_window): Call enlarge_window instead of change_window_height.
author Gerd Moellmann <gerd@gnu.org>
date Thu, 23 Sep 1999 11:58:37 +0000
parents 6413bcf4ea32
children 2bbee3534773
files src/window.c
diffstat 1 files changed, 218 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/window.c	Thu Sep 23 11:58:34 1999 +0000
+++ b/src/window.c	Thu Sep 23 11:58:37 1999 +0000
@@ -54,12 +54,13 @@
 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
 static int window_min_size_1 P_ ((struct window *, int));
-static int window_min_size P_ ((struct window *, int, int *));
-static int window_fixed_size_p P_ ((struct window *, int, int));
+static int window_min_size P_ ((struct window *, int, int, int *));
 static void size_window P_ ((Lisp_Object, int, int, int));
 static void foreach_window_1 P_ ((struct window *, void (*fn) (), int, int,
 				  int, int));
 static void freeze_window_start P_ ((struct window *, int));
+static int window_fixed_size_p P_ ((struct window *, int, int));
+static void enlarge_window P_ ((int, int));
 
 
 /* This is the window in which the terminal's cursor should
@@ -210,6 +211,7 @@
   XSETFASTINT (p->height, 0);
   XSETFASTINT (p->width, 0);
   XSETFASTINT (p->hscroll, 0);
+  p->orig_top = p->orig_height = Qnil;
   p->start = Fmake_marker ();
   p->pointm = Fmake_marker ();
   XSETFASTINT (p->use_time, 0);
@@ -923,6 +925,7 @@
   XSETFASTINT (p->window_end_pos, 0);
   p->window_end_valid = Qnil;
   p->frozen_window_start_p = 0;
+  p->orig_top = p->orig_height = Qnil;
 
   p->next = tem = o->next;
   if (!NILP (tem))
@@ -2104,17 +2107,22 @@
 
 /* Return the minimum size of window W, taking fixed-size windows into
    account.  WIDTH_P non-zero means return the minimum width,
-   otherwise return the minimum height.  Set *FIXED to 1 if W is
-   fixed-size unless FIXED is null.  */
+   otherwise return the minimum height.  IGNORE_FIXED_P non-zero means
+   ignore if W is fixed-size.  Set *FIXED to 1 if W is fixed-size
+   unless FIXED is null.  */
 
 static int
-window_min_size (w, width_p, fixed)
+window_min_size (w, width_p, ignore_fixed_p, fixed)
      struct window *w;
-     int width_p, *fixed;
+     int width_p, ignore_fixed_p, *fixed;
 {
   int size, fixed_p;
 
-  fixed_p = window_fixed_size_p (w, width_p, 1);
+  if (ignore_fixed_p)
+    fixed_p = 0;
+  else
+    fixed_p = window_fixed_size_p (w, width_p, 1);
+  
   if (fixed)
     *fixed = fixed_p;
   
@@ -2122,7 +2130,7 @@
     size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
   else
     size = window_min_size_1 (w, width_p);
-
+      
   return size;
 }
 
@@ -2785,9 +2793,9 @@
 	      old_selected_window = selected_window;
 
 	      selected_window = upper;
-	      change_window_height ((total / 2
-				     - XFASTINT (XWINDOW (upper)->height)),
-				    0);
+	      enlarge_window ((total / 2
+			       - XFASTINT (XWINDOW (upper)->height)),
+			      0);
 	      selected_window = old_selected_window;
 	    }
 	}
@@ -3022,7 +3030,7 @@
      register Lisp_Object arg, side;
 {
   CHECK_NUMBER (arg, 0);
-  change_window_height (XINT (arg), !NILP (side));
+  enlarge_window (XINT (arg), !NILP (side));
 
   if (! NILP (Vwindow_configuration_change_hook))
     call1 (Vrun_hooks, Qwindow_configuration_change_hook);
@@ -3037,7 +3045,7 @@
      register Lisp_Object arg, side;
 {
   CHECK_NUMBER (arg, 0);
-  change_window_height (-XINT (arg), !NILP (side));
+  enlarge_window (-XINT (arg), !NILP (side));
 
   if (! NILP (Vwindow_configuration_change_hook))
     call1 (Vrun_hooks, Qwindow_configuration_change_hook);
@@ -3074,8 +3082,8 @@
    fullfil the size request.  If they become too small in the process,
    they will be deleted.  */
 
-void
-change_window_height (delta, widthflag)
+static void
+enlarge_window (delta, widthflag)
      int delta, widthflag;
 {
   Lisp_Object parent, window, next, prev;
@@ -3124,10 +3132,10 @@
     maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
 		: !NILP (p->next) ? ((*sizefun) (p->next)
 				     - window_min_size (XWINDOW (p->next),
-							widthflag, 0))
+							widthflag, 0, 0))
 		: !NILP (p->prev) ? ((*sizefun) (p->prev)
 				     - window_min_size (XWINDOW (p->prev),
-							widthflag, 0))
+							widthflag, 0, 0))
 		/* This is a frame with only one window, a minibuffer-only
 		   or a minibufferless frame.  */
 		: (delta = 0));
@@ -3139,7 +3147,7 @@
       delta = maxdelta;
   }
 
-  if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0))
+  if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
     {
       delete_window (window);
       return;
@@ -3152,10 +3160,10 @@
   maximum = 0;
   for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
     maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
-						    widthflag, 0);
+						    widthflag, 0, 0);
   for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
     maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
-						    widthflag, 0);
+						    widthflag, 0, 0);
 
   /* If we can get it all from them, do so.  */
   if (delta <= maximum)
@@ -3176,7 +3184,7 @@
 	    {
 	      int this_one = ((*sizefun) (next)
 			      - window_min_size (XWINDOW (next),
-						 widthflag, &fixed_p));
+						 widthflag, 0, &fixed_p));
 	      if (!fixed_p)
 		{
 		  if (this_one > delta)
@@ -3198,7 +3206,7 @@
 	    {
 	      int this_one = ((*sizefun) (prev)
 			      - window_min_size (XWINDOW (prev),
-						 widthflag, &fixed_p));
+						 widthflag, 0, &fixed_p));
 	      if (!fixed_p)
 		{
 		  if (this_one > delta)
@@ -3309,6 +3317,194 @@
 #undef CURSIZE
 
 
+
+/***********************************************************************
+			Resizing Mini-Windows
+ ***********************************************************************/
+
+static void shrink_window_lowest_first P_ ((struct window *, int));
+static void save_restore_orig_size P_ ((struct window *, int));
+
+
+/* Shrink windows rooted in window W to HEIGHT.  Take the space needed
+   from lowest windows first.  */
+
+static void
+shrink_window_lowest_first (w, height)
+     struct window *w;
+     int height;
+{
+  struct window *c;
+  Lisp_Object child;
+  int old_height;
+
+  xassert (!MINI_WINDOW_P (w));
+
+  /* Set redisplay hints.  */
+  XSETFASTINT (w->last_modified, 0);
+  XSETFASTINT (w->last_overlay_modified, 0);
+  windows_or_buffers_changed++;
+  FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
+
+  old_height = XFASTINT (w->height);
+  XSETFASTINT (w->height, height);
+
+  if (!NILP (w->hchild))
+    {
+      for (child = w->hchild; !NILP (child); child = c->next)
+	{
+	  c = XWINDOW (child);
+	  c->top = w->top;
+	  shrink_window_lowest_first (c, height);
+	}
+    }
+  else if (!NILP (w->vchild))
+    {
+      Lisp_Object last_child;
+      int delta = old_height - height;
+      int last_top;
+      
+      /* Find the last child.  We are taking space from lowest windows
+	 first, so we iterate over children from the last child
+	 backwards.  */
+      for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
+	last_child = child;
+
+      /* Assign new heights.  We leave only MIN_SAFE_WINDOW_HEIGHT.  */
+      for (child = last_child; delta && !NILP (child); child = c->prev)
+	{
+	  int this_one;
+	  
+	  c = XWINDOW (child);
+	  this_one = XFASTINT (c->height) - MIN_SAFE_WINDOW_HEIGHT;
+
+	  if (this_one > delta)
+	    this_one = delta;
+
+	  shrink_window_lowest_first (c, XFASTINT (c->height) - this_one);
+	  delta -= this_one;
+	}
+
+      /* Compute new positions.  */
+      last_top = w->top;
+      for (child = w->vchild; !NILP (child); child = c->next)
+	{
+	  c = XWINDOW (child);
+	  c->top = make_number (last_top);
+	  shrink_window_lowest_first (c, XFASTINT (c->height));
+	  last_top += XFASTINT (c->height);
+	}
+    }
+}
+
+
+/* Save or restore positions and sizes in the window tree rooted at W.
+   SAVE_P non-zero means save top position and height in orig_top and
+   orig_height members of the window structure.  Otherwise, restore top
+   and height from orig_top and orig_height.  */
+
+static void
+save_restore_orig_size (w, save_p)
+     struct window *w;
+     int save_p;
+{
+  while (w)
+    {
+      if (!NILP (w->hchild))
+	save_restore_orig_size (XWINDOW (w->hchild), save_p);
+      else if (!NILP (w->vchild))
+	save_restore_orig_size (XWINDOW (w->vchild), save_p);
+      
+      if (save_p)
+	{
+	  w->orig_top = w->top;
+	  w->orig_height = w->height;
+	}
+      else
+	{
+	  xassert (INTEGERP (w->orig_top) && INTEGERP (w->orig_height));
+	  w->top = w->orig_top;
+	  w->height = w->orig_height;
+	  w->orig_height = w->orig_top = Qnil;
+	}
+      
+      XSETFASTINT (w->last_modified, 0);
+      XSETFASTINT (w->last_overlay_modified, 0);
+      w = NILP (w->next) ? NULL : XWINDOW (w->next);
+    }
+}
+
+
+/* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
+   without deleting other windows.  */
+
+void
+grow_mini_window (w, delta)
+     struct window *w;
+     int delta;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct window *root;
+  
+  xassert (MINI_WINDOW_P (w));
+  xassert (delta >= 0);
+	   
+  /* Check values of window_min_width and window_min_height for
+     validity.  */
+  check_min_window_sizes ();
+
+  /* Compute how much we can enlarge the mini-window without deleting
+     other windows.  */
+  root = XWINDOW (FRAME_ROOT_WINDOW (f));
+  if (delta)
+    {
+      int min_height = window_min_size (root, 0, 0, 0);
+      if (XFASTINT (root->height) - delta < min_height)
+	delta = XFASTINT (root->height) - min_height;
+    }
+    
+  if (delta)
+    {
+      /* Save original window sizes and positions, if not already done.  */
+      if (NILP (root->orig_top))
+	save_restore_orig_size (root, 1);
+
+      /* Shrink other windows.  */
+      shrink_window_lowest_first (root, XFASTINT (root->height) - delta);
+
+      /* Grow the mini-window.  */
+      w->top = make_number (XFASTINT (root->top) + XFASTINT (root)->height);
+      w->height = make_number (XFASTINT (w->height) + delta);
+      XSETFASTINT (w->last_modified, 0);
+      XSETFASTINT (w->last_overlay_modified, 0);
+      
+      adjust_glyphs (f);
+    }
+}
+
+
+/* Shrink mini-window W back to its original size before the first
+   call to grow_mini_window.  Resize other windows on the same frame
+   back to their original size.  */
+
+void
+shrink_mini_window (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
+
+  if (!NILP (root->orig_height))
+    {
+      save_restore_orig_size (root, 0);
+      adjust_glyphs (f);
+      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
+      windows_or_buffers_changed = 1;
+    }
+}
+
+
+
 /* Mark window cursors off for all windows in the window tree rooted
    at W by setting their phys_cursor_on_p flag to zero.  Called from
    xterm.c, e.g. when a frame is cleared and thereby all cursors on