(Fwindow_end): Don't call temp_set_pt_both with
[bpt/emacs.git] / src / window.c
index e5cb271..dc01b2f 100644 (file)
@@ -54,12 +54,13 @@ 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 P_ ((struct window *, int, int *));
-static int window_fixed_size_p P_ ((struct window *, int, int));
+static int window_min_size P_ ((struct window *, int, int, int *));
 static void size_window P_ ((Lisp_Object, int, int, int));
 static void foreach_window_1 P_ ((struct window *, void (*fn) (), int, int,
                                  int, int));
 static void freeze_window_start P_ ((struct window *, int));
+static int window_fixed_size_p P_ ((struct window *, int, int));
+static void enlarge_window P_ ((Lisp_Object, int, int));
 
 
 /* This is the window in which the terminal's cursor should
@@ -210,6 +211,7 @@ make_window ()
   XSETFASTINT (p->height, 0);
   XSETFASTINT (p->width, 0);
   XSETFASTINT (p->hscroll, 0);
+  p->orig_top = p->orig_height = Qnil;
   p->start = Fmake_marker ();
   p->pointm = Fmake_marker ();
   XSETFASTINT (p->use_time, 0);
@@ -248,10 +250,8 @@ used by that frame.")
     Lisp_Object frame;
 {
   if (NILP (frame))
-    XSETFRAME (frame, selected_frame);
-  else
-    CHECK_LIVE_FRAME (frame, 0);
-
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame, 0);
   return FRAME_MINIBUF_WINDOW (XFRAME (frame));
 }
 
@@ -480,8 +480,8 @@ coordinates_in_window (w, x, y)
           && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
     /* On the mode line.  */
     return 2;
-  else if (WINDOW_WANTS_TOP_LINE_P (w)
-          && *y < top_y + CURRENT_TOP_LINE_HEIGHT (w))
+  else if (WINDOW_WANTS_HEADER_LINE_P (w)
+          && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
     /* On the top line.  */
     return 4;
   else if (*x < left_x || *x >= right_x)
@@ -519,7 +519,7 @@ frame.\n\
 If COORDINATES are in the text portion of WINDOW,\n\
    the coordinates relative to the window are returned.\n\
 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
-If they are in the top mode line of WINDOW, `top-line' is returned.\n\
+If they are in the top mode line of WINDOW, `header-line' is returned.\n\
 If they are in the bitmap-area to the left of the window,\n\
    `left-bitmap-area' is returned, if they are in the area on the right of\n\
    the window, `right-bitmap-area' is returned.\n\
@@ -563,7 +563,7 @@ If they are on the border between WINDOW and its right sibling,\n\
       return Qvertical_line;
 
     case 4:
-      return Qtop_line;
+      return Qheader_line;
 
     case 5:
       return Qleft_bitmap_area;
@@ -581,14 +581,14 @@ If they are on the border between WINDOW and its right sibling,\n\
    set *PART to 1; if it is on the separating line between the window
    and its right sibling, set it to 2; otherwise set it to 0.  If
    there is no window under X, Y return nil and leave *PART
-   unmodified.  TOOLBAR_P non-zero means detect toolbar windows.  */
+   unmodified.  TOOL_BAR_P non-zero means detect tool-bar windows.  */
 
 Lisp_Object
-window_from_coordinates (frame, x, y, part, toolbar_p)
+window_from_coordinates (frame, x, y, part, tool_bar_p)
      FRAME_PTR frame;
      int x, y;
      int *part;
-     int toolbar_p;
+     int tool_bar_p;
 {
   register Lisp_Object tem, first;
   int found;
@@ -609,14 +609,14 @@ window_from_coordinates (frame, x, y, part, toolbar_p)
     }
   while (!EQ (tem, first));
 
-  /* See if it's in the toolbar window, if a toolbar exists.  */
-  if (toolbar_p
-      && WINDOWP (frame->toolbar_window)
-      && XFASTINT (XWINDOW (frame->toolbar_window)->height)
-      && coordinates_in_window (XWINDOW (frame->toolbar_window), &x, &y))
+  /* See if it's in the tool bar window, if a tool bar exists.  */
+  if (tool_bar_p
+      && WINDOWP (frame->tool_bar_window)
+      && XFASTINT (XWINDOW (frame->tool_bar_window)->height)
+      && coordinates_in_window (XWINDOW (frame->tool_bar_window), &x, &y))
     {
       *part = 0;
-      return frame->toolbar_window;
+      return frame->tool_bar_window;
     }
 
   return Qnil;
@@ -634,9 +634,8 @@ column 0.")
   struct frame *f;
 
   if (NILP (frame))
-    XSETFRAME (frame, selected_frame);
-  else
-    CHECK_LIVE_FRAME (frame, 2);
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame, 2);
   f = XFRAME (frame);
 
   /* Check that arguments are integers or floats.  */
@@ -721,8 +720,21 @@ if it isn't already recorded.")
            && XFASTINT (w->last_modified) >= MODIFF))
     {
       int opoint = PT, opoint_byte = PT_BYTE;
-      TEMP_SET_PT_BOTH (XMARKER (w->start)->charpos,
-                       XMARKER (w->start)->bytepos);
+
+      /* In case W->start is out of the range, use something
+         reasonable.  This situation occured when loading a file with
+         `-l' containing a call to `rmail' with subsequent other
+         commands.  At the end, W->start happened to be BEG, while
+         rmail had already narrowed the buffer.  This leads to an
+         abort in temp_set_pt_both.  */
+      if (XMARKER (w->start)->charpos < BEGV)
+       TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
+      else if (XMARKER (w->start)->charpos > ZV)
+       TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
+      else
+       TEMP_SET_PT_BOTH (XMARKER (w->start)->charpos,
+                         XMARKER (w->start)->bytepos);
+      
       Fvertical_motion (make_number (window_internal_height (w)), Qnil);
       XSETINT (value, PT);
       TEMP_SET_PT_BOTH (opoint, opoint_byte);
@@ -926,6 +938,7 @@ replace_window (old, replacement)
   XSETFASTINT (p->window_end_pos, 0);
   p->window_end_valid = Qnil;
   p->frozen_window_start_p = 0;
+  p->orig_top = p->orig_height = Qnil;
 
   p->next = tem = o->next;
   if (!NILP (tem))
@@ -1213,7 +1226,7 @@ DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
                   If that happens, go back to the selected frame
                   so we can complete the cycle.  */
                if (EQ (tem, tem1))
-                 XSETFRAME (tem, selected_frame);
+                 tem = selected_frame;
              }
            tem = FRAME_ROOT_WINDOW (XFRAME (tem));
 
@@ -1232,6 +1245,8 @@ DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
            window = XWINDOW (window)->vchild;
          else break;
        }
+
+      QUIT;
     }
   /* Which windows are acceptable?
      Exit the loop and accept this window if
@@ -1365,7 +1380,7 @@ DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
                   If that happens, go back to the selected frame
                   so we can complete the cycle.  */
                if (EQ (tem, tem1))
-                 XSETFRAME (tem, selected_frame);
+                 tem = selected_frame;
              }
            /* If this frame has a minibuffer, find that window first,
               because it is conceptually the last window in that frame.  */
@@ -1476,7 +1491,7 @@ window_loop (type, obj, mini, frames)
   if (FRAMEP (frames))
     frame = XFRAME (frames);
   else if (NILP (frames))
-    frame = selected_frame;
+    frame = SELECTED_FRAME ();
   else
     frame = 0;
   if (frame)
@@ -1496,7 +1511,7 @@ window_loop (type, obj, mini, frames)
   else if (frame)
     w = FRAME_SELECTED_WINDOW (frame);
   else
-    w = FRAME_SELECTED_WINDOW (selected_frame);
+    w = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
 
   /* Figure out the last window we're going to mess with.  Since
      Fnext_window, given the same options, is guaranteed to go in a
@@ -1970,22 +1985,27 @@ window_fixed_size_p (w, width_p, check_siblings_p)
     }
   else if (BUFFERP (w->buffer))
     {
-      Lisp_Object val;
-      struct buffer *old = current_buffer;
-
-      current_buffer = XBUFFER (w->buffer);
-      val = find_symbol_value (Qwindow_size_fixed);
-      current_buffer = old;
-
-      fixed_p = 0;
-      if (!EQ (val, Qunbound))
+      if (w->height_fixed_p && !width_p)
+       fixed_p = 1;
+      else
        {
-         fixed_p = !NILP (val);
-         
-         if (fixed_p
-             && ((EQ (val, Qheight) && width_p)
-                 || (EQ (val, Qwidth) && !width_p)))
-           fixed_p = 0;
+         struct buffer *old = current_buffer;
+         Lisp_Object val;
+      
+         current_buffer = XBUFFER (w->buffer);
+         val = find_symbol_value (Qwindow_size_fixed);
+         current_buffer = old;
+
+         fixed_p = 0;
+         if (!EQ (val, Qunbound))
+           {
+             fixed_p = !NILP (val);
+             
+             if (fixed_p
+                 && ((EQ (val, Qheight) && width_p)
+                     || (EQ (val, Qwidth) && !width_p)))
+               fixed_p = 0;
+           }
        }
 
       /* Can't tell if this one is resizable without looking at
@@ -2089,7 +2109,7 @@ window_min_size_1 (w, width_p)
        {
          if (MINI_WINDOW_P (w)
              || (!WINDOW_WANTS_MODELINE_P (w)
-                 && !WINDOW_WANTS_TOP_LINE_P (w)))
+                 && !WINDOW_WANTS_HEADER_LINE_P (w)))
            size = 1;
          else
            size = window_min_height;
@@ -2102,17 +2122,22 @@ window_min_size_1 (w, width_p)
 
 /* 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.  Set *FIXED to 1 if W is
-   fixed-size unless FIXED is null.  */
+   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, fixed)
+window_min_size (w, width_p, ignore_fixed_p, fixed)
      struct window *w;
-     int width_p, *fixed;
+     int width_p, ignore_fixed_p, *fixed;
 {
   int size, fixed_p;
 
-  fixed_p = window_fixed_size_p (w, width_p, 1);
+  if (ignore_fixed_p)
+    fixed_p = 0;
+  else
+    fixed_p = window_fixed_size_p (w, width_p, 1);
+  
   if (fixed)
     *fixed = fixed_p;
   
@@ -2120,7 +2145,7 @@ window_min_size (w, width_p, fixed)
     size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
   else
     size = window_min_size_1 (w, width_p);
-
+      
   return size;
 }
 
@@ -2382,8 +2407,7 @@ set_window_buffer (window, buffer, run_hooks_p)
     }
 
   /* Set left and right marginal area width from buffer.  */
-  Fset_window_margins (b->left_margin_width, b->right_margin_width,
-                      window);
+  Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
 
   if (run_hooks_p)
     {
@@ -2408,7 +2432,6 @@ BUFFER can be a buffer or buffer name.")
 {
   register Lisp_Object tem;
   register struct window *w = decode_window (window);
-  struct buffer *b;
 
   buffer = Fget_buffer (buffer);
   CHECK_BUFFER (buffer, 1);
@@ -2451,6 +2474,7 @@ select_window_1 (window, recordflag)
 {
   register struct window *w;
   register struct window *ow = XWINDOW (selected_window);
+  struct frame *sf;
 
   CHECK_LIVE_WINDOW (window, 0);
 
@@ -2469,7 +2493,8 @@ select_window_1 (window, recordflag)
                     BUF_PT_BYTE (XBUFFER (ow->buffer)));
 
   selected_window = window;
-  if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
+  sf = SELECTED_FRAME ();
+  if (XFRAME (WINDOW_FRAME (w)) != sf)
     {
       XFRAME (WINDOW_FRAME (w))->selected_window = window;
       /* Use this rather than Fhandle_switch_frame
@@ -2479,7 +2504,7 @@ select_window_1 (window, recordflag)
       Fselect_frame (WINDOW_FRAME (w), Qnil);
     }
   else
-    selected_frame->selected_window = window;
+    sf->selected_window = window;
 
   if (recordflag)
     record_buffer (w->buffer);
@@ -2520,15 +2545,19 @@ static Lisp_Object
 display_buffer_1 (window)
      Lisp_Object window;
 {
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
+  Lisp_Object frame = XWINDOW (window)->frame;
+  FRAME_PTR f = XFRAME (frame);
+  
   FRAME_SAMPLE_VISIBILITY (f);
-  if (f != selected_frame)
+  
+  if (!EQ (frame, selected_frame))
     {
       if (FRAME_ICONIFIED_P (f))
-       Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
+       Fmake_frame_visible (frame);
       else if (FRAME_VISIBLE_P (f))
-       Fraise_frame (WINDOW_FRAME (XWINDOW (window)));
+       Fraise_frame (frame);
     }
+  
   return window;
 }
 
@@ -2625,6 +2654,7 @@ If FRAME is nil, search only the selected frame\n\
      register Lisp_Object buffer, not_this_window, frame;
 {
   register Lisp_Object window, tem, swp;
+  struct frame *f;
 
   swp = Qnil;
   buffer = Fget_buffer (buffer);
@@ -2684,17 +2714,17 @@ If FRAME is nil, search only the selected frame\n\
       return display_buffer_1 (window);
     }
 
+  f = SELECTED_FRAME ();
   if (pop_up_windows
-      || FRAME_MINIBUF_ONLY_P (selected_frame)
+      || FRAME_MINIBUF_ONLY_P (f)
       /* If the current frame is a special display frame,
         don't try to reuse its windows.  */
-      || !NILP (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->dedicated)
-      )
+      || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
     {
       Lisp_Object frames;
 
       frames = Qnil;
-      if (FRAME_MINIBUF_ONLY_P (selected_frame))
+      if (FRAME_MINIBUF_ONLY_P (f))
        XSETFRAME (frames, last_nonminibuf_frame);
       /* Don't try to create a window if would get an error */
       if (split_height_threshold < window_min_height << 1)
@@ -2706,8 +2736,7 @@ If FRAME is nil, search only the selected frame\n\
 
       /* If the frame we would try to split cannot be split,
         try other frames.  */
-      if (FRAME_NO_SPLIT_P (NILP (frames) ? selected_frame
-                           : last_nonminibuf_frame))
+      if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
        {
          /* Try visible frames first.  */
          window = Fget_largest_window (Qvisible);
@@ -2775,14 +2804,9 @@ If FRAME is nil, search only the selected frame\n\
            {
              int total = (XFASTINT (XWINDOW (other)->height)
                           + XFASTINT (XWINDOW (window)->height));
-             Lisp_Object old_selected_window;
-             old_selected_window = selected_window;
-
-             selected_window = upper;
-             change_window_height ((total / 2
-                                    - XFASTINT (XWINDOW (upper)->height)),
-                                   0);
-             selected_window = old_selected_window;
+             enlarge_window (upper,
+                             total / 2 - XFASTINT (XWINDOW (upper)->height),
+                             0);
            }
        }
     }
@@ -2817,7 +2841,7 @@ temp_output_buffer_show (buf)
     {
       window = Fdisplay_buffer (buf, Qnil, Qnil);
 
-      if (XFRAME (XWINDOW (window)->frame) != selected_frame)
+      if (!EQ (XWINDOW (window)->frame, selected_frame))
        Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
       Vminibuf_scroll_window = window;
       w = XWINDOW (window);
@@ -3016,7 +3040,7 @@ From program, optional second arg non-nil means grow sideways ARG columns.")
      register Lisp_Object arg, side;
 {
   CHECK_NUMBER (arg, 0);
-  change_window_height (XINT (arg), !NILP (side));
+  enlarge_window (selected_window, XINT (arg), !NILP (side));
 
   if (! NILP (Vwindow_configuration_change_hook))
     call1 (Vrun_hooks, Qwindow_configuration_change_hook);
@@ -3031,7 +3055,7 @@ From program, optional second arg non-nil means shrink sideways arg columns.")
      register Lisp_Object arg, side;
 {
   CHECK_NUMBER (arg, 0);
-  change_window_height (-XINT (arg), !NILP (side));
+  enlarge_window (selected_window, -XINT (arg), !NILP (side));
 
   if (! NILP (Vwindow_configuration_change_hook))
     call1 (Vrun_hooks, Qwindow_configuration_change_hook);
@@ -3068,11 +3092,12 @@ window_width (window)
    fullfil the size request.  If they become too small in the process,
    they will be deleted.  */
 
-void
-change_window_height (delta, widthflag)
+static void
+enlarge_window (window, delta, widthflag)
+     Lisp_Object window;
      int delta, widthflag;
 {
-  Lisp_Object parent, window, next, prev;
+  Lisp_Object parent, next, prev;
   struct window *p;
   int *sizep, maximum;
   int (*sizefun) P_ ((Lisp_Object))
@@ -3085,7 +3110,6 @@ change_window_height (delta, widthflag)
   check_min_window_sizes ();
 
   /* Give up if this window cannot be resized.  */
-  window = selected_window;
   if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
     error ("Window is not resizable");
 
@@ -3118,10 +3142,10 @@ change_window_height (delta, widthflag)
     maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
                : !NILP (p->next) ? ((*sizefun) (p->next)
                                     - window_min_size (XWINDOW (p->next),
-                                                       widthflag, 0))
+                                                       widthflag, 0, 0))
                : !NILP (p->prev) ? ((*sizefun) (p->prev)
                                     - window_min_size (XWINDOW (p->prev),
-                                                       widthflag, 0))
+                                                       widthflag, 0, 0))
                /* This is a frame with only one window, a minibuffer-only
                   or a minibufferless frame.  */
                : (delta = 0));
@@ -3133,7 +3157,7 @@ change_window_height (delta, widthflag)
       delta = maxdelta;
   }
 
-  if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0))
+  if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
     {
       delete_window (window);
       return;
@@ -3146,10 +3170,10 @@ change_window_height (delta, widthflag)
   maximum = 0;
   for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
     maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
-                                                   widthflag, 0);
+                                                   widthflag, 0, 0);
   for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
     maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
-                                                   widthflag, 0);
+                                                   widthflag, 0, 0);
 
   /* If we can get it all from them, do so.  */
   if (delta <= maximum)
@@ -3170,7 +3194,7 @@ change_window_height (delta, widthflag)
            {
              int this_one = ((*sizefun) (next)
                              - window_min_size (XWINDOW (next),
-                                                widthflag, &fixed_p));
+                                                widthflag, 0, &fixed_p));
              if (!fixed_p)
                {
                  if (this_one > delta)
@@ -3192,7 +3216,7 @@ change_window_height (delta, widthflag)
            {
              int this_one = ((*sizefun) (prev)
                              - window_min_size (XWINDOW (prev),
-                                                widthflag, &fixed_p));
+                                                widthflag, 0, &fixed_p));
              if (!fixed_p)
                {
                  if (this_one > delta)
@@ -3303,6 +3327,239 @@ change_window_height (delta, widthflag)
 #undef CURSIZE
 
 
+\f
+/***********************************************************************
+                       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 = 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
@@ -3976,7 +4233,7 @@ struct save_window_data
     EMACS_INT size_from_Lisp_Vector_struct;
     struct Lisp_Vector *next_from_Lisp_Vector_struct;
     Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
-    Lisp_Object frame_toolbar_lines;
+    Lisp_Object frame_tool_bar_lines;
     Lisp_Object selected_frame;
     Lisp_Object current_window;
     Lisp_Object current_buffer;
@@ -4091,7 +4348,7 @@ the return value is nil.  Otherwise the value is t.")
       int previous_frame_height = FRAME_HEIGHT (f);
       int previous_frame_width =  FRAME_WIDTH  (f);
       int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
-      int previous_frame_toolbar_lines = FRAME_TOOLBAR_LINES (f);
+      int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
 
       /* The mouse highlighting code could get screwed up
         if it runs during this.  */
@@ -4106,9 +4363,9 @@ the return value is nil.  Otherwise the value is t.")
          != previous_frame_menu_bar_lines)
        x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
 #ifdef HAVE_WINDOW_SYSTEM
-      if (XFASTINT (data->frame_toolbar_lines)
-         != previous_frame_toolbar_lines)
-       x_set_toolbar_lines (f, data->frame_toolbar_lines, make_number (0));
+      if (XFASTINT (data->frame_tool_bar_lines)
+         != previous_frame_tool_bar_lines)
+       x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
 #endif
 #endif
 
@@ -4273,9 +4530,9 @@ the return value is nil.  Otherwise the value is t.")
        x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
                              make_number (0));
 #ifdef HAVE_WINDOW_SYSTEM
-      if (previous_frame_toolbar_lines != FRAME_TOOLBAR_LINES (f))
-       x_set_toolbar_lines (f, make_number (previous_frame_toolbar_lines),
-                            make_number (0));
+      if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
+       x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
+                             make_number (0));
 #endif
 #endif
 
@@ -4512,12 +4769,9 @@ redirection (see `redirect-frame-focus').")
   FRAME_PTR f;
 
   if (NILP (frame))
-    f = selected_frame;
-  else
-    {
-      CHECK_LIVE_FRAME (frame, 0);
-      f = XFRAME (frame);
-    }
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame, 0);
+  f = XFRAME (frame);
 
   n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
   vec = allocate_vectorlike (VECSIZE (struct save_window_data));
@@ -4529,8 +4783,8 @@ redirection (see `redirect-frame-focus').")
   XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
   XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
   XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
-  XSETFASTINT (data->frame_toolbar_lines, FRAME_TOOLBAR_LINES (f));
-  XSETFRAME (data->selected_frame, selected_frame);
+  XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
+  data->selected_frame = selected_frame;
   data->current_window = FRAME_SELECTED_WINDOW (f);
   XSETBUFFER (data->current_buffer, current_buffer);
   data->minibuf_scroll_window = Vminibuf_scroll_window;
@@ -4582,27 +4836,26 @@ First parameter LEFT-WIDTH specifies the number of character\n\
 cells to reserve for the left marginal area.  Second parameter\n\
 RIGHT-WIDTH does the same for the right marginal area.\n\
 A nil width parameter means no margin.")
-  (left, right, window)
+  (window, left, right)
      Lisp_Object window, left, right;
 {
   struct window *w = decode_window (window);
-  struct frame *f = XFRAME (w->frame);
 
   if (!NILP (left))
-    CHECK_NUMBER_OR_FLOAT (left, 0);
+    CHECK_NUMBER_OR_FLOAT (left, 1);
   if (!NILP (right))
-    CHECK_NUMBER_OR_FLOAT (right, 0);
+    CHECK_NUMBER_OR_FLOAT (right, 2);
 
   /* Check widths < 0 and translate a zero width to nil.
      Margins that are too wide have to be checked elsewhere.  */
   if ((INTEGERP (left) && XINT (left) < 0)
-      || (FLOATP (left) && XFLOAT (left)->data <= 0))
+      || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
      XSETFASTINT (left, 0);
   if (INTEGERP (left) && XFASTINT (left) == 0)
     left = Qnil;
   
   if ((INTEGERP (right) && XINT (right) < 0)
-      || (FLOATP (right) && XFLOAT (right)->data <= 0))
+      || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
     XSETFASTINT (right, 0);
   if (INTEGERP (right) && XFASTINT (right) == 0)
     right = Qnil;
@@ -4643,43 +4896,51 @@ Value is a multiple of the canonical character height of WINDOW.")
   (window)
      Lisp_Object window;
 {
+  Lisp_Object result;
   struct frame *f;
   struct window *w;
   
   if (NILP (window))
     window = selected_window;
+  else
+    CHECK_WINDOW (window, 0);
   w = XWINDOW (window);
   f = XFRAME (w->frame);
   
   if (FRAME_WINDOW_P (f))
-    return CANON_Y_FROM_PIXEL_Y (f, w->vscroll);
+    result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
   else
-    return make_number (0);
+    result = make_number (0);
+  return result;
 }
 
 
 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
-       1, 2, 0,
-  "Set amount by WINDOW should be scrolled vertically to VSCROLL.\n\
+       2, 2, 0,
+  "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
 WINDOW nil or omitted means use the selected window.  VSCROLL is a\n\
-multiple of the canonical character height of WINDOW.")
-  (vscroll, window)
-     Lisp_Object vscroll, window;
+non-negative multiple of the canonical character height of WINDOW.")
+  (window, vscroll)
+     Lisp_Object window, vscroll;
 {
   struct window *w;
   struct frame *f;
   
-  CHECK_NUMBER_OR_FLOAT (vscroll, 0);
-  
   if (NILP (window))
     window = selected_window;
+  else
+    CHECK_WINDOW (window, 0);
+  CHECK_NUMBER_OR_FLOAT (vscroll, 1);
+  
   w = XWINDOW (window);
   f = XFRAME (w->frame);
 
   if (FRAME_WINDOW_P (f))
     {
       int old_dy = w->vscroll;
-      w->vscroll = min (0, CANON_Y_UNIT (f) * XFLOATINT (vscroll));
+      
+      w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
+      w->vscroll = min (w->vscroll, 0);
 
       /* Adjust glyph matrix of the frame if the virtual display
         area becomes larger than before.  */
@@ -4690,7 +4951,7 @@ multiple of the canonical character height of WINDOW.")
       XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
     }
   
-  return Qnil;
+  return Fwindow_vscroll (window);
 }
        
 \f
@@ -4883,11 +5144,12 @@ and scrolling positions.")
 void
 init_window_once ()
 {
-  selected_frame = make_terminal_frame ();
-  XSETFRAME (Vterminal_frame, selected_frame);
-  minibuf_window = selected_frame->minibuffer_window;
-  selected_window = selected_frame->selected_window;
-  last_nonminibuf_frame = selected_frame;
+  struct frame *f = make_terminal_frame ();
+  XSETFRAME (selected_frame, f);
+  Vterminal_frame = selected_frame;
+  minibuf_window = f->minibuffer_window;
+  selected_window = f->selected_window;
+  last_nonminibuf_frame = f;
 
   window_initialized = 1;
 }