aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Djärv2003-10-11 23:03:09 +0000
committerJan Djärv2003-10-11 23:03:09 +0000
commit0aa513ed133ef5d13657c5ab80f7ec5d319fdb06 (patch)
treec3aa8ace37b1a8a44662eea9ef34d1593d854c6b /src
parent564946b688ae39d5289aa0fd28be5ea8f0682252 (diff)
downloademacs-0aa513ed133ef5d13657c5ab80f7ec5d319fdb06.tar.gz
emacs-0aa513ed133ef5d13657c5ab80f7ec5d319fdb06.zip
* window.c (shrink_windows): New function.
(size_window): Call shrink_windows to calculate window sizes when shrinking frame with more than one window.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog6
-rw-r--r--src/window.c133
2 files changed, 133 insertions, 6 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 5edaa04dde1..b7b8394c87e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
12003-10-12 Jan Dj,Ad(Brv <jan.h.d@swipnet.se>
2
3 * window.c (shrink_windows): New function.
4 (size_window): Call shrink_windows to calculate window sizes when
5 shrinking frame with more than one window.
6
12003-10-12 Kim F. Storm <storm@cua.dk> 72003-10-12 Kim F. Storm <storm@cua.dk>
2 8
3 * xdisp.c (compute_fringe_widths): Doc fix. 9 * xdisp.c (compute_fringe_widths): Doc fix.
diff --git a/src/window.c b/src/window.c
index ce7b086833e..683332c5c3c 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2538,6 +2538,118 @@ adjust_window_margins (w)
2538 return 1; 2538 return 1;
2539} 2539}
2540 2540
2541/* Calculate new sizes for windows in the list FORWARD when the window size
2542 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2543 The number of windows in FORWARD is NCHILDREN, and the number that
2544 can shrink is SHRINKABLE.
2545 The minimum size a window can have is MIN_SIZE.
2546 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2547 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2548 shrinking rows.
2549
2550 This function returns an allocated array of new sizes that the caller
2551 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2552 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2553 the second, and so on.
2554
2555 This function tries to keep windows at least at the minimum size
2556 and resize other windows before it resizes any window to zero (i.e.
2557 delete that window).
2558
2559 Windows are resized proportional to their size, so bigger windows
2560 shrink more than smaller windows. */
2561static int *
2562shrink_windows (total, size, nchildren, shrinkable,
2563 min_size, resize_fixed_p, forward, width_p)
2564 int total, size, nchildren, shrinkable, min_size;
2565 int resize_fixed_p, width_p;
2566 Lisp_Object forward;
2567{
2568 int available_resize = 0;
2569 int *new_sizes;
2570 struct window *c;
2571 Lisp_Object child;
2572 int smallest = total;
2573 int total_removed = 0;
2574 int total_shrink = total - size;
2575 int i;
2576
2577 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2578
2579 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2580 {
2581 int child_size;
2582
2583 c = XWINDOW (child);
2584 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2585
2586 if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2587 new_sizes[i] = -1;
2588 else
2589 {
2590 new_sizes[i] = child_size;
2591 if (child_size > min_size)
2592 available_resize += child_size - min_size;
2593 }
2594 }
2595 /* We might need to shrink some windows to zero. Find the smallest
2596 windows and set them to 0 until we can fulfil the new size. */
2597
2598 while (shrinkable > 1 && size + available_resize < total)
2599 {
2600 for (i = 0; i < nchildren; ++i)
2601 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2602 smallest = new_sizes[i];
2603
2604 for (i = 0; i < nchildren; ++i)
2605 if (new_sizes[i] == smallest)
2606 {
2607 /* Resize this window down to zero. */
2608 new_sizes[i] = 0;
2609 if (smallest > min_size)
2610 available_resize -= smallest - min_size;
2611 available_resize += smallest;
2612 --shrinkable;
2613 total_removed += smallest;
2614
2615 /* Out of for, just remove one window at the time and
2616 check again if we have enough space. */
2617 break;
2618 }
2619 }
2620
2621 /* Now, calculate the new sizes. Try to shrink each window
2622 proportional to its size. */
2623 for (i = 0; i < nchildren; ++i)
2624 {
2625 if (new_sizes[i] > min_size)
2626 {
2627 int to_shrink = total_shrink*new_sizes[i]/total;
2628 if (new_sizes[i] - to_shrink < min_size)
2629 to_shrink = new_sizes[i] - min_size;
2630 new_sizes[i] -= to_shrink;
2631 total_removed += to_shrink;
2632 }
2633 }
2634
2635 /* Any reminder due to rounding, we just subtract from windows
2636 that are left and still can be shrunk. */
2637 while (total_shrink > total_removed)
2638 {
2639 for (i = 0; i < nchildren; ++i)
2640 if (new_sizes[i] > min_size)
2641 {
2642 --new_sizes[i];
2643 ++total_removed;
2644
2645 /* Out of for, just shrink one window at the time and
2646 check again if we have enough space. */
2647 break;
2648 }
2649 }
2650
2651 return new_sizes;
2652}
2541 2653
2542/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set 2654/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2543 WINDOW's width. Resize WINDOW's children, if any, so that they 2655 WINDOW's width. Resize WINDOW's children, if any, so that they
@@ -2641,6 +2753,7 @@ size_window (window, size, width_p, nodelete_p)
2641 int fixed_size, each, extra, n; 2753 int fixed_size, each, extra, n;
2642 int resize_fixed_p, nfixed; 2754 int resize_fixed_p, nfixed;
2643 int last_pos, first_pos, nchildren, total; 2755 int last_pos, first_pos, nchildren, total;
2756 int *new_sizes = NULL;
2644 2757
2645 /* Determine the fixed-size portion of the this window, and the 2758 /* Determine the fixed-size portion of the this window, and the
2646 number of child windows. */ 2759 number of child windows. */
@@ -2665,16 +2778,22 @@ size_window (window, size, width_p, nodelete_p)
2665 windows. */ 2778 windows. */
2666 resize_fixed_p = nfixed == nchildren || size < fixed_size; 2779 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2667 2780
2668 /* Compute how many lines/columns to add to each child. The 2781 /* Compute how many lines/columns to add/remove to each child. The
2669 value of extra takes care of rounding errors. */ 2782 value of extra takes care of rounding errors. */
2670 n = resize_fixed_p ? nchildren : nchildren - nfixed; 2783 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2671 each = (size - total) / n; 2784 if (size < total && n > 1)
2672 extra = (size - total) - n * each; 2785 new_sizes = shrink_windows (total, size, nchildren, n, min_size,
2786 resize_fixed_p, *forward, width_p);
2787 else
2788 {
2789 each = (size - total) / n;
2790 extra = (size - total) - n * each;
2791 }
2673 2792
2674 /* Compute new children heights and edge positions. */ 2793 /* Compute new children heights and edge positions. */
2675 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line); 2794 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
2676 last_pos = first_pos; 2795 last_pos = first_pos;
2677 for (child = *forward; !NILP (child); child = c->next) 2796 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
2678 { 2797 {
2679 int new_size, old_size; 2798 int new_size, old_size;
2680 2799
@@ -2692,7 +2811,7 @@ size_window (window, size, width_p, nodelete_p)
2692 /* If this child can be resized, do it. */ 2811 /* If this child can be resized, do it. */
2693 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0)) 2812 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2694 { 2813 {
2695 new_size = old_size + each + extra; 2814 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
2696 extra = 0; 2815 extra = 0;
2697 } 2816 }
2698 2817
@@ -2703,9 +2822,11 @@ size_window (window, size, width_p, nodelete_p)
2703 2822
2704 /* Remember the bottom/right edge position of this child; it 2823 /* Remember the bottom/right edge position of this child; it
2705 will be used to set the top/left edge of the next child. */ 2824 will be used to set the top/left edge of the next child. */
2706 last_pos += new_size; 2825 last_pos += new_size;
2707 } 2826 }
2708 2827
2828 if (new_sizes) xfree (new_sizes);
2829
2709 /* We should have covered the parent exactly with child windows. */ 2830 /* We should have covered the parent exactly with child windows. */
2710 xassert (size == last_pos - first_pos); 2831 xassert (size == last_pos - first_pos);
2711 2832