+/***********************************************************************
+ Resizing Mini-Windows
+ ***********************************************************************/
+
+static void shrink_window_lowest_first P_ ((struct window *, int));
+
+enum save_restore_action
+{
+ CHECK_ORIG_SIZES,
+ SAVE_ORIG_SIZES,
+ RESTORE_ORIG_SIZES
+};
+
+static int save_restore_orig_size P_ ((struct window *,
+ enum save_restore_action));
+
+/* Shrink windows rooted in window W to HEIGHT. Take the space needed
+ from lowest windows first. */
+
+static void
+shrink_window_lowest_first (w, height)
+ struct window *w;
+ int height;
+{
+ struct window *c;
+ Lisp_Object child;
+ int old_height;
+
+ xassert (!MINI_WINDOW_P (w));
+
+ /* Set redisplay hints. */
+ XSETFASTINT (w->last_modified, 0);
+ XSETFASTINT (w->last_overlay_modified, 0);
+ windows_or_buffers_changed++;
+ FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
+
+ old_height = XFASTINT (w->height);
+ XSETFASTINT (w->height, height);
+
+ if (!NILP (w->hchild))
+ {
+ for (child = w->hchild; !NILP (child); child = c->next)
+ {
+ c = XWINDOW (child);
+ c->top = w->top;
+ shrink_window_lowest_first (c, height);
+ }
+ }
+ else if (!NILP (w->vchild))
+ {
+ Lisp_Object last_child;
+ int delta = old_height - height;
+ int last_top;
+
+ /* Find the last child. We are taking space from lowest windows
+ first, so we iterate over children from the last child
+ backwards. */
+ for (child = w->vchild; !NILP (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->height) - MIN_SAFE_WINDOW_HEIGHT;
+
+ if (this_one > delta)
+ this_one = delta;
+
+ shrink_window_lowest_first (c, XFASTINT (c->height) - this_one);
+ delta -= this_one;
+ }
+
+ /* Compute new positions. */
+ last_top = XINT (w->top);
+ for (child = w->vchild; !NILP (child); child = c->next)
+ {
+ c = XWINDOW (child);
+ c->top = make_number (last_top);
+ shrink_window_lowest_first (c, XFASTINT (c->height));
+ last_top += XFASTINT (c->height);
+ }
+ }
+}
+
+
+/* Save, restore, or check positions and sizes in the window tree
+ rooted at W. ACTION says what to do.
+
+ If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
+ members are valid for all windows in the window tree. Value is
+ non-zero if they are valid.
+
+ If ACTION is SAVE_ORIG_SIZES, save members top and height in
+ orig_top and orig_height for all windows in the tree.
+
+ If ACTION is RESTORE_ORIG_SIZES, restore top and height from
+ values stored in orig_top and orig_height for all windows. */
+
+static int
+save_restore_orig_size (w, action)
+ struct window *w;
+ enum save_restore_action action;
+{
+ int success_p = 1;
+
+ while (w)
+ {
+ if (!NILP (w->hchild))
+ {
+ if (!save_restore_orig_size (XWINDOW (w->hchild), action))
+ success_p = 0;
+ }
+ else if (!NILP (w->vchild))
+ {
+ if (!save_restore_orig_size (XWINDOW (w->vchild), action))
+ success_p = 0;
+ }
+
+ switch (action)
+ {
+ case CHECK_ORIG_SIZES:
+ if (!INTEGERP (w->orig_top) || !INTEGERP (w->orig_height))
+ return 0;
+ break;
+
+ case SAVE_ORIG_SIZES:
+ w->orig_top = w->top;
+ w->orig_height = w->height;
+ XSETFASTINT (w->last_modified, 0);
+ XSETFASTINT (w->last_overlay_modified, 0);
+ break;
+
+ case RESTORE_ORIG_SIZES:
+ xassert (INTEGERP (w->orig_top) && INTEGERP (w->orig_height));
+ w->top = w->orig_top;
+ w->height = w->orig_height;
+ w->orig_height = w->orig_top = Qnil;
+ XSETFASTINT (w->last_modified, 0);
+ XSETFASTINT (w->last_overlay_modified, 0);
+ break;
+
+ default:
+ abort ();
+ }
+
+ w = NILP (w->next) ? NULL : XWINDOW (w->next);
+ }
+
+ return success_p;
+}
+
+
+/* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
+ without deleting other windows. */
+
+void
+grow_mini_window (w, delta)
+ struct window *w;
+ int delta;
+{
+ struct frame *f = XFRAME (w->frame);
+ struct window *root;
+
+ 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->height) - delta < min_height)
+ delta = XFASTINT (root->height) - min_height;
+ }
+
+ if (delta)
+ {
+ /* Save original window sizes and positions, if not already done. */
+ if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
+ save_restore_orig_size (root, SAVE_ORIG_SIZES);
+
+ /* Shrink other windows. */
+ shrink_window_lowest_first (root, XFASTINT (root->height) - delta);
+
+ /* Grow the mini-window. */
+ w->top = make_number (XFASTINT (root->top) + XFASTINT (root->height));
+ w->height = make_number (XFASTINT (w->height) + delta);
+ XSETFASTINT (w->last_modified, 0);
+ XSETFASTINT (w->last_overlay_modified, 0);
+
+ adjust_glyphs (f);
+ }
+}
+
+
+/* Shrink mini-window W. If there is recorded info about window sizes
+ before a call to grow_mini_window, restore recorded window sizes.
+ Otherwise, if the mini-window is higher than 1 line, resize it to 1
+ line. */
+
+void
+shrink_mini_window (w)
+ struct window *w;
+{
+ struct frame *f = XFRAME (w->frame);
+ struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
+
+ if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
+ {
+ save_restore_orig_size (root, RESTORE_ORIG_SIZES);
+ adjust_glyphs (f);
+ FRAME_WINDOW_SIZES_CHANGED (f) = 1;
+ windows_or_buffers_changed = 1;
+ }
+ else if (XFASTINT (w->height) > 1)
+ {
+ Lisp_Object window;
+ XSETWINDOW (window, w);
+ enlarge_window (window, 1 - XFASTINT (w->height), 0);
+ }
+}
+
+
+\f
+/* Mark window cursors off for all windows in the window tree rooted
+ at W by setting their phys_cursor_on_p flag to zero. Called from
+ xterm.c, e.g. when a frame is cleared and thereby all cursors on
+ the frame are cleared. */
+
+void
+mark_window_cursors_off (w)
+ struct window *w;
+{
+ while (w)
+ {
+ if (!NILP (w->hchild))
+ mark_window_cursors_off (XWINDOW (w->hchild));
+ else if (!NILP (w->vchild))
+ mark_window_cursors_off (XWINDOW (w->vchild));
+ else
+ w->phys_cursor_on_p = 0;
+
+ w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ }
+}
+
+