lread.c (init_lread): Fixing typo HAVE_CARBON test logic
[bpt/emacs.git] / src / window.c
index f5f67a6..f830c88 100644 (file)
@@ -279,6 +279,7 @@ make_window ()
   p->fringes_outside_margins = Qnil;
   p->scroll_bar_width = Qnil;
   p->vertical_scroll_bar_type = Qt;
+  p->overlay_arrow_bitmap = 0;
 
   Vwindow_list = Qnil;
   return val;
@@ -305,7 +306,8 @@ used by that frame.  */)
 }
 
 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
-       doc: /* Returns non-nil if WINDOW is a minibuffer window.  */)
+       doc: /* Returns non-nil if WINDOW is a minibuffer window.
+WINDOW defaults to the selected window.  */)
      (window)
      Lisp_Object window;
 {
@@ -320,7 +322,11 @@ DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
 Return nil if that position is scrolled vertically out of view.
 If a character is only partially visible, nil is returned, unless the
 optional argument PARTIALLY is non-nil.
-POS defaults to point in WINDOW; WINDOW defaults to the selected window.  */)
+POS defaults to point in WINDOW; WINDOW defaults to the selected window.
+
+If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
+return value is a list (X Y PARTIAL) where X and Y are the pixel relative
+coordinate  */)
      (pos, window, partially)
      Lisp_Object pos, window, partially;
 {
@@ -328,8 +334,9 @@ POS defaults to point in WINDOW; WINDOW defaults to the selected window.  */)
   register int posint;
   register struct buffer *buf;
   struct text_pos top;
-  Lisp_Object in_window;
-  int fully_p;
+  Lisp_Object in_window = Qnil;
+  int fully_p = 1;
+  int x, y;
 
   w = decode_window (window);
   buf = XBUFFER (w->buffer);
@@ -345,38 +352,20 @@ POS defaults to point in WINDOW; WINDOW defaults to the selected window.  */)
   else
     posint = XMARKER (w->pointm)->charpos;
 
-  /* If position is above window start, it's not visible.  */
-  if (posint < CHARPOS (top))
-    in_window = Qnil;
-  else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
-          && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
-          && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
-    {
-      /* If frame is up-to-date, and POSINT is < window end pos, use
-        that info.  This doesn't work for POSINT == end pos, because
-        the window end pos is actually the position _after_ the last
-        char in the window.  */
-      if (NILP (partially))
-       {
-         pos_visible_p (w, posint, &fully_p, NILP (partially));
-         in_window = fully_p ? Qt : Qnil;
-       }
-      else
-       in_window = Qt;
-    }
-  else if (posint > BUF_ZV (buf))
-    in_window = Qnil;
-  else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
-    /* If window start is out of range, do something reasonable.  */
-    in_window = Qnil;
-  else
-    {
-      if (pos_visible_p (w, posint, &fully_p, NILP (partially)))
-       in_window = !NILP (partially) || fully_p ? Qt : Qnil;
-      else
-       in_window = Qnil;
-    }
-
+  /* If position is above window start or outside buffer boundaries,
+     or if window start is out of range, position is not visible.  */
+  if (posint >= CHARPOS (top)
+      && posint <= BUF_ZV (buf)
+      && CHARPOS (top) >= BUF_BEGV (buf)
+      && CHARPOS (top) <= BUF_ZV (buf)
+      && pos_visible_p (w, posint, &fully_p, &x, &y, NILP (partially))
+      && (!NILP (partially) || fully_p))
+    in_window = Qt;
+
+  if (!NILP (in_window) && !NILP (partially))
+    in_window = Fcons (make_number (x),
+                      Fcons (make_number (y),
+                             Fcons (fully_p ? Qt : Qnil, Qnil)));
   return in_window;
 }
 
@@ -392,6 +381,17 @@ decode_window (window)
   return XWINDOW (window);
 }
 
+static struct window *
+decode_any_window (window)
+     register Lisp_Object window;
+{
+  if (NILP (window))
+    return XWINDOW (selected_window);
+
+  CHECK_WINDOW (window);
+  return XWINDOW (window);
+}
+
 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
        doc: /* Return the buffer that WINDOW is displaying.  */)
      (window)
@@ -405,7 +405,7 @@ DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
      (window)
      Lisp_Object window;
 {
-  return decode_window (window)->total_lines;
+  return decode_any_window (window)->total_lines;
 }
 
 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
@@ -416,7 +416,7 @@ use  (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).  */)
      (window)
      Lisp_Object window;
 {
-  return make_number (window_box_text_cols (decode_window (window)));
+  return make_number (window_box_text_cols (decode_any_window (window)));
 }
 
 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
@@ -489,7 +489,7 @@ To get the edges of the actual text area, use `window-inside-edges'.  */)
      (window)
      Lisp_Object window;
 {
-  register struct window *w = decode_window (window);
+  register struct window *w = decode_any_window (window);
 
   return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
         Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
@@ -509,7 +509,7 @@ To get the edges of the actual text area, use `window-inside-pixel-edges'.  */)
      (window)
      Lisp_Object window;
 {
-  register struct window *w = decode_window (window);
+  register struct window *w = decode_any_window (window);
 
   return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
         Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
@@ -528,7 +528,7 @@ display margins, fringes, header line, and/or mode line.  */)
      (window)
      Lisp_Object window;
 {
-  register struct window *w = decode_window (window);
+  register struct window *w = decode_any_window (window);
 
   return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
                             + WINDOW_LEFT_MARGIN_COLS (w)
@@ -552,7 +552,7 @@ display margins, fringes, header line, and/or mode line.  */)
      (window)
      Lisp_Object window;
 {
-  register struct window *w = decode_window (window);
+  register struct window *w = decode_any_window (window);
 
   return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
                             + WINDOW_LEFT_MARGIN_WIDTH (w)
@@ -632,8 +632,7 @@ coordinates_in_window (w, x, y)
      scroll bars.  */
 
   if (WINDOW_WANTS_MODELINE_P (w)
-      && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
-      && *y < bottom_y)
+      && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
     {
       part = ON_MODE_LINE;
 
@@ -654,11 +653,14 @@ coordinates_in_window (w, x, y)
            return ON_VERTICAL_BORDER;
        }
 
+      /* Convert X and Y to window relative coordinates.
+        Mode line starts at left edge of window.  */
+      *x -= x0;
+      *y -= top_y;
       return part;
     }
 
   if (WINDOW_WANTS_HEADER_LINE_P (w)
-      && *y >= top_y
       && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
     {
       part = ON_HEADER_LINE;
@@ -703,7 +705,13 @@ coordinates_in_window (w, x, y)
          && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
              ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
              : (*x < left_x + lmargin_width)))
-       return ON_LEFT_MARGIN;
+       {
+         *x -= left_x;
+         if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
+           *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
+         *y -= top_y;
+         return ON_LEFT_MARGIN;
+       }
 
       /* Convert X and Y to window-relative pixel coordinates.  */
       *x -= left_x;
@@ -717,7 +725,13 @@ coordinates_in_window (w, x, y)
          && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
              ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
              : (*x >= right_x - rmargin_width)))
-       return ON_RIGHT_MARGIN;
+       {
+         *x -= right_x;
+         if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
+           *x -= WINDOW_RIGHT_FRINGE_WIDTH (w);
+         *y -= top_y;
+         return ON_RIGHT_MARGIN;
+       }
 
       /* Convert X and Y to window-relative pixel coordinates.  */
       *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
@@ -757,7 +771,7 @@ If they are in the windows's left or right marginal areas, `left-margin'\n\
   int x, y;
   Lisp_Object lx, ly;
 
-  CHECK_LIVE_WINDOW (window);
+  CHECK_WINDOW (window);
   w = XWINDOW (window);
   f = XFRAME (w->frame);
   CHECK_CONS (coordinates);
@@ -1103,10 +1117,7 @@ non-nil means yes. */)
 {
   register struct window *w = decode_window (window);
 
-  if (NILP (arg))
-    w->dedicated = Qnil;
-  else
-    w->dedicated = Qt;
+  w->dedicated = arg;
 
   return w->dedicated;
 }
@@ -1365,8 +1376,8 @@ delete_window (window)
   if (!NILP (tem))
     {
       unshow_buffer (p);
-      unchain_marker (p->pointm);
-      unchain_marker (p->start);
+      unchain_marker (XMARKER (p->pointm));
+      unchain_marker (XMARKER (p->start));
     }
 
   /* Free window glyph matrices.  It is sure that they are allocated
@@ -1818,6 +1829,7 @@ enum window_loop
   DELETE_BUFFER_WINDOWS,       /* Arg is buffer */
   GET_LARGEST_WINDOW,
   UNSHOW_BUFFER,               /* Arg is buffer */
+  REDISPLAY_BUFFER_WINDOWS,    /* Arg is buffer */
   CHECK_ALL_WINDOWS
 };
 
@@ -2016,6 +2028,17 @@ window_loop (type, obj, mini, frames)
              }
            break;
 
+         case REDISPLAY_BUFFER_WINDOWS:
+           if (EQ (w->buffer, obj))
+             {
+               mark_window_display_accurate (window, 0);
+               w->update_mode_line = Qt;
+               XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
+               ++update_mode_lines;
+               best_window = window;
+             }
+           break;
+
            /* Check for a window that has a killed buffer.  */
          case CHECK_ALL_WINDOWS:
            if (! NILP (w->buffer)
@@ -2042,6 +2065,7 @@ check_all_windows ()
 
 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
        doc: /* Return the window least recently selected or used for display.
+Return a full-width window if possible.
 If optional argument FRAME is `visible', search all visible frames.
 If FRAME is 0, search all visible and iconified frames.
 If FRAME is t, search all frames.
@@ -2525,6 +2549,118 @@ adjust_window_margins (w)
   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;
+  int total_removed = 0;
+  int total_shrink = total - size;
+  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
+     windows and set them to 0 until we can fulfil the new size.  */
+
+  while (shrinkable > 1 && size + available_resize < total)
+    {
+      for (i = 0; i < nchildren; ++i)
+        if (new_sizes[i] > 0 && smallest > new_sizes[i])
+          smallest = new_sizes[i];
+
+      for (i = 0; i < nchildren; ++i)
+        if (new_sizes[i] == smallest)
+          {
+            /* 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;
+
+            /* Out of for, just remove one window at the time and
+               check again if we have enough space.  */
+            break;
+          }
+    }
+
+  /* Now, calculate the new sizes.  Try to shrink each window
+     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;
+        }
+    }
+
+  /* Any reminder due to rounding, we just subtract from windows
+     that are left and still can be shrunk.  */
+  while (total_shrink > total_removed)
+    {
+      for (i = 0; i < nchildren; ++i)
+        if (new_sizes[i] > min_size)
+          {
+            --new_sizes[i];
+            ++total_removed;
+
+            /* Out of for, just shrink one window at the time and
+               check again if we have enough space.  */
+            break;
+          }
+    }
+
+  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
@@ -2628,6 +2764,7 @@ size_window (window, size, width_p, nodelete_p)
       int fixed_size, each, extra, n;
       int resize_fixed_p, nfixed;
       int last_pos, first_pos, nchildren, total;
+      int *new_sizes = NULL;
 
       /* Determine the fixed-size portion of the this window, and the
         number of child windows.  */
@@ -2652,16 +2789,22 @@ size_window (window, size, width_p, nodelete_p)
         windows.  */
       resize_fixed_p = nfixed == nchildren || size < fixed_size;
 
-      /* Compute how many lines/columns to add to each child.  The
+      /* Compute how many lines/columns to add/remove to each child.  The
         value of extra takes care of rounding errors.  */
       n = resize_fixed_p ? nchildren : nchildren - nfixed;
-      each = (size - total) / n;
-      extra = (size - total) - n * each;
+      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;
+          extra = (size - total) - n * each;
+        }
 
       /* Compute new children heights and edge positions.  */
       first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
       last_pos = first_pos;
-      for (child = *forward; !NILP (child); child = c->next)
+      for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
        {
          int new_size, old_size;
 
@@ -2679,7 +2822,7 @@ size_window (window, size, width_p, nodelete_p)
          /* If this child can be resized, do it.  */
          if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
            {
-             new_size = old_size + each + extra;
+             new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
              extra = 0;
            }
 
@@ -2690,9 +2833,11 @@ size_window (window, size, width_p, nodelete_p)
 
          /* Remember the bottom/right edge position of this child; it
             will be used to set the top/left edge of the next child.  */
-         last_pos += new_size;
+          last_pos += new_size;
        }
 
+      if (new_sizes) xfree (new_sizes);
+
       /* We should have covered the parent exactly with child windows.  */
       xassert (size == last_pos - first_pos);
 
@@ -2840,6 +2985,9 @@ set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
 
       /* This may call adjust_window_margins three times, so
         temporarily disable window margins.  */
+      Lisp_Object save_left = w->left_margin_cols;
+      Lisp_Object save_right = w->right_margin_cols;
+
       w->left_margin_cols = w->right_margin_cols = Qnil;
 
       Fset_window_fringes (window,
@@ -2850,6 +2998,9 @@ set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
                               b->scroll_bar_width,
                               b->vertical_scroll_bar_type, Qnil);
 
+      w->left_margin_cols = save_left;
+      w->right_margin_cols = save_right;
+
       Fset_window_margins (window,
                           b->left_margin_cols, b->right_margin_cols);
     }
@@ -2906,6 +3057,9 @@ defaults.  */)
   return Qnil;
 }
 
+/* Note that selected_window can be nil
+   when this is called from Fset_window_configuration.  */
+
 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
        doc: /* Select WINDOW.  Most editing will apply to WINDOW's buffer.
 If WINDOW is not already selected, also make WINDOW's buffer current.
@@ -3005,7 +3159,14 @@ display_buffer_1 (window)
 
   FRAME_SAMPLE_VISIBILITY (f);
 
-  if (!EQ (frame, selected_frame))
+  if (EQ (frame, selected_frame))
+    ; /* Assume the selected frame is already visible enough.  */
+  else if (minibuf_level > 0
+          && MINI_WINDOW_P (XWINDOW (selected_window))
+          && WINDOW_LIVE_P (minibuf_selected_window)
+          && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
+    ; /* Assume the frame from which we invoked the minibuffer is visible.  */
+  else
     {
       if (FRAME_ICONIFIED_P (f))
        Fmake_frame_visible (frame);
@@ -3095,9 +3256,10 @@ Returns the window displaying BUFFER.
 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
 displaying BUFFER, then simply raise that frame.
 
-The variables `special-display-buffer-names', `special-display-regexps',
-`same-window-buffer-names', and `same-window-regexps' customize how certain
-buffer names are handled.
+The variables `special-display-buffer-names',
+`special-display-regexps', `same-window-buffer-names', and
+`same-window-regexps' customize how certain buffer names are handled.
+The latter two take effect only if NOT-THIS-WINDOW is t.
 
 If optional argument FRAME is `visible', search all visible frames.
 If FRAME is 0, search all visible and iconified frames.
@@ -3280,6 +3442,52 @@ displayed.  */)
   return display_buffer_1 (window);
 }
 
+
+DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
+       0, 1, 0,
+       doc: /* Force redisplay of all windows.
+If optional arg OBJECT is a window, force redisplay of that window only.
+If OBJECT is a buffer or buffer name, force redisplay of all windows
+displaying that buffer.  */)
+     (object)
+     Lisp_Object object;
+{
+  if (NILP (object))
+    {
+      windows_or_buffers_changed++;
+      update_mode_lines++;
+      return Qt;
+    }
+
+  if (WINDOWP (object))
+    {
+      struct window *w = XWINDOW (object);
+      mark_window_display_accurate (object, 0);
+      w->update_mode_line = Qt;
+      if (BUFFERP (w->buffer))
+       XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+      ++update_mode_lines;
+      return Qt;
+    }
+
+  if (STRINGP (object))
+    object = Fget_buffer (object);
+  if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
+    {
+      /* Walk all windows looking for buffer, and force update
+        of each of those windows.  */
+
+      object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
+      return NILP (object) ? Qnil : Qt;
+    }
+
+  /* If nothing suitable was found, just return.
+     We could signal an error, but this feature will typically be used
+     asynchronously in timers or process sentinels, so we don't.  */
+  return Qnil;
+}
+
+
 void
 temp_output_buffer_show (buf)
      register Lisp_Object buf;
@@ -3312,37 +3520,31 @@ temp_output_buffer_show (buf)
       w = XWINDOW (window);
       XSETFASTINT (w->hscroll, 0);
       XSETFASTINT (w->min_hscroll, 0);
-      set_marker_restricted_both (w->start, buf, 1, 1);
-      set_marker_restricted_both (w->pointm, buf, 1, 1);
+      set_marker_restricted_both (w->start, buf, BEG, BEG);
+      set_marker_restricted_both (w->pointm, buf, BEG, BEG);
 
       /* Run temp-buffer-show-hook, with the chosen window selected
         and its buffer current.  */
-      if (!NILP (Vrun_hooks))
+
+      if (!NILP (Vrun_hooks)
+         && !NILP (Fboundp (Qtemp_buffer_show_hook))
+         && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
        {
-         Lisp_Object tem;
-         tem = Fboundp (Qtemp_buffer_show_hook);
-         if (!NILP (tem))
-           {
-             tem = Fsymbol_value (Qtemp_buffer_show_hook);
-             if (!NILP (tem))
-               {
-                 int count = SPECPDL_INDEX ();
-                 Lisp_Object prev_window, prev_buffer;
-                 prev_window = selected_window;
-                 XSETBUFFER (prev_buffer, old);
-
-                 /* Select the window that was chosen, for running the hook.
-                    Note: Both Fselect_window and select_window_norecord may
-                    set-buffer to the buffer displayed in the window,
-                    so we need to save the current buffer.  --stef  */
-                 record_unwind_protect (Fset_buffer, prev_buffer);
-                 record_unwind_protect (select_window_norecord, prev_window);
-                 Fselect_window (window, Qt);
-                 Fset_buffer (w->buffer);
-                 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
-                 unbind_to (count, Qnil);
-               }
-           }
+         int count = SPECPDL_INDEX ();
+         Lisp_Object prev_window, prev_buffer;
+         prev_window = selected_window;
+         XSETBUFFER (prev_buffer, old);
+
+         /* Select the window that was chosen, for running the hook.
+            Note: Both Fselect_window and select_window_norecord may
+            set-buffer to the buffer displayed in the window,
+            so we need to save the current buffer.  --stef  */
+         record_unwind_protect (Fset_buffer, prev_buffer);
+         record_unwind_protect (select_window_norecord, prev_window);
+         Fselect_window (window, Qt);
+         Fset_buffer (w->buffer);
+         call1 (Vrun_hooks, Qtemp_buffer_show_hook);
+         unbind_to (count, Qnil);
        }
     }
 }
@@ -4802,7 +5004,6 @@ Returns nil, if current window is not a minibuffer window.  */)
 {
   if (minibuf_level > 0
       && MINI_WINDOW_P (XWINDOW (selected_window))
-      && !NILP (minibuf_selected_window)
       && WINDOW_LIVE_P (minibuf_selected_window))
     return minibuf_selected_window;
 
@@ -5703,38 +5904,32 @@ usage: (save-window-excursion BODY ...)  */)
 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
        2, 3, 0,
        doc: /* Set width of marginal areas of window WINDOW.
-If window is nil, set margins of the currently selected window.
-First parameter LEFT-WIDTH specifies the number of character
-cells to reserve for the left marginal area.  Second parameter
-RIGHT-WIDTH does the same for the right marginal area.
-A nil width parameter means no margin.  */)
+If WINDOW is nil, set margins of the currently selected window.
+Second arg LEFT-WIDTH specifies the number of character cells to
+reserve for the left marginal area.  Optional third arg RIGHT-WIDTH
+does the same for the right marginal area.  A nil width parameter
+means no margin.  */)
      (window, left, right)
      Lisp_Object window, left, right;
 {
   struct window *w = decode_window (window);
 
-  /* TODO: It doesn't make sense to use FLOATs here, since
-     the rest of the code assumes they are integers.
-     So don't allow floats!  ++KFS */
+  /* Translate negative or zero widths to nil.
+     Margins that are too wide have to be checked elsewhere.  */
 
   if (!NILP (left))
-    CHECK_NUMBER_OR_FLOAT (left);
-  if (!NILP (right))
-    CHECK_NUMBER_OR_FLOAT (right);
+    {
+      CHECK_NUMBER (left);
+      if (XINT (left) <= 0)
+       left = Qnil;
+    }
 
-  /* 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_DATA (left) <= 0))
-     XSETFASTINT (left, 0);
-  if (INTEGERP (left) && XFASTINT (left) == 0)
-    left = Qnil;
-
-  if ((INTEGERP (right) && XINT (right) < 0)
-      || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
-    XSETFASTINT (right, 0);
-  if (INTEGERP (right) && XFASTINT (right) == 0)
-    right = Qnil;
+  if (!NILP (right))
+    {
+      CHECK_NUMBER (right);
+      if (XINT (right) <= 0)
+       right = Qnil;
+    }
 
   if (!EQ (w->left_margin_cols, left)
       || !EQ (w->right_margin_cols, right))
@@ -5774,15 +5969,17 @@ as nil.  */)
 
 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
        2, 4, 0,
-       doc: /* Set width of fringes of window WINDOW.
-
-If window is nil, set fringes of the currently selected window.
-Second parameter LEFT-WIDTH specifies the number of pixels to reserve
-for the left fringe.  Third parameter RIGHT-WIDTH does the same for
-the right fringe.  Fourth parameter OUTSIDE-MARGINS non-nil specifies
-that fringes are drawn outside of the display margins; by default, fringes
-are drawn between display marginal areas and the text area.
-A nil width parameter means to use the frame's corresponding fringe width.  */)
+       doc: /* Set the fringe widths of window WINDOW.
+If WINDOW is nil, set the fringe widths of the currently selected
+window.
+Second arg LEFT-WIDTH specifies the number of pixels to reserve for
+the left fringe.  Optional third arg RIGHT-WIDTH specifies the right
+fringe width.  If a fringe width arg is nil, that means to use the
+frame's default fringe width.  Default fringe widths can be set with
+the command `set-fringe-style'.
+If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
+outside of the display margins.  By default, fringes are drawn between
+display marginal areas and the text area.  */)
      (window, left, right, outside_margins)
      Lisp_Object window, left, right, outside_margins;
 {
@@ -5818,9 +6015,7 @@ DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
        0, 1, 0,
        doc: /* Get width of fringes of window WINDOW.
 If WINDOW is omitted or nil, use the currently selected window.
-Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).
-If a window specific fringe width is not set, its width will be returned
-as nil.  */)
+Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).  */)
      (window)
      Lisp_Object window;
 {
@@ -5845,7 +6040,8 @@ Second parameter WIDTH specifies the pixel width for the scroll bar;
 this is automatically adjusted to a multiple of the frame column width.
 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
 bar: left, right, or nil.
-A width of nil and type of t means to use the frame's corresponding value.  */)
+If WIDTH is nil, use the frame's scroll-bar width.
+If TYPE is t, use the frame's scroll-bar type.  */)
      (window, width, vertical_type, horizontal_type)
      Lisp_Object window, width, vertical_type, horizontal_type;
 {
@@ -5857,6 +6053,12 @@ A width of nil and type of t means to use the frame's corresponding value.  */)
   if (XINT (width) == 0)
     vertical_type = Qnil;
 
+  if (!(EQ (vertical_type, Qnil)
+       || EQ (vertical_type, Qleft)
+       || EQ (vertical_type, Qright)
+       || EQ (vertical_type, Qt)))
+    error ("Invalid type of vertical scroll bar");
+
   if (!EQ (w->scroll_bar_width, width)
       || !EQ (w->vertical_scroll_bar_type, vertical_type))
     {
@@ -5880,7 +6082,9 @@ DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
        0, 1, 0,
        doc: /* Get width and type of scroll bars of window WINDOW.
 If WINDOW is omitted or nil, use the currently selected window.
-Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).  */)
+Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
+If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
+value.  */)
      (window)
      Lisp_Object window;
 {
@@ -5899,12 +6103,13 @@ Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).  */)
                           Smooth scrolling
  ***********************************************************************/
 
-DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
+DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
        doc: /* Return the amount by which WINDOW is scrolled vertically.
 Use the selected window if WINDOW is nil or omitted.
-Value is a multiple of the canonical character height of WINDOW.  */)
-     (window)
-     Lisp_Object window;
+Normally, value is a multiple of the canonical character height of WINDOW;
+optional second arg PIXELS_P means value is measured in pixels.  */)
+  (window, pixels_p)
+     Lisp_Object window, pixels_p;
 {
   Lisp_Object result;
   struct frame *f;
@@ -5918,7 +6123,9 @@ Value is a multiple of the canonical character height of WINDOW.  */)
   f = XFRAME (w->frame);
 
   if (FRAME_WINDOW_P (f))
-    result = FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
+    result = (NILP (pixels_p)
+             ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
+             : make_number (-w->vscroll));
   else
     result = make_number (0);
   return result;
@@ -5926,12 +6133,13 @@ Value is a multiple of the canonical character height of WINDOW.  */)
 
 
 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
-       2, 2, 0,
+       2, 3, 0,
        doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
-WINDOW nil means use the selected window.  VSCROLL is a non-negative
-multiple of the canonical character height of WINDOW.  */)
-     (window, vscroll)
-     Lisp_Object window, vscroll;
+WINDOW nil means use the selected window.  Normally, VSCROLL is a
+non-negative multiple of the canonical character height of WINDOW;
+optional third arg PIXELS_P non-nil means that VSCROLL is in pixels.  */)
+  (window, vscroll, pixels_p)
+     Lisp_Object window, vscroll, pixels_p;
 {
   struct window *w;
   struct frame *f;
@@ -5949,7 +6157,9 @@ multiple of the canonical character height of WINDOW.  */)
     {
       int old_dy = w->vscroll;
 
-      w->vscroll = - FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll);
+      w->vscroll = - (NILP (pixels_p)
+                     ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
+                     : XFLOATINT (vscroll));
       w->vscroll = min (w->vscroll, 0);
 
       /* Adjust glyph matrix of the frame if the virtual display
@@ -5961,7 +6171,7 @@ multiple of the canonical character height of WINDOW.  */)
       XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
     }
 
-  return Fwindow_vscroll (window);
+  return Fwindow_vscroll (window, pixels_p);
 }
 
 \f
@@ -6294,6 +6504,11 @@ In the latter case, FUNCTION is called with BUFFER as the first argument,
 followed by OTHER-ARGS--it can display BUFFER in any way it likes.
 All this is done by the function found in `special-display-function'.
 
+If the specified frame parameters include (same-buffer . t), the
+buffer is displayed in the currently selected window.  Otherwise, if
+they include (same-frame . t), the buffer is displayed in a new window
+in the currently selected frame.
+
 If this variable appears \"not to work\", because you add a name to it
 but that buffer still appears in the selected window, look at the
 values of `same-window-buffer-names' and `same-window-regexps'.
@@ -6314,6 +6529,11 @@ In the latter case, FUNCTION is called with the buffer as first argument,
 followed by OTHER-ARGS--it can display the buffer in any way it likes.
 All this is done by the function found in `special-display-function'.
 
+If the specified frame parameters include (same-buffer . t), the
+buffer is displayed in the currently selected window.  Otherwise, if
+they include (same-frame . t), the buffer is displayed in a new window
+in the currently selected frame.
+
 If this variable appears \"not to work\", because you add a regexp to it
 but the matching buffers still appear in the selected window, look at the
 values of `same-window-buffer-names' and `same-window-regexps'.
@@ -6446,6 +6666,7 @@ This variable automatically becomes buffer-local when set.  */);
   defsubr (&Sspecial_display_p);
   defsubr (&Ssame_window_p);
   defsubr (&Sdisplay_buffer);
+  defsubr (&Sforce_window_update);
   defsubr (&Ssplit_window);
   defsubr (&Senlarge_window);
   defsubr (&Sshrink_window);
@@ -6494,3 +6715,6 @@ keys_of_window ()
   initial_define_key (global_map, Ctl('L'), "recenter");
   initial_define_key (meta_map, 'r', "move-to-window-line");
 }
+
+/* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
+   (do not change this comment) */