# HG changeset patch # User Martin Rudalics # Date 1209637020 0 # Node ID b64e3d5c58520cab3594417afd41b8d31eef307e # Parent befafb2d092851390739af95d67465f9daceb3e6 (make_window): Initialize resize_proportionally. (enlarge_window): Temporarily set resize_proportionally to make sure that shrink_windows does scale the window proportionally. (shrink_windows): When window has resize_proportionally set try to shrink it proportionally by stealing from other windows. (struct saved_window, Fset_window_configuration) (compare_window_configurations): Handle resize_proportionally. (WINDOW_TOTAL_SIZE): New macro. (window_min_size, shrink_windows, size_window): Use it. (check_min_window_sizes): Removed. Invalid values of window-min-height|width are handled by window_min_size_2 now. (size_window, Fsplit_window, enlarge_window) (adjust_window_trailing_edge, grow_mini_window): Don't call check_min_window_sizes. (window_min_size_2, window_min_size_1, window_min_size): New argument safe_p for retrieving "safe" minimum sizes. (Fdisplay_buffer, Fsplit_window, enlarge_window): (adjust_window_trailing_edge, grow_mini_window): Adjust arguments of window_min_size... functions. (shrink_windows): Argument min_size removed. New argument safe_p allows shrinking windows to their safe minimum sizes. Calculate minimum size and decide whether a window shall be deleted for each window individually. (size_window): When nodelete_p equals 2, tell shrink_windows to delete windows only if their new minimum size is no more safe. (shrink_window_lowest_first): Call window_min_size_1 to make sure to preserve modeline of bottom-most window when resizing the minibuffer. (Fset_window_configuration, Fcurrent_window_configuration) (compare_window_configurations): Do not handle window-min-height|width any more. (syms_of_window): Clarify window-min-height|width doc-strings. diff -r befafb2d0928 -r b64e3d5c5852 src/window.c --- a/src/window.c Thu May 01 10:14:44 2008 +0000 +++ b/src/window.c Thu May 01 10:17:00 2008 +0000 @@ -65,9 +65,9 @@ static void window_scroll P_ ((Lisp_Object, int, int, int)); 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_2 P_ ((struct window *, int)); -static int window_min_size P_ ((struct window *, int, int, int *)); +static int window_min_size_1 P_ ((struct window *, int, int)); +static int window_min_size_2 P_ ((struct window *, int, int)); +static int window_min_size P_ ((struct window *, int, int, int, int *)); static void size_window P_ ((Lisp_Object, int, int, int, int, int)); static int freeze_window_start P_ ((struct window *, void *)); static int window_fixed_size_p P_ ((struct window *, int, int)); @@ -299,6 +299,7 @@ p->fringes_outside_margins = Qnil; p->scroll_bar_width = Qnil; p->vertical_scroll_bar_type = Qt; + p->resize_proportionally = Qnil; Vwindow_list = Qnil; return val; @@ -2550,18 +2551,11 @@ #define MIN_SAFE_WINDOW_WIDTH (2) #define MIN_SAFE_WINDOW_HEIGHT (1) -/* Make sure that window_min_height and window_min_width are - not too small; if they are, set them to safe minima. */ - -static void -check_min_window_sizes () -{ - /* Smaller values might permit a crash. */ - if (window_min_width < MIN_SAFE_WINDOW_WIDTH) - window_min_width = MIN_SAFE_WINDOW_WIDTH; - if (window_min_height < MIN_SAFE_WINDOW_HEIGHT) - window_min_height = MIN_SAFE_WINDOW_HEIGHT; -} +/* For wp non-zero the total number of columns of window w. Otherwise + the total number of lines of w. */ + +#define WINDOW_TOTAL_SIZE(w, wp) \ + (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w)) /* If *ROWS or *COLS are too small a size for FRAME, set them to the minimum allowable size. */ @@ -2608,7 +2602,7 @@ if (width_p) { - /* A horiz. combination is fixed-width if all of if its + /* A horizontal combination is fixed-width if all of if its children are. */ while (c && window_fixed_size_p (c, width_p, 0)) c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; @@ -2616,7 +2610,7 @@ } else { - /* A horiz. combination is fixed-height if one of if its + /* A horizontal combination is fixed-height if one of if its children is. */ while (c && !window_fixed_size_p (c, width_p, 0)) c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; @@ -2629,7 +2623,7 @@ if (width_p) { - /* A vert. combination is fixed-width if one of if its + /* A vertical combination is fixed-width if one of if its children is. */ while (c && !window_fixed_size_p (c, width_p, 0)) c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; @@ -2637,7 +2631,7 @@ } else { - /* A vert. combination is fixed-height if all of if its + /* A vertical combination is fixed-height if all of if its children are. */ while (c && window_fixed_size_p (c, width_p, 0)) c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; @@ -2689,120 +2683,130 @@ return fixed_p; } -/* Return the minimum size for leaf window W. WIDTH_P non-zero means - take into account fringes and the scrollbar of W. WIDTH_P zero means - take into account mode-line of W. Return 1 for the minibuffer. */ +/* Return minimum size of leaf window W. WIDTH_P non-zero means return + the minimum width of W, WIDTH_P zero means return the minimum height + of W. SAFE_P non-zero means ignore window-min-height|width but just + return values that won't crash Emacs and don't hide components like + fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the + minibuffer window, always return 1. */ static int -window_min_size_2 (w, width_p) +window_min_size_2 (w, width_p, safe_p) struct window *w; - int width_p; -{ - int size; - + int width_p, safe_p; +{ + /* We should consider buffer-local values of window_min_height and + window_min_width here. */ if (width_p) - size = max (window_min_width, - (MIN_SAFE_WINDOW_WIDTH + { + int safe_size = (MIN_SAFE_WINDOW_WIDTH + WINDOW_FRINGE_COLS (w) - + WINDOW_SCROLL_BAR_COLS (w))); + + WINDOW_SCROLL_BAR_COLS (w)); + + return safe_p ? safe_size : max (window_min_width, safe_size); + } else if (MINI_WINDOW_P (w)) - size = 1; + return 1; else - size = max (window_min_height, - (MIN_SAFE_WINDOW_HEIGHT - /* Don't count the header-line here. It would break - splitting a window with a header-line when the new - window shall have a height of two (calculator does - that). */ - + (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0))); - - return size; -} - -/* Return the minimum size of window W, not taking fixed-width windows - into account. WIDTH_P non-zero means return the minimum width, - otherwise return the minimum height. If W is a combination window, - compute the minimum size from the minimum sizes of W's children. */ + { + int safe_size = (MIN_SAFE_WINDOW_HEIGHT + + ((BUFFERP (w->buffer) + && !NILP (XBUFFER (w->buffer)->mode_line_format)) + ? 1 : 0)); + + return safe_p ? safe_size : max (window_min_height, safe_size); + } +} + +/* Return minimum size of window W, not taking fixed-width windows into + account. WIDTH_P non-zero means return the minimum width, otherwise + return the minimum height. SAFE_P non-zero means ignore + window-min-height|width but just return values that won't crash Emacs + and don't hide components like fringes, scrollbars, or modelines. If + W is a combination window, compute the minimum size from the minimum + sizes of W's children. */ static int -window_min_size_1 (w, width_p) +window_min_size_1 (w, width_p, safe_p) struct window *w; - int width_p; + int width_p, safe_p; { struct window *c; int size; if (!NILP (w->hchild)) { + /* W is a horizontal combination. */ c = XWINDOW (w->hchild); size = 0; if (width_p) { - /* The min width of a horizontal combination is - the sum of the min widths of its children. */ + /* The minimum width of a horizontal combination is the sum of + the minimum widths of its children. */ while (c) { - size += window_min_size_1 (c, width_p); + size += window_min_size_1 (c, 1, safe_p); c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; } } else { - /* The min height a horizontal combination equals - the maximum of all min height of its children. */ + /* The minimum height of a horizontal combination is the + maximum of the minimum heights of its children. */ while (c) { - int min_size = window_min_size_1 (c, width_p); - size = max (min_size, size); + size = max (window_min_size_1 (c, 0, safe_p), size); c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; } } } else if (!NILP (w->vchild)) { + /* W is a vertical combination. */ c = XWINDOW (w->vchild); size = 0; if (width_p) { - /* The min width of a vertical combination is - the maximum of the min widths of its children. */ + /* The minimum width of a vertical combination is the maximum + of the minimum widths of its children. */ while (c) { - int min_size = window_min_size_1 (c, width_p); - size = max (min_size, size); + size = max (window_min_size_1 (c, 1, safe_p), size); c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; } } else { - /* The min height of a vertical combination equals - the sum of the min height of its children. */ + /* The minimum height of a vertical combination is the sum of + the minimum height of its children. */ while (c) { - size += window_min_size_1 (c, width_p); + size += window_min_size_1 (c, 0, safe_p); c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; } } } else - size = window_min_size_2 (w, width_p); + /* W is a leaf window. */ + size = window_min_size_2 (w, width_p, safe_p); return size; } - /* 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. 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. */ + account. WIDTH_P non-zero means return the minimum width, otherwise + return the minimum height. SAFE_P non-zero means ignore + window-min-height|width but just return values that won't crash Emacs + and don't hide components like fringes, scrollbars, or modelines. + 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, ignore_fixed_p, fixed) +window_min_size (w, width_p, safe_p, ignore_fixed_p, fixed) struct window *w; - int width_p, ignore_fixed_p, *fixed; + int width_p, safe_p, ignore_fixed_p, *fixed; { int size, fixed_p; @@ -2815,9 +2819,9 @@ *fixed = fixed_p; if (fixed_p) - size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines); + size = WINDOW_TOTAL_SIZE (w, width_p); else - size = window_min_size_1 (w, width_p); + size = window_min_size_1 (w, width_p, safe_p); return size; } @@ -2859,35 +2863,38 @@ 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. +/* Calculate new sizes for windows in the list FORWARD when their + compound 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. Fixed-size windows may be shrunk if + and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means + shrink columns, otherwise shrink lines. + + SAFE_P zero means windows may be sized down to window-min-height + lines (window-min-window columns for WIDTH_P non-zero). SAFE_P + non-zero means windows may be sized down to their minimum safe sizes + taking into account the space needed to display modelines, fringes, + and scrollbars. 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. */ + must free. A size -1 means the window is fixed and RESIZE_FIXED_P is + zero. A size zero means the window shall be deleted. Array index 0 + refers to the first window in FORWARD, 1 to the second, and so on. + + This function resizes windows proportionally to their size. It also + tries to preserve smaller windows by resizing larger windows before + resizing any window to zero. If resize_proportionally is non-nil for + a specific window, it will attempt to strictly resize that window + proportionally, even at the expense of deleting 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; +shrink_windows (total, size, nchildren, shrinkable, resize_fixed_p, + forward, width_p, safe_p) + int total, size, nchildren, shrinkable; + int resize_fixed_p, width_p, safe_p; Lisp_Object forward; { int available_resize = 0; - int *new_sizes; + int *new_sizes, *min_sizes; struct window *c; Lisp_Object child; int smallest = total; @@ -2896,21 +2903,24 @@ int i; new_sizes = xmalloc (sizeof (*new_sizes) * nchildren); + min_sizes = xmalloc (sizeof (*min_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)) + child_size = WINDOW_TOTAL_SIZE (c, width_p); + + 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; + min_sizes[i] = window_min_size_1 (c, width_p, safe_p); + if (child_size > min_sizes[i] + && NILP (c->resize_proportionally)) + available_resize += child_size - min_sizes[i]; } } /* We might need to shrink some windows to zero. Find the smallest @@ -2927,8 +2937,8 @@ { /* Resize this window down to zero. */ new_sizes[i] = 0; - if (smallest > min_size) - available_resize -= smallest - min_size; + if (smallest > min_sizes[i]) + available_resize -= smallest - min_sizes[i]; available_resize += smallest; --shrinkable; total_removed += smallest; @@ -2946,11 +2956,12 @@ proportional to its size. */ for (i = 0; i < nchildren; ++i) { - if (new_sizes[i] > min_size) + if (new_sizes[i] > min_sizes[i]) { - int to_shrink = total_shrink*new_sizes[i]/total; - if (new_sizes[i] - to_shrink < min_size) - to_shrink = new_sizes[i] - min_size; + int to_shrink = total_shrink * new_sizes[i] / total; + + if (new_sizes[i] - to_shrink < min_sizes[i]) + to_shrink = new_sizes[i] - min_sizes[i]; new_sizes[i] -= to_shrink; total_removed += to_shrink; } @@ -2971,7 +2982,7 @@ } for (i = 0; i < nchildren; ++i) - if (new_sizes[i] > min_size) + if (new_sizes[i] > min_sizes[i]) { --new_sizes[i]; ++total_removed; @@ -2981,7 +2992,6 @@ break; } - /* Special case, only one window left. */ if (nonzero_sizes == 1) break; @@ -3001,22 +3011,24 @@ } } + xfree (min_sizes); + 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 - keep their proportionate size relative to WINDOW. + WINDOW's width. Resize WINDOW's children, if any, so that they keep + their proportionate size relative to WINDOW. If FIRST_ONLY is 1, change only the first of WINDOW's children when they are in series. If LAST_ONLY is 1, change only the last of WINDOW's children when they are in series. Propagate WINDOW's top or left edge position to children. Delete - windows that become too small unless NODELETE_P is non-zero. - - If NODELETE_P is 2, that means we do delete windows that are - too small, even if they were too small before! */ + windows that become too small unless NODELETE_P is 1. When + NODELETE_P equals 2 do not honor settings for window-min-height and + window-min-width when resizing windows but use safe defaults instead. + This should give better behavior when resizing frames. */ static void size_window (window, size, width_p, nodelete_p, first_only, last_only) @@ -3027,47 +3039,16 @@ struct window *w = XWINDOW (window); struct window *c; Lisp_Object child, *forward, *sideward; - int old_size, min_size, safe_min_size; - - check_min_window_sizes (); + int old_size = WINDOW_TOTAL_SIZE (w, width_p); + size = max (0, size); - /* If the window has been "too small" at one point, - don't delete it for being "too small" in the future. - Preserve it as long as that is at all possible. */ - if (width_p) - { - old_size = WINDOW_TOTAL_COLS (w); - min_size = window_min_width; - safe_min_size = window_min_size_2 (w, 1); - } - else - { - old_size = XINT (w->total_lines); - min_size = window_min_height; - safe_min_size = window_min_size_2 (w, 0); - } - - if (old_size < min_size && nodelete_p != 2) - w->too_small_ok = Qt; - - /* Move the following test here since otherwise the - preceding test doesn't make sense. martin. */ - if (nodelete_p == 2) - nodelete_p = 0; - - /* Maybe delete WINDOW if it's too small. */ - if (nodelete_p != 1 && !NILP (w->parent)) - { - if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok)) - min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT; - if (min_size < safe_min_size) - min_size = safe_min_size; - if (size < min_size) - { - delete_window (window); - return; - } + /* Delete WINDOW if it's too small. */ + if (nodelete_p != 1 && !NILP (w->parent) + && size < window_min_size_1 (w, width_p, nodelete_p == 2)) + { + delete_window (window); + return; } /* Set redisplay hints. */ @@ -3117,9 +3098,8 @@ last_child = child; } - child_size = XINT (width_p ? c->total_cols : c->total_lines); - size_window (last_child, - size - old_size + child_size, + child_size = WINDOW_TOTAL_SIZE (c, width_p); + size_window (last_child, size - old_size + child_size, width_p, nodelete_p, first_only, last_only); } else if (!NILP (*forward) && first_only) @@ -3135,9 +3115,8 @@ else c->top_line = w->top_line; - child_size = XINT (width_p ? c->total_cols : c->total_lines); - size_window (child, - size - old_size + child_size, + child_size = WINDOW_TOTAL_SIZE (c, width_p); + size_window (child, size - old_size + child_size, width_p, nodelete_p, first_only, last_only); } else if (!NILP (*forward)) @@ -3155,7 +3134,7 @@ int child_size; c = XWINDOW (child); - child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines); + child_size = WINDOW_TOTAL_SIZE (c, width_p); total += child_size; if (window_fixed_size_p (c, width_p, 0)) @@ -3174,8 +3153,9 @@ 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); + new_sizes = shrink_windows (total, size, nchildren, n, + resize_fixed_p, *forward, width_p, + nodelete_p == 2); else { each = (size - total) / n; @@ -3190,7 +3170,7 @@ int new_size, old_size; c = XWINDOW (child); - old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines); + old_size = WINDOW_TOTAL_SIZE (c, width_p); new_size = old_size; /* The top or left edge position of this child equals the @@ -3207,7 +3187,7 @@ extra = 0; } - /* Set new height. Note that size_window also propagates + /* Set new size. Note that size_window also propagates edge positions to children, so it's not a no-op if we didn't change the child's size. */ size_window (child, new_size, width_p, 1, first_only, last_only); @@ -3223,21 +3203,26 @@ xassert (size == last_pos - first_pos); /* Now delete any children that became too small. */ - if (!nodelete_p) + if (nodelete_p != 1) for (child = *forward; !NILP (child); child = c->next) { int child_size; + c = XWINDOW (child); - child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines); - size_window (child, child_size, width_p, 2, first_only, last_only); + child_size = WINDOW_TOTAL_SIZE (c, width_p); + size_window (child, child_size, width_p, nodelete_p, + first_only, last_only); } } } /* Set WINDOW's height to HEIGHT, and recursively change the height of - WINDOW's children. NODELETE non-zero means don't delete windows - that become too small in the process. (The caller should check - later and do so if appropriate.) */ + WINDOW's children. NODELETE zero means windows that have become + smaller than window-min-height in the process may be deleted. + NODELETE 1 means never delete windows that become too small in the + process. (The caller should check later and do so if appropriate.) + NODELETE 2 means delete only windows that have become too small to be + displayed correctly. */ void set_window_height (window, height, nodelete) @@ -3248,11 +3233,13 @@ size_window (window, height, 0, nodelete, 0, 0); } - /* Set WINDOW's width to WIDTH, and recursively change the width of - WINDOW's children. NODELETE non-zero means don't delete windows - that become too small in the process. (The caller should check - later and do so if appropriate.) */ + WINDOW's children. NODELETE zero means windows that have become + smaller than window-min-width in the process may be deleted. + NODELETE 1 means never delete windows that become too small in the + process. (The caller should check later and do so if appropriate.) + NODELETE 2 means delete only windows that have become too small to be + displayed correctly. */ void set_window_width (window, width, nodelete) @@ -3359,7 +3346,7 @@ } } } - + run_funs (global_wcch); unbind_to (count, Qnil); } @@ -3863,7 +3850,7 @@ && (window_height (window) >= split_height_threshold || (NILP (XWINDOW (window)->parent))) && (window_height (window) - >= (2 * window_min_size_2 (XWINDOW (window), 0)))) + >= (2 * window_min_size_2 (XWINDOW (window), 0, 0)))) window = Fsplit_window (window, Qnil, Qnil); else { @@ -3878,7 +3865,7 @@ && window_height (window) >= split_height_threshold) || (NILP (XWINDOW (window)->parent))) && (window_height (window) - >= (2 * window_min_size_2 (XWINDOW (window), 0)))) + >= (2 * window_min_size_2 (XWINDOW (window), 0, 0)))) window = Fsplit_window (window, Qnil, Qnil); else window = Fget_lru_window (frames, Qnil); @@ -4124,12 +4111,10 @@ else if (window_fixed_size_p (o, !NILP (horflag), 0)) error ("Attempt to split fixed-size window"); - check_min_window_sizes (); - if (NILP (horflag)) { - int window_safe_height = window_min_size_2 (o, 0); - + int window_safe_height = window_min_size_2 (o, 0, 0); + if (size_int < window_safe_height) error ("Window height %d too small (after splitting)", size_int); if (size_int + window_safe_height > XFASTINT (o->total_lines)) @@ -4145,8 +4130,8 @@ } else { - int window_safe_width = window_min_size_2 (o, 1); - + int window_safe_width = window_min_size_2 (o, 1, 0); + if (size_int < window_safe_width) error ("Window width %d too small (after splitting)", size_int); if (size_int + window_safe_width > XFASTINT (o->total_cols)) @@ -4277,12 +4262,11 @@ *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines)) -/* Enlarge WINDOW by DELTA. - HORIZ_FLAG nonzero means enlarge it horizontally; - zero means do it vertically. +/* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it + horizontally; zero means do it vertically. Siblings of the selected window are resized to fulfill the size - request. If they become too small in the process, they will be + request. If they become too small in the process, they may be deleted. */ static void @@ -4299,10 +4283,6 @@ void (*setsizefun) P_ ((Lisp_Object, int, int)) = (horiz_flag ? set_window_width : set_window_height); - /* Check values of window_min_width and window_min_height for - validity. */ - check_min_window_sizes (); - /* Give up if this window cannot be resized. */ if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1)) error ("Window is not resizable"); @@ -4339,11 +4319,11 @@ /* This is a main window followed by a minibuffer. */ : !NILP (p->next) ? ((*sizefun) (p->next) - window_min_size (XWINDOW (p->next), - horiz_flag, 0, 0)) + horiz_flag, 0, 0, 0)) /* This is a minibuffer following a main window. */ : !NILP (p->prev) ? ((*sizefun) (p->prev) - window_min_size (XWINDOW (p->prev), - horiz_flag, 0, 0)) + horiz_flag, 0, 0, 0)) /* This is a frame with only one window, a minibuffer-only or a minibufferless frame. */ : (delta = 0)); @@ -4355,7 +4335,8 @@ delta = maxdelta; } - if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0)) + if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), + horiz_flag, 0, 0, 0)) { delete_window (window); return; @@ -4368,10 +4349,10 @@ maximum = 0; for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next) maximum += (*sizefun) (next) - window_min_size (XWINDOW (next), - horiz_flag, 0, 0); + horiz_flag, 0, 0, 0); for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev) maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), - horiz_flag, 0, 0); + horiz_flag, 0, 0, 0); /* If we can get it all from them without deleting them, do so. */ if (delta <= maximum) @@ -4392,8 +4373,8 @@ if (! NILP (next)) { int this_one = ((*sizefun) (next) - - window_min_size (XWINDOW (next), - horiz_flag, 0, &fixed_p)); + - window_min_size (XWINDOW (next), horiz_flag, + 0, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) @@ -4414,8 +4395,8 @@ if (! NILP (prev)) { int this_one = ((*sizefun) (prev) - - window_min_size (XWINDOW (prev), - horiz_flag, 0, &fixed_p)); + - window_min_size (XWINDOW (prev), horiz_flag, + 0, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) @@ -4474,7 +4455,7 @@ /* Delete any siblings that come after WINDOW. Note that if START is not WINDOW, then WINDOW still - Fhas siblings, so WINDOW has not yet replaced its parent. */ + has siblings, so WINDOW has not yet replaced its parent. */ tem = start; while (! EQ (tem, window)) { @@ -4511,7 +4492,11 @@ The number of children n equals the number of resizable children of this window + 1 because we know window itself - is resizable (otherwise we would have signalled an error). */ + is resizable (otherwise we would have signalled an error). + + This reasoning is not correct when other windows become too + small and shrink_windows refuses to delete them. Below we + use resize_proportionally to work around this problem. */ struct window *w = XWINDOW (window); Lisp_Object s; @@ -4532,12 +4517,17 @@ (*setsizefun) (window, XINT (*sizep) + delta1, 0); /* Squeeze out delta1 lines or columns from our parent, - shriking this window and siblings proportionately. - This brings parent back to correct size. - Delta1 was calculated so this makes this window the desired size, - taking it all out of the siblings. */ + shrinking this window and siblings proportionately. This + brings parent back to correct size. Delta1 was calculated + so this makes this window the desired size, taking it all + out of the siblings. + + Temporarily set resize_proportionally to Qt to assure that, + if necessary, shrink_windows deletes smaller windows rather + than shrink this window. */ + w->resize_proportionally = Qt; (*setsizefun) (parent, opht, 0); - + w->resize_proportionally = Qnil; } } @@ -4567,10 +4557,6 @@ Lisp_Object old_config = Fcurrent_window_configuration (Qnil); int delcount = window_deletion_count; - /* Check values of window_min_width and window_min_height for - validity. */ - check_min_window_sizes (); - CHECK_WINDOW (window); /* Give up if this window cannot be resized. */ @@ -4625,7 +4611,7 @@ /* Don't make this window too small. */ if (XINT (CURSIZE (window)) + delta - < window_min_size_2 (XWINDOW (window), horiz_flag)) + < window_min_size_2 (XWINDOW (window), horiz_flag, 0)) { Fset_window_configuration (old_config); error ("Cannot adjust window size as specified"); @@ -4778,13 +4764,13 @@ for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next) last_child = child; - /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */ + /* Size children down to their safe heights. */ for (child = last_child; delta && !NILP (child); child = c->prev) { int this_one; c = XWINDOW (child); - this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT; + this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1); if (this_one > delta) this_one = delta; @@ -4887,16 +4873,12 @@ 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); + int min_height = window_min_size (root, 0, 0, 0, 0); if (XFASTINT (root->total_lines) - delta < min_height) /* Note that the root window may already be smaller than min_height. */ @@ -6141,9 +6123,6 @@ int frame_cols, frame_lines, frame_menu_bar_lines; int frame_tool_bar_lines; - /* Record the values of window-min-width and window-min-height - so that window sizes remain consistent with them. */ - int min_width, min_height; }; /* This is saved as a Lisp_Vector */ @@ -6164,7 +6143,7 @@ Lisp_Object left_margin_cols, right_margin_cols; Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins; Lisp_Object scroll_bar_width, vertical_scroll_bar_type; - Lisp_Object dedicated; + Lisp_Object dedicated, resize_proportionally; }; #define SAVED_WINDOW_N(swv,n) \ @@ -6327,11 +6306,6 @@ * sizeof (struct window *)); n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0); - /* Temporarily avoid any problems with windows that are smaller - than they are supposed to be. */ - window_min_height = 1; - window_min_width = 1; - /* Kludge Alert! Mark all windows now on frame as "deleted". Restoring the new configuration "undeletes" any that are in it. @@ -6398,6 +6372,7 @@ w->scroll_bar_width = p->scroll_bar_width; w->vertical_scroll_bar_type = p->vertical_scroll_bar_type; w->dedicated = p->dedicated; + w->resize_proportionally = p->resize_proportionally; XSETFASTINT (w->last_modified, 0); XSETFASTINT (w->last_overlay_modified, 0); @@ -6527,10 +6502,6 @@ if (!NILP (new_current_buffer)) Fset_buffer (new_current_buffer); - /* Restore the minimum heights recorded in the configuration. */ - window_min_height = data->min_height; - window_min_width = data->min_width; - Vminibuf_scroll_window = data->minibuf_scroll_window; minibuf_selected_window = data->minibuf_selected_window; @@ -6666,6 +6637,7 @@ p->scroll_bar_width = w->scroll_bar_width; p->vertical_scroll_bar_type = w->vertical_scroll_bar_type; p->dedicated = w->dedicated; + p->resize_proportionally = w->resize_proportionally; if (!NILP (w->buffer)) { /* Save w's value of point in the window configuration. @@ -6753,8 +6725,6 @@ data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil; data->root_window = FRAME_ROOT_WINDOW (f); data->focus_frame = FRAME_FOCUS_FRAME (f); - data->min_height = window_min_height; - data->min_width = window_min_width; tem = Fmake_vector (make_number (n_windows), Qnil); data->saved_windows = tem; for (i = 0; i < n_windows; i++) @@ -7287,10 +7257,6 @@ if everything else compares equal. */ if (! EQ (d1->focus_frame, d2->focus_frame)) return 0; - if (d1->min_width != d2->min_width) - return 0; - if (d1->min_height != d2->min_height) - return 0; /* Verify that the two confis have the same number of windows. */ if (sw1->size != sw2->size) @@ -7611,12 +7577,21 @@ Vsplit_window_preferred_function = Qnil; DEFVAR_INT ("window-min-height", &window_min_height, - doc: /* *Delete any window less than this tall (including its mode line). -The value is in line units. */); + doc: /* Allow deleting windows less than this tall. +The value is measured in line units. If a window wants a modeline it +is counted as one line. + +Emacs honors settings of this variable when enlarging or shrinking +windows vertically. A value less than 1 is invalid. */); window_min_height = 4; DEFVAR_INT ("window-min-width", &window_min_width, - doc: /* *Delete any window less than this wide (measured in characters). */); + doc: /* Allow deleting windows less than this wide. +The value is measured in characters and includes any fringes or +the scrollbar. + +Emacs honors settings of this variable when enlarging or shrinking +windows horizontally. A value less than 2 is invalid. */); window_min_width = 10; DEFVAR_LISP ("scroll-preserve-screen-position",