emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/src/window.c


From: Jan Djärv
Subject: [Emacs-diffs] Changes to emacs/src/window.c
Date: Sat, 11 Oct 2003 19:03:10 -0400

Index: emacs/src/window.c
diff -c emacs/src/window.c:1.449 emacs/src/window.c:1.450
*** emacs/src/window.c:1.449    Wed Sep 24 19:52:45 2003
--- emacs/src/window.c  Sat Oct 11 19:03:09 2003
***************
*** 2538,2543 ****
--- 2538,2655 ----
    return 1;
  }
  
+ /* Calculate new sizes for windows in the list FORWARD when the window size
+    goes from TOTAL to SIZE.  TOTAL must be greater than SIZE.
+    The number of windows in FORWARD is NCHILDREN, and the number that
+    can shrink is SHRINKABLE.
+    The minimum size a window can have is MIN_SIZE.
+    If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
+    If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
+    shrinking rows.
+ 
+    This function returns an allocated array of new sizes that the caller
+    must free.  The size -1 means the window is fixed and RESIZE_FIXED_P
+    is zero.  Array index 0 refers to the first window in FORWARD, 1 to
+    the second, and so on.
+ 
+    This function tries to keep windows at least at the minimum size
+    and resize other windows before it resizes any window to zero (i.e.
+    delete that window).
+ 
+    Windows are resized proportional to their size, so bigger windows
+    shrink more than smaller windows.  */
+ static int *
+ shrink_windows (total, size, nchildren, shrinkable,
+                 min_size, resize_fixed_p, forward, width_p)
+      int total, size, nchildren, shrinkable, min_size;
+      int resize_fixed_p, width_p;
+      Lisp_Object forward;
+ {
+   int available_resize = 0;
+   int *new_sizes;
+   struct window *c;
+   Lisp_Object child;
+   int smallest = total;
+   int total_removed = 0;
+   int total_shrink = total - size;
+   int i;
+ 
+   new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
+ 
+   for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
+     {
+       int child_size;
+ 
+       c = XWINDOW (child);
+       child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
+ 
+       if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
+         new_sizes[i] = -1;
+       else
+         {
+           new_sizes[i] = child_size;
+           if (child_size > min_size)
+             available_resize += child_size - min_size;
+         }
+     }
+   /* We might need to shrink some windows to zero.  Find the smallest
+      windows and set them to 0 until we can fulfil the new size.  */
+ 
+   while (shrinkable > 1 && size + available_resize < total)
+     {
+       for (i = 0; i < nchildren; ++i)
+         if (new_sizes[i] > 0 && smallest > new_sizes[i])
+           smallest = new_sizes[i];
+ 
+       for (i = 0; i < nchildren; ++i)
+         if (new_sizes[i] == smallest)
+           {
+             /* Resize this window down to zero.  */
+             new_sizes[i] = 0;
+             if (smallest > min_size)
+               available_resize -= smallest - min_size;
+             available_resize += smallest;
+             --shrinkable;
+             total_removed += smallest;
+ 
+             /* Out of for, just remove one window at the time and
+                check again if we have enough space.  */
+             break;
+           }
+     }
+ 
+   /* Now, calculate the new sizes.  Try to shrink each window
+      proportional to its size.  */
+   for (i = 0; i < nchildren; ++i)
+     {
+       if (new_sizes[i] > min_size)
+         {
+           int to_shrink = total_shrink*new_sizes[i]/total;
+           if (new_sizes[i] - to_shrink < min_size)
+             to_shrink = new_sizes[i] - min_size;
+           new_sizes[i] -= to_shrink;
+           total_removed += to_shrink;
+         }
+     }
+ 
+   /* Any reminder due to rounding, we just subtract from windows
+      that are left and still can be shrunk.  */
+   while (total_shrink > total_removed)
+     {
+       for (i = 0; i < nchildren; ++i)
+         if (new_sizes[i] > min_size)
+           {
+             --new_sizes[i];
+             ++total_removed;
+ 
+             /* Out of for, just shrink one window at the time and
+                check again if we have enough space.  */
+             break;
+           }
+     }
+ 
+   return new_sizes;
+ }
  
  /* Set WINDOW's height or width to SIZE.  WIDTH_P non-zero means set
     WINDOW's width.  Resize WINDOW's children, if any, so that they
***************
*** 2641,2646 ****
--- 2753,2759 ----
        int fixed_size, each, extra, n;
        int resize_fixed_p, nfixed;
        int last_pos, first_pos, nchildren, total;
+       int *new_sizes = NULL;
  
        /* Determine the fixed-size portion of the this window, and the
         number of child windows.  */
***************
*** 2665,2680 ****
         windows.  */
        resize_fixed_p = nfixed == nchildren || size < fixed_size;
  
!       /* Compute how many lines/columns to add to each child.  The
         value of extra takes care of rounding errors.  */
        n = resize_fixed_p ? nchildren : nchildren - nfixed;
!       each = (size - total) / n;
!       extra = (size - total) - n * each;
  
        /* Compute new children heights and edge positions.  */
        first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
        last_pos = first_pos;
!       for (child = *forward; !NILP (child); child = c->next)
        {
          int new_size, old_size;
  
--- 2778,2799 ----
         windows.  */
        resize_fixed_p = nfixed == nchildren || size < fixed_size;
  
!       /* Compute how many lines/columns to add/remove to each child.  The
         value of extra takes care of rounding errors.  */
        n = resize_fixed_p ? nchildren : nchildren - nfixed;
!       if (size < total && n > 1)
!         new_sizes = shrink_windows (total, size, nchildren, n, min_size,
!                                     resize_fixed_p, *forward, width_p);
!       else
!         {
!           each = (size - total) / n;
!           extra = (size - total) - n * each;
!         }
  
        /* Compute new children heights and edge positions.  */
        first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
        last_pos = first_pos;
!       for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
        {
          int new_size, old_size;
  
***************
*** 2692,2698 ****
          /* If this child can be resized, do it.  */
          if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
            {
!             new_size = old_size + each + extra;
              extra = 0;
            }
  
--- 2811,2817 ----
          /* If this child can be resized, do it.  */
          if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
            {
!             new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
              extra = 0;
            }
  
***************
*** 2703,2710 ****
  
          /* Remember the bottom/right edge position of this child; it
             will be used to set the top/left edge of the next child.  */
!         last_pos += new_size;
        }
  
        /* We should have covered the parent exactly with child windows.  */
        xassert (size == last_pos - first_pos);
--- 2822,2831 ----
  
          /* Remember the bottom/right edge position of this child; it
             will be used to set the top/left edge of the next child.  */
!           last_pos += new_size;
        }
+ 
+       if (new_sizes) xfree (new_sizes);
  
        /* We should have covered the parent exactly with child windows.  */
        xassert (size == last_pos - first_pos);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]