+
+/* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
+ HORIZ_FLAG nonzero means adjust the width, moving the right edge.
+ zero means adjust the height, moving the bottom edge.
+
+ Following siblings of the selected window are resized to fulfill
+ the size request. If they become too small in the process, they
+ are not deleted; instead, we signal an error. */
+
+static void
+adjust_window_trailing_edge (window, delta, horiz_flag)
+ Lisp_Object window;
+ int delta, horiz_flag;
+{
+ Lisp_Object parent, child;
+ struct window *p;
+ 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 ();
+
+ if (NILP (window))
+ window = Fselected_window ();
+
+ CHECK_WINDOW (window);
+
+ /* Give up if this window cannot be resized. */
+ if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
+ error ("Window is not resizable");
+
+ while (1)
+ {
+ Lisp_Object first_parallel = Qnil;
+
+ if (NILP (window))
+ {
+ /* This happens if WINDOW on the previous iteration was
+ at top level of the window tree. */
+ Fset_window_configuration (old_config);
+ error ("Specified window edge is fixed");
+ }
+
+ p = XWINDOW (window);
+ parent = p->parent;
+
+ /* See if this level has windows in parallel in the specified
+ direction. If so, set FIRST_PARALLEL to the first one. */
+ if (horiz_flag)
+ {
+ if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
+ first_parallel = XWINDOW (parent)->vchild;
+ else if (NILP (parent) && !NILP (p->next))
+ {
+ /* Handle the vertical chain of main window and minibuffer
+ which has no parent. */
+ first_parallel = window;
+ while (! NILP (XWINDOW (first_parallel)->prev))
+ first_parallel = XWINDOW (first_parallel)->prev;
+ }
+ }
+ else
+ {
+ if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
+ first_parallel = XWINDOW (parent)->hchild;
+ }
+
+ /* If this level's succession is in the desired dimension,
+ and this window is the last one, and there is no higher level,
+ its trailing edge is fixed. */
+ if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
+ && NILP (parent))
+ {
+ Fset_window_configuration (old_config);
+ error ("Specified window edge is fixed");
+ }
+
+ /* Don't make this window too small. */
+ if (XINT (CURSIZE (window)) + delta
+ < (horiz_flag ? window_min_width : window_min_height))
+ {
+ Fset_window_configuration (old_config);
+ error ("Cannot adjust window size as specified");
+ }
+
+ /* Clear out some redisplay caches. */
+ XSETFASTINT (p->last_modified, 0);
+ XSETFASTINT (p->last_overlay_modified, 0);
+
+ /* Adjust this window's edge. */
+ XSETINT (CURSIZE (window),
+ XINT (CURSIZE (window)) + delta);
+
+ /* If this window has following siblings in the desired dimension,
+ make them smaller, and exit the loop.
+
+ (If we reach the top of the tree and can never do this,
+ we will fail and report an error, above.) */
+ if (NILP (first_parallel))
+ {
+ if (!NILP (p->next))
+ {
+ /* This may happen for the minibuffer. In that case
+ the window_deletion_count check below does not work. */
+ if (XINT (CURSIZE (p->next)) - delta <= 0)
+ {
+ Fset_window_configuration (old_config);
+ error ("Cannot adjust window size as specified");
+ }
+
+ XSETINT (CURBEG (p->next),
+ XINT (CURBEG (p->next)) + delta);
+ size_window (p->next, XINT (CURSIZE (p->next)) - delta,
+ horiz_flag, 0, 1, 0);
+ break;
+ }
+ }
+ else
+ /* Here we have a chain of parallel siblings, in the other dimension.
+ Change the size of the other siblings. */
+ for (child = first_parallel;
+ ! NILP (child);
+ child = XWINDOW (child)->next)
+ if (! EQ (child, window))
+ size_window (child, XINT (CURSIZE (child)) + delta,
+ horiz_flag, 0, 0, 1);
+
+ window = parent;
+ }
+
+ /* If we made a window so small it got deleted,
+ we failed. Report failure. */
+ if (delcount != window_deletion_count)
+ {
+ Fset_window_configuration (old_config);
+ error ("Cannot adjust window size as specified");
+ }
+
+ /* Adjust glyph matrices. */
+ adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
+}
+