2538 |
return 1; |
return 1; |
2539 |
} |
} |
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 |
|
} |
2653 |
|
|
2654 |
/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set |
/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set |
2655 |
WINDOW's width. Resize WINDOW's children, if any, so that they |
WINDOW's width. Resize WINDOW's children, if any, so that they |
2753 |
int fixed_size, each, extra, n; |
int fixed_size, each, extra, n; |
2754 |
int resize_fixed_p, nfixed; |
int resize_fixed_p, nfixed; |
2755 |
int last_pos, first_pos, nchildren, total; |
int last_pos, first_pos, nchildren, total; |
2756 |
|
int *new_sizes = NULL; |
2757 |
|
|
2758 |
/* Determine the fixed-size portion of the this window, and the |
/* Determine the fixed-size portion of the this window, and the |
2759 |
number of child windows. */ |
number of child windows. */ |
2778 |
windows. */ |
windows. */ |
2779 |
resize_fixed_p = nfixed == nchildren || size < fixed_size; |
resize_fixed_p = nfixed == nchildren || size < fixed_size; |
2780 |
|
|
2781 |
/* Compute how many lines/columns to add to each child. The |
/* Compute how many lines/columns to add/remove to each child. The |
2782 |
value of extra takes care of rounding errors. */ |
value of extra takes care of rounding errors. */ |
2783 |
n = resize_fixed_p ? nchildren : nchildren - nfixed; |
n = resize_fixed_p ? nchildren : nchildren - nfixed; |
2784 |
each = (size - total) / n; |
if (size < total && n > 1) |
2785 |
extra = (size - total) - n * each; |
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 |
|
} |
2792 |
|
|
2793 |
/* Compute new children heights and edge positions. */ |
/* Compute new children heights and edge positions. */ |
2794 |
first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line); |
first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line); |
2795 |
last_pos = first_pos; |
last_pos = first_pos; |
2796 |
for (child = *forward; !NILP (child); child = c->next) |
for (n = 0, child = *forward; !NILP (child); child = c->next, ++n) |
2797 |
{ |
{ |
2798 |
int new_size, old_size; |
int new_size, old_size; |
2799 |
|
|
2811 |
/* If this child can be resized, do it. */ |
/* If this child can be resized, do it. */ |
2812 |
if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0)) |
if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0)) |
2813 |
{ |
{ |
2814 |
new_size = old_size + each + extra; |
new_size = new_sizes ? new_sizes[n] : old_size + each + extra; |
2815 |
extra = 0; |
extra = 0; |
2816 |
} |
} |
2817 |
|
|
2822 |
|
|
2823 |
/* Remember the bottom/right edge position of this child; it |
/* Remember the bottom/right edge position of this child; it |
2824 |
will be used to set the top/left edge of the next child. */ |
will be used to set the top/left edge of the next child. */ |
2825 |
last_pos += new_size; |
last_pos += new_size; |
2826 |
} |
} |
2827 |
|
|
2828 |
|
if (new_sizes) xfree (new_sizes); |
2829 |
|
|
2830 |
/* We should have covered the parent exactly with child windows. */ |
/* We should have covered the parent exactly with child windows. */ |
2831 |
xassert (size == last_pos - first_pos); |
xassert (size == last_pos - first_pos); |
2832 |
|
|