(displayed_window_lines): Take empty lines at
[bpt/emacs.git] / src / window.c
index e5cb271..1289d18 100644 (file)
@@ -36,6 +36,12 @@ Boston, MA 02111-1307, USA.  */
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif /* HAVE_X_WINDOWS */
+#ifdef WINDOWSNT
+#include "w32term.h"
+#endif
+#ifdef MSDOS
+#include "msdos.h"
+#endif
 
 #ifndef max
 #define max(a, b) ((a) < (b) ? (b) : (a))
@@ -54,12 +60,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 +217,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 +256,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));
 }
 
@@ -452,18 +458,22 @@ coordinates_in_window (w, x, y)
   int left_x, right_x, top_y, bottom_y;
   int flags_area_width = FRAME_LEFT_FLAGS_AREA_WIDTH (f);
 
+  /* In what's below, we subtract 1 when computing right_x because we
+     want the rightmost pixel, which is given by left_pixel+width-1.  */
   if (w->pseudo_window_p)
     {
       left_x = 0;
-      right_x = XFASTINT (w->width) * CANON_Y_UNIT (f);
+      right_x = XFASTINT (w->width) * CANON_Y_UNIT (f) - 1;
       top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
       bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
     }
   else
     {
-      left_x = WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
-      right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w);
-      top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
+      left_x = (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w)
+               - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
+      right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w) - 1;
+      top_y = (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w)
+              - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
       bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
     }
 
@@ -480,8 +490,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 +529,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 +573,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 +591,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 +619,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 +644,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 +730,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);
@@ -865,9 +887,6 @@ unshow_buffer (w)
   if (b != XMARKER (w->pointm)->buffer)
     abort ();
 
-  if (w == XWINDOW (b->last_selected_window))
-    b->last_selected_window = Qnil;
-
 #if 0
   if (w == XWINDOW (selected_window)
       || ! EQ (buf, XWINDOW (selected_window)->buffer))
@@ -886,7 +905,11 @@ unshow_buffer (w)
   /* Point in the selected window's buffer
      is actually stored in that buffer, and the window's pointm isn't used.
      So don't clobber point in that buffer.  */
-  if (! EQ (buf, XWINDOW (selected_window)->buffer))
+  if (! EQ (buf, XWINDOW (selected_window)->buffer)
+      /* This line helps to fix Horsley's testbug.el bug.  */
+      && !(WINDOWP (b->last_selected_window)
+          && w != XWINDOW (b->last_selected_window)
+          && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
     temp_set_point_both (b,
                         clip_to_bounds (BUF_BEGV (b),
                                         XMARKER (w->pointm)->charpos,
@@ -894,6 +917,10 @@ unshow_buffer (w)
                         clip_to_bounds (BUF_BEGV_BYTE (b),
                                         marker_byte_position (w->pointm),
                                         BUF_ZV_BYTE (b)));
+  
+  if (WINDOWP (b->last_selected_window)
+      && w == XWINDOW (b->last_selected_window))
+    b->last_selected_window = Qnil;
 }
 
 /* Put replacement into the window structure in place of old. */
@@ -926,6 +953,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))
@@ -1040,9 +1068,11 @@ delete_window (window)
       unchain_marker (p->start);
     }
 
-  /* Free window glyph matrices.
-     It is sure that they are allocated again when ADJUST_GLYPHS
-     is called. */
+  /* Free window glyph matrices.  It is sure that they are allocated
+     again when ADJUST_GLYPHS is called.  Block input so that expose
+     events and other events that access glyph matrices are not
+     processed while we are changing them.  */
+  BLOCK_INPUT;
   free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (frame)));
 
   tem = p->next;
@@ -1101,6 +1131,7 @@ delete_window (window)
 
   /* Adjust glyph matrices. */
   adjust_glyphs (frame);
+  UNBLOCK_INPUT;
 }
 \f
 
@@ -1213,7 +1244,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 +1263,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 +1398,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 +1509,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 +1529,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
@@ -1604,7 +1637,8 @@ window_loop (type, obj, mini, frames)
          case GET_LARGEST_WINDOW:
            /* Ignore dedicated windows and minibuffers.  */
            if (MINI_WINDOW_P (XWINDOW (w))
-               || !NILP (XWINDOW (w)->dedicated))
+               || !NILP (XWINDOW (w)->dedicated)
+               || NILP (best_window))
              break;
            {
              struct window *best_window_ptr = XWINDOW (best_window);
@@ -1970,22 +2004,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 +2128,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 +2141,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 +2164,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 +2426,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,8 +2451,8 @@ BUFFER can be a buffer or buffer name.")
 {
   register Lisp_Object tem;
   register struct window *w = decode_window (window);
-  struct buffer *b;
 
+  XSETWINDOW (window, w);
   buffer = Fget_buffer (buffer);
   CHECK_BUFFER (buffer, 1);
 
@@ -2444,13 +2487,17 @@ selects the buffer of the selected window before each command.")
   return select_window_1 (window, 1);
 }
 \f
+/* Note that selected_window can be nil
+   when this is called from Fset_window_configuration.  */
 static Lisp_Object
 select_window_1 (window, recordflag)
      register Lisp_Object window;
      int recordflag;
 {
   register struct window *w;
-  register struct window *ow = XWINDOW (selected_window);
+  register struct window *ow;
+  struct frame *sf;
 
   CHECK_LIVE_WINDOW (window, 0);
 
@@ -2463,13 +2510,18 @@ select_window_1 (window, recordflag)
   if (EQ (window, selected_window))
     return window;
 
-  if (! NILP (ow->buffer))
-    set_marker_both (ow->pointm, ow->buffer,
-                    BUF_PT (XBUFFER (ow->buffer)),
-                    BUF_PT_BYTE (XBUFFER (ow->buffer)));
+  if (!NILP (selected_window))
+    {
+      ow = XWINDOW (selected_window);
+      if (! NILP (ow->buffer))
+       set_marker_both (ow->pointm, ow->buffer,
+                        BUF_PT (XBUFFER (ow->buffer)),
+                        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 +2531,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 +2572,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 +2681,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 +2741,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 +2763,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 +2831,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 +2868,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 +3067,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 +3082,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);
@@ -3057,10 +3108,10 @@ window_width (window)
 
        
 #define CURBEG(w) \
-  *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
+  *(widthflag ? &(XWINDOW (w)->left) : &(XWINDOW (w)->top))
 
 #define CURSIZE(w) \
-  *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
+  *(widthflag ? &(XWINDOW (w)->width) : &(XWINDOW (w)->height))
 
 
 /* Enlarge selected_window by DELTA.  WIDTHFLAG non-zero means
@@ -3068,13 +3119,15 @@ 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;
+  Lisp_Object *sizep;
+  int maximum;
   int (*sizefun) P_ ((Lisp_Object))
     = widthflag ? window_width : window_height;
   void (*setsizefun) P_ ((Lisp_Object, int, int))
@@ -3085,7 +3138,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");
 
@@ -3115,13 +3167,13 @@ change_window_height (delta, widthflag)
   {
     register int maxdelta;
 
-    maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
+    maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*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 +3185,7 @@ change_window_height (delta, widthflag)
       delta = maxdelta;
   }
 
-  if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0))
+  if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
     {
       delete_window (window);
       return;
@@ -3146,10 +3198,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,14 +3222,14 @@ 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)
                    this_one = delta;
                  
                  (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
-                 (*setsizefun) (window, *sizep + this_one, 0);
+                 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
 
                  delta -= this_one;
                }
@@ -3192,7 +3244,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)
@@ -3201,7 +3253,7 @@ change_window_height (delta, widthflag)
                  first_affected = prev;
                  
                  (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
-                 (*setsizefun) (window, *sizep + this_one, 0);
+                 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
 
                  delta -= this_one;
                }
@@ -3219,7 +3271,7 @@ change_window_height (delta, widthflag)
       for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
           prev = next, next = XWINDOW (next)->next)
        {
-         CURBEG (next) = CURBEG (prev) + (*sizefun) (prev);
+         XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
          /* This does not change size of NEXT,
             but it propagates the new top edge to its children */
          (*setsizefun) (next, (*sizefun) (next), 0);
@@ -3233,7 +3285,7 @@ change_window_height (delta, widthflag)
       /* If trying to grow this window to or beyond size of the parent,
         make delta1 so big that, on shrinking back down,
         all the siblings end up with less than one line and are deleted.  */
-      if (opht <= *sizep + delta)
+      if (opht <= XINT (*sizep) + delta)
        delta1 = opht * opht * 2;
       else
        {
@@ -3281,8 +3333,8 @@ change_window_height (delta, widthflag)
 
       /* Add delta1 lines or columns to this window, and to the parent,
         keeping things consistent while not affecting siblings.  */
-      CURSIZE (parent) = opht + delta1;
-      (*setsizefun) (window, *sizep + delta1, 0);
+      XSETINT (CURSIZE (parent), opht + delta1);
+      (*setsizefun) (window, XINT (*sizep) + delta1, 0);
 
       /* Squeeze out delta1 lines or columns from our parent,
         shriking this window and siblings proportionately.
@@ -3303,6 +3355,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 = 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
@@ -3896,6 +4181,11 @@ redraws with point in the center of the current window.")
   if (NILP (arg))
     {
       extern int frame_garbaged;
+      int i;
+
+      /* Invalidate pixel data calculated for all compositions.  */
+      for (i = 0; i < n_compositions; i++)
+       composition_table[i]->font = NULL;
 
       Fredraw_frame (w->frame);
       SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
@@ -3926,6 +4216,36 @@ redraws with point in the center of the current window.")
 
   return Qnil;
 }
+
+
+/* Value is the number of lines actually displayed in window W,
+   as opposed to its height.  */
+
+static int
+displayed_window_lines (w)
+     struct window *w;
+{
+  struct it it;
+  struct text_pos start;
+  int height = window_box_height (w);
+
+  SET_TEXT_POS_FROM_MARKER (start, w->start);
+  start_display (&it, w, start);
+  move_it_vertically (&it, height);
+
+  /* Add in empty lines at the bottom of the window.  */
+  if (it.current_y < height)
+    {
+      struct frame *f = XFRAME (w->frame);
+      int rest = height - it.current_y;
+      int lines = (rest + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
+      it.vpos += lines;
+    }
+  
+  return it.vpos;
+}
+
+
 \f
 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
   1, 1, "P",
@@ -3934,26 +4254,17 @@ With no argument, position point at center of window.\n\
 An argument specifies vertical position within the window;\n\
 zero means top of window, negative means relative to bottom of window.")
   (arg)
-     register Lisp_Object arg;
+     Lisp_Object arg;
 {
-  register struct window *w = XWINDOW (selected_window);
-  register int height = window_internal_height (w);
-  register int start;
+  struct window *w = XWINDOW (selected_window);
+  int lines, start;
   Lisp_Object window;
 
-  if (NILP (arg))
-    XSETFASTINT (arg, height / 2);
-  else
-    {
-      arg = Fprefix_numeric_value (arg);
-      if (XINT (arg) < 0)
-       XSETINT (arg, XINT (arg) + height);
-    }
-
+  window = selected_window;
   start = marker_position (w->start);
-  XSETWINDOW (window, w);
   if (start < BEGV || start > ZV)
     {
+      int height = window_internal_height (w);
       Fvertical_motion (make_number (- (height / 2)), window);
       set_marker_both (w->start, w->buffer, PT, PT_BYTE);
       w->start_at_line_beg = Fbolp ();
@@ -3962,6 +4273,16 @@ zero means top of window, negative means relative to bottom of window.")
   else
     Fgoto_char (w->start);
 
+  lines = displayed_window_lines (w);
+  if (NILP (arg))
+    XSETFASTINT (arg, lines / 2);
+  else
+    {
+      arg = Fprefix_numeric_value (arg);
+      if (XINT (arg) < 0)
+       XSETINT (arg, XINT (arg) + lines);
+    }
+
   return Fvertical_motion (arg, window);
 }
 
@@ -3976,7 +4297,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 +4412,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,12 +4427,16 @@ 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
 
+      /* "Swap out" point from the selected window
+        into its buffer.  We do this now, before
+        restoring the window contents, and prevent it from
+        being done later on when we select a new window.  */
       if (! NILP (XWINDOW (selected_window)->buffer))
        {
          w = XWINDOW (selected_window);
@@ -4247,6 +4572,11 @@ the return value is nil.  Otherwise the value is t.")
        }
 
       FRAME_ROOT_WINDOW (f) = data->root_window;
+      /* Prevent "swapping out point" in the old selected window
+        using the buffer that has been restored into it.
+        That swapping out has already been done,
+        near the beginning of this function.  */
+      selected_window = Qnil;
       Fselect_window (data->current_window);
       XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
        = selected_window;
@@ -4273,9 +4603,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 +4842,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 +4856,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;
@@ -4554,8 +4881,8 @@ DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
   "Execute body, preserving window sizes and contents.\n\
 Restore which buffer appears in which window, where display starts,\n\
 and the value of point and mark for each window.\n\
+Also restore the choice of selected window.\n\
 Also restore which buffer is current.\n\
-But do not preserve point in the current buffer.\n\
 Does not restore the value of point in current buffer.")
   (args)
      Lisp_Object args;
@@ -4575,34 +4902,33 @@ Does not restore the value of point in current buffer.")
  ***********************************************************************/
 
 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
-       2, 3, "",
+       2, 3, 0,
   "Set width of marginal areas of window WINDOW.\n\
-If window is nil or omitted, set margins of the currently selected window.\n\
+If window is nil, set margins of the currently selected window.\n\
 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 +4969,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 +5024,7 @@ multiple of the canonical character height of WINDOW.")
       XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
     }
   
-  return Qnil;
+  return Fwindow_vscroll (window);
 }
        
 \f
@@ -4744,6 +5078,7 @@ freeze_window_start (w, freeze_p)
   if (w == XWINDOW (selected_window)
       || MINI_WINDOW_P (w)
       || (MINI_WINDOW_P (XWINDOW (selected_window))
+         && ! NILP (Vminibuf_scroll_window)
          && w == XWINDOW (Vminibuf_scroll_window)))
     freeze_p = 0;
   
@@ -4780,6 +5115,11 @@ compare_window_configurations (c1, c2, ignore_positions)
   struct Lisp_Vector *sw1, *sw2;
   int i;
 
+  if (!WINDOW_CONFIGURATIONP (c1))
+    wrong_type_argument (Qwindow_configuration_p, c1);
+  if (!WINDOW_CONFIGURATIONP (c2))
+    wrong_type_argument (Qwindow_configuration_p, c2);
+  
   d1 = (struct save_window_data *) XVECTOR (c1);
   d2 = (struct save_window_data *) XVECTOR (c2);
   sw1 = XVECTOR (d1->saved_windows);
@@ -4883,11 +5223,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;
 }