*** window.c Wed Apr 2 22:15:44 2008 --- window.c Tue Apr 29 16:39:42 2008 *************** *** 65,73 **** 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 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)); --- 65,73 ---- 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, 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,304 **** --- 299,305 ---- 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,2567 **** #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; ! } /* If *ROWS or *COLS are too small a size for FRAME, set them to the minimum allowable size. */ --- 2551,2561 ---- #define MIN_SAFE_WINDOW_WIDTH (2) #define MIN_SAFE_WINDOW_HEIGHT (1) ! /* 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,2614 **** if (width_p) { ! /* A horiz. 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; --- 2602,2608 ---- if (width_p) { ! /* 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,2622 **** } else { ! /* A horiz. 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; --- 2610,2616 ---- } else { ! /* 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,2635 **** if (width_p) { ! /* A vert. 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; --- 2623,2629 ---- if (width_p) { ! /* 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,2643 **** } else { ! /* A vert. 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; --- 2631,2637 ---- } else { ! /* 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,2808 **** 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. */ static int ! window_min_size_2 (w, width_p) struct window *w; ! int width_p; { ! int size; ! if (width_p) ! size = max (window_min_width, ! (MIN_SAFE_WINDOW_WIDTH + WINDOW_FRINGE_COLS (w) ! + WINDOW_SCROLL_BAR_COLS (w))); else if (MINI_WINDOW_P (w)) ! size = 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. */ static int ! window_min_size_1 (w, width_p) struct window *w; ! int width_p; { struct window *c; int size; if (!NILP (w->hchild)) { 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. */ while (c) { ! size += window_min_size_1 (c, width_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. */ while (c) { ! int min_size = window_min_size_1 (c, width_p); ! size = max (min_size, size); c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; } } } else if (!NILP (w->vchild)) { 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. */ while (c) { ! int min_size = window_min_size_1 (c, width_p); ! size = max (min_size, 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. */ while (c) { ! size += window_min_size_1 (c, width_p); c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; } } } else ! size = window_min_size_2 (w, width_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. */ static int ! window_min_size (w, width_p, ignore_fixed_p, fixed) struct window *w; ! int width_p, ignore_fixed_p, *fixed; { int size, fixed_p; --- 2683,2812 ---- return fixed_p; } ! /* 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, safe_p) struct window *w; ! int width_p, safe_p; { ! /* We should consider buffer-local values of window_min_height and ! window_min_width here. */ if (width_p) ! { ! int safe_size = (MIN_SAFE_WINDOW_WIDTH + WINDOW_FRINGE_COLS (w) ! + WINDOW_SCROLL_BAR_COLS (w)); ! ! return safe_p ? safe_size : max (window_min_width, safe_size); ! } else if (MINI_WINDOW_P (w)) ! return 1; else ! { ! 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, safe_p) struct window *w; ! 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 minimum width of a horizontal combination is the sum of ! the minimum widths of its children. */ while (c) { ! size += window_min_size_1 (c, 1, safe_p); c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; } } else { ! /* The minimum height of a horizontal combination is the ! maximum of the minimum heights of its children. */ while (c) { ! 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 minimum width of a vertical combination is the maximum ! of the minimum widths of its children. */ while (c) { ! size = max (window_min_size_1 (c, 1, safe_p), size); c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; } } else { ! /* 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, 0, safe_p); c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; } } } else ! /* 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. 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, safe_p, ignore_fixed_p, fixed) struct window *w; ! int width_p, safe_p, ignore_fixed_p, *fixed; { int size, fixed_p; *************** *** 2815,2823 **** *fixed = fixed_p; if (fixed_p) ! size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines); else ! size = window_min_size_1 (w, width_p); return size; } --- 2819,2827 ---- *fixed = fixed_p; if (fixed_p) ! size = WINDOW_TOTAL_SIZE (w, width_p); else ! size = window_min_size_1 (w, width_p, safe_p); return size; } *************** *** 2859,2893 **** 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; --- 2863,2900 ---- return 1; } ! /* 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. 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, 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, *min_sizes; struct window *c; Lisp_Object child; int smallest = total; *************** *** 2896,2916 **** 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 --- 2903,2926 ---- 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 = 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; ! 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,2934 **** { /* 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; --- 2937,2944 ---- { /* Resize this window down to zero. */ new_sizes[i] = 0; ! if (smallest > min_sizes[i]) ! available_resize -= smallest - min_sizes[i]; available_resize += smallest; --shrinkable; total_removed += smallest; *************** *** 2946,2956 **** 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; } --- 2956,2967 ---- proportional to its size. */ for (i = 0; i < nchildren; ++i) { ! if (new_sizes[i] > min_sizes[i]) { ! 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,2977 **** } for (i = 0; i < nchildren; ++i) ! if (new_sizes[i] > min_size) { --new_sizes[i]; ++total_removed; --- 2982,2988 ---- } for (i = 0; i < nchildren; ++i) ! if (new_sizes[i] > min_sizes[i]) { --new_sizes[i]; ++total_removed; *************** *** 2981,2987 **** break; } - /* Special case, only one window left. */ if (nonzero_sizes == 1) break; --- 2992,2997 ---- *************** *** 3001,3022 **** } } 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. 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! */ static void size_window (window, size, width_p, nodelete_p, first_only, last_only) --- 3011,3034 ---- } } + 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. 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 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,3073 **** 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 (); 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; ! } } /* Set redisplay hints. */ --- 3039,3054 ---- struct window *w = XWINDOW (window); struct window *c; Lisp_Object child, *forward, *sideward; ! int old_size = WINDOW_TOTAL_SIZE (w, width_p); size = max (0, size); ! /* 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,3125 **** last_child = child; } ! child_size = XINT (width_p ? c->total_cols : c->total_lines); ! size_window (last_child, ! size - old_size + child_size, width_p, nodelete_p, first_only, last_only); } else if (!NILP (*forward) && first_only) --- 3098,3105 ---- last_child = child; } ! 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,3143 **** 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, width_p, nodelete_p, first_only, last_only); } else if (!NILP (*forward)) --- 3115,3122 ---- else c->top_line = w->top_line; ! 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,3161 **** int child_size; c = XWINDOW (child); ! child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines); total += child_size; if (window_fixed_size_p (c, width_p, 0)) --- 3134,3140 ---- int child_size; c = XWINDOW (child); ! child_size = WINDOW_TOTAL_SIZE (c, width_p); total += child_size; if (window_fixed_size_p (c, width_p, 0)) *************** *** 3174,3181 **** 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; --- 3153,3161 ---- 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, ! resize_fixed_p, *forward, width_p, ! nodelete_p == 2); else { each = (size - total) / n; *************** *** 3190,3196 **** int new_size, old_size; c = XWINDOW (child); ! old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines); new_size = old_size; /* The top or left edge position of this child equals the --- 3170,3176 ---- int new_size, old_size; c = XWINDOW (child); ! old_size = WINDOW_TOTAL_SIZE (c, width_p); new_size = old_size; /* The top or left edge position of this child equals the *************** *** 3207,3213 **** extra = 0; } ! /* Set new height. 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); --- 3187,3193 ---- extra = 0; } ! /* 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,3243 **** xassert (size == last_pos - first_pos); /* Now delete any children that became too small. */ ! if (!nodelete_p) 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); } } } /* 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.) */ void set_window_height (window, height, nodelete) --- 3203,3228 ---- xassert (size == last_pos - first_pos); /* Now delete any children that became too small. */ ! if (nodelete_p != 1) for (child = *forward; !NILP (child); child = c->next) { int child_size; + c = XWINDOW (child); ! 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 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,3258 **** 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.) */ void set_window_width (window, width, nodelete) --- 3233,3245 ---- size_window (window, height, 0, nodelete, 0, 0); } /* Set WINDOW's width to WIDTH, and recursively change the width of ! 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,3365 **** } } } ! run_funs (global_wcch); unbind_to (count, Qnil); } --- 3346,3352 ---- } } } ! run_funs (global_wcch); unbind_to (count, Qnil); } *************** *** 3863,3869 **** && (window_height (window) >= split_height_threshold || (NILP (XWINDOW (window)->parent))) && (window_height (window) ! >= (2 * window_min_size_2 (XWINDOW (window), 0)))) window = Fsplit_window (window, Qnil, Qnil); else { --- 3850,3856 ---- && (window_height (window) >= split_height_threshold || (NILP (XWINDOW (window)->parent))) && (window_height (window) ! >= (2 * window_min_size_2 (XWINDOW (window), 0, 0)))) window = Fsplit_window (window, Qnil, Qnil); else { *************** *** 3878,3884 **** && window_height (window) >= split_height_threshold) || (NILP (XWINDOW (window)->parent))) && (window_height (window) ! >= (2 * window_min_size_2 (XWINDOW (window), 0)))) window = Fsplit_window (window, Qnil, Qnil); else window = Fget_lru_window (frames, Qnil); --- 3865,3871 ---- && window_height (window) >= split_height_threshold) || (NILP (XWINDOW (window)->parent))) && (window_height (window) ! >= (2 * window_min_size_2 (XWINDOW (window), 0, 0)))) window = Fsplit_window (window, Qnil, Qnil); else window = Fget_lru_window (frames, Qnil); *************** *** 4124,4135 **** 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); ! 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)) --- 4111,4120 ---- else if (window_fixed_size_p (o, !NILP (horflag), 0)) error ("Attempt to split fixed-size window"); if (NILP (horflag)) { ! 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,4152 **** } else { ! int window_safe_width = window_min_size_2 (o, 1); ! 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)) --- 4130,4137 ---- } else { ! 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,4288 **** *(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. Siblings of the selected window are resized to fulfill the size ! request. If they become too small in the process, they will be deleted. */ static void --- 4262,4272 ---- *(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. Siblings of the selected window are resized to fulfill the size ! request. If they become too small in the process, they may be deleted. */ static void *************** *** 4299,4308 **** 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"); --- 4283,4288 ---- *************** *** 4339,4349 **** /* 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)) /* This is a minibuffer following a main window. */ : !NILP (p->prev) ? ((*sizefun) (p->prev) - window_min_size (XWINDOW (p->prev), ! horiz_flag, 0, 0)) /* This is a frame with only one window, a minibuffer-only or a minibufferless frame. */ : (delta = 0)); --- 4319,4329 ---- /* 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, 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, 0)) /* This is a frame with only one window, a minibuffer-only or a minibufferless frame. */ : (delta = 0)); *************** *** 4355,4361 **** delta = maxdelta; } ! if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0)) { delete_window (window); return; --- 4335,4342 ---- delta = maxdelta; } ! if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), ! horiz_flag, 0, 0, 0)) { delete_window (window); return; *************** *** 4368,4377 **** maximum = 0; for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next) maximum += (*sizefun) (next) - window_min_size (XWINDOW (next), ! horiz_flag, 0, 0); for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev) maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), ! horiz_flag, 0, 0); /* If we can get it all from them without deleting them, do so. */ if (delta <= maximum) --- 4349,4358 ---- maximum = 0; for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next) maximum += (*sizefun) (next) - window_min_size (XWINDOW (next), ! 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, 0); /* If we can get it all from them without deleting them, do so. */ if (delta <= maximum) *************** *** 4392,4399 **** if (! NILP (next)) { int this_one = ((*sizefun) (next) ! - window_min_size (XWINDOW (next), ! horiz_flag, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) --- 4373,4380 ---- if (! NILP (next)) { int this_one = ((*sizefun) (next) ! - window_min_size (XWINDOW (next), horiz_flag, ! 0, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) *************** *** 4414,4421 **** if (! NILP (prev)) { int this_one = ((*sizefun) (prev) ! - window_min_size (XWINDOW (prev), ! horiz_flag, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) --- 4395,4402 ---- if (! NILP (prev)) { int this_one = ((*sizefun) (prev) ! - window_min_size (XWINDOW (prev), horiz_flag, ! 0, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) *************** *** 4474,4480 **** /* 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. */ tem = start; while (! EQ (tem, window)) { --- 4455,4461 ---- /* Delete any siblings that come after WINDOW. Note that if START is not WINDOW, then WINDOW still ! has siblings, so WINDOW has not yet replaced its parent. */ tem = start; while (! EQ (tem, window)) { *************** *** 4511,4517 **** 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). */ struct window *w = XWINDOW (window); Lisp_Object s; --- 4492,4502 ---- 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). ! ! 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,4543 **** (*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. */ (*setsizefun) (parent, opht, 0); ! } } --- 4517,4533 ---- (*setsizefun) (window, XINT (*sizep) + delta1, 0); /* Squeeze out delta1 lines or columns from our parent, ! 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,4576 **** 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. */ --- 4557,4562 ---- *************** *** 4625,4631 **** /* Don't make this window too small. */ if (XINT (CURSIZE (window)) + delta ! < window_min_size_2 (XWINDOW (window), horiz_flag)) { Fset_window_configuration (old_config); error ("Cannot adjust window size as specified"); --- 4611,4617 ---- /* Don't make this window too small. */ if (XINT (CURSIZE (window)) + delta ! < window_min_size_2 (XWINDOW (window), horiz_flag, 0)) { Fset_window_configuration (old_config); error ("Cannot adjust window size as specified"); *************** *** 4778,4790 **** for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next) last_child = child; ! /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */ 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; if (this_one > delta) this_one = delta; --- 4764,4776 ---- for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next) last_child = child; ! /* 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) - window_min_size_1 (c, 0, 1); if (this_one > delta) this_one = delta; *************** *** 4887,4902 **** 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); if (XFASTINT (root->total_lines) - delta < min_height) /* Note that the root window may already be smaller than min_height. */ --- 4873,4884 ---- xassert (MINI_WINDOW_P (w)); xassert (delta >= 0); /* 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, 0); if (XFASTINT (root->total_lines) - delta < min_height) /* Note that the root window may already be smaller than min_height. */ *************** *** 6164,6170 **** 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; }; #define SAVED_WINDOW_N(swv,n) \ --- 6146,6152 ---- 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, resize_proportionally; }; #define SAVED_WINDOW_N(swv,n) \ *************** *** 6327,6337 **** * 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. --- 6309,6314 ---- *************** *** 6398,6403 **** --- 6375,6381 ---- 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,6536 **** 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; --- 6505,6510 ---- *************** *** 6666,6671 **** --- 6640,6646 ---- 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,6760 **** 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++) --- 6728,6733 ---- *************** *** 7611,7622 **** 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. */); window_min_height = 4; DEFVAR_INT ("window-min-width", &window_min_width, ! doc: /* *Delete any window less than this wide (measured in characters). */); window_min_width = 10; DEFVAR_LISP ("scroll-preserve-screen-position", --- 7584,7604 ---- Vsplit_window_preferred_function = Qnil; DEFVAR_INT ("window-min-height", &window_min_height, ! 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: /* 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",