diff options
| author | Jan Djärv | 2003-10-11 23:03:09 +0000 |
|---|---|---|
| committer | Jan Djärv | 2003-10-11 23:03:09 +0000 |
| commit | 0aa513ed133ef5d13657c5ab80f7ec5d319fdb06 (patch) | |
| tree | c3aa8ace37b1a8a44662eea9ef34d1593d854c6b /src/window.c | |
| parent | 564946b688ae39d5289aa0fd28be5ea8f0682252 (diff) | |
| download | emacs-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/window.c')
| -rw-r--r-- | src/window.c | 133 |
1 files changed, 127 insertions, 6 deletions
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. */ | ||
| 2561 | static int * | ||
| 2562 | shrink_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 | ||