(construct_menu_click, construct_mouse_click):
[bpt/emacs.git] / src / window.c
index ab81e80..b253f7d 100644 (file)
@@ -1,6 +1,6 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985, 1986, 1987, 1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-#include "config.h"
+#include <config.h>
 #include "lisp.h"
 #include "buffer.h"
 #include "frame.h"
@@ -29,7 +29,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "disptab.h"
 #include "keyboard.h"
 
-Lisp_Object Qwindowp, Qlive_window_p;
+Lisp_Object Qwindowp, Qwindow_live_p;
 
 Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
 Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
@@ -60,9 +60,6 @@ Lisp_Object Vminibuf_scroll_window;
 /* Non-nil means this is the buffer whose window C-M-v should scroll.  */
 Lisp_Object Vother_window_scroll_buffer;
 
-/* Last mouse click data structure (nil if no mouse support).  */
-Lisp_Object Vmouse_event;
-
 /* Non-nil means it's function to call to display temp buffers.  */
 Lisp_Object Vtemp_buffer_show_function;
 
@@ -102,7 +99,7 @@ DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
   return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
 }
 
-DEFUN ("live-window-p", Flive_window_p, Slive_window_p, 1, 1, 0,
+DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
   "Returns t if OBJ is a window which is currently visible.")
      (obj)
      Lisp_Object obj;
@@ -188,6 +185,7 @@ POS defaults to point; WINDOW, to the selected window.")
   register int posint;
   register struct buffer *buf;
   struct position posval;
+  int hscroll;
 
   if (NILP (pos))
     posint = point;
@@ -199,6 +197,7 @@ POS defaults to point; WINDOW, to the selected window.")
 
   w = decode_window (window);
   top = marker_position (w->start);
+  hscroll = XINT (w->hscroll);
 
   if (posint < top)
     return Qnil;
@@ -217,13 +216,14 @@ POS defaults to point; WINDOW, to the selected window.")
     }
   else
     {
-      if (posint > BUF_Z (buf))
+      if (posint > BUF_ZV (buf))
        return Qnil;
 
       /* If that info is not correct, calculate afresh */
-      posval = *compute_motion (top, 0, 0, posint, height, 0,
+      posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0),
+                               posint, height, 0,
                                window_internal_width (w) - 1,
-                               XINT (w->hscroll), 0);
+                               hscroll, 0);
 
       return posval.vpos < height ? Qt : Qnil;
     }
@@ -257,14 +257,14 @@ DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
 }
 
 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
-  "Return the number of columns in WINDOW.")
+  "Return the number of display columns in WINDOW.\n\
+This is the width that is usable columns available for text in WINDOW.\n\
+If you want to find out how many columns WINDOW takes up,\n\
+use  (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
   (window)
      Lisp_Object window;
 {
-  register struct window *w = decode_window (window);
-  register int width = XFASTINT (w->width);
-
-  return make_number (window_internal_width (w));
+  return make_number (window_internal_width (decode_window (window)));
 }
 
 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
@@ -483,9 +483,13 @@ DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
 {
   Lisp_Object value;
   struct window *w = decode_window (window);
-  
+  Lisp_Object buf;
+
+  buf = w->buffer;
+  CHECK_BUFFER (buf, 0);
+
   XSET (value, Lisp_Int,
-       BUF_Z (current_buffer) - XFASTINT (w->window_end_pos));
+       BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
 
   return value;
 }
@@ -531,7 +535,7 @@ from overriding motion of point in order to display at this exact start.")
 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
        1, 1, 0,
   "Return WINDOW's dedicated object, usually t or nil.\n\
-See also `set-window-buffer-dedicated'.")
+See also `set-window-dedicated-p'.")
   (window)
      Lisp_Object window;
 {
@@ -608,15 +612,25 @@ static
 unshow_buffer (w)
      register struct window *w;
 {
-  Lisp_Object buf = w->buffer;
+  Lisp_Object buf;
 
+  buf = w->buffer;
   if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
     abort ();
 
+#if 0
   if (w == XWINDOW (selected_window)
       || ! EQ (buf, XWINDOW (selected_window)->buffer))
     /* Do this except when the selected window's buffer
        is being removed from some other window.  */
+#endif
+    /* last_window_start records the start position that this buffer
+       had in the last window to be disconnected from it.
+       Now that this statement is unconditional,
+       it is possible for the buffer to be displayed in the
+       selected window, while last_window_start reflects another
+       window which was recently showing the same buffer.
+       Some people might say that might be a good thing.  Let's see.  */
     XBUFFER (buf)->last_window_start = marker_position (w->start);
 
   /* Point in the selected window's buffer
@@ -703,11 +717,25 @@ DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
 
   /* Are we trying to delete any frame's selected window?  */
   {
-    Lisp_Object frame = WINDOW_FRAME (XWINDOW (window));
+    Lisp_Object frame, pwindow;
 
-    if (EQ (window, FRAME_SELECTED_WINDOW (XFRAME (frame))))
+    /* See if the frame's selected window is either WINDOW
+       or any subwindow of it, by finding all that window's parents
+       and comparing each one with WINDOW.  */
+    frame = WINDOW_FRAME (XWINDOW (window));
+    pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
+
+    while (!NILP (pwindow))
       {
-       Lisp_Object alternative = Fnext_window (window, Qlambda, Qnil);
+       if (EQ (window, pwindow))
+         break;
+       pwindow = XWINDOW (pwindow)->parent;
+      }
+
+    if (EQ (window, pwindow))
+      {
+       Lisp_Object alternative;
+       alternative = Fnext_window (window, Qlambda, Qnil);
 
        /* If we're about to delete the selected window on the
           selected frame, then we should use Fselect_window to select
@@ -791,7 +819,11 @@ DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
 
 extern Lisp_Object next_frame (), prev_frame ();
 
-DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
+/* This comment supplies the doc string for `next-window',
+   for make-docfile to see.  We cannot put this in the real DEFUN
+   due to limits in the Unix cpp.
+
+DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
   "Return next window after WINDOW in canonical ordering of windows.\n\
 If omitted, WINDOW defaults to the selected window.\n\
 \n\
@@ -808,12 +840,17 @@ minibuffer does not count, only windows from WINDOW's frame count.\n\
 \n\
 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
-above.  If neither nil nor t, restrict to WINDOW's frame.\n\
+above.  ALL-FRAMES = `visible' means include windows on all visible frames.\n\
+Anything else means restrict to WINDOW's frame.\n\
 \n\
 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
 `next-window' to iterate through the entire cycle of acceptable\n\
 windows, eventually ending up back at the window you started with.\n\
 `previous-window' traverses the same cycle, in the reverse order.")
+  (window, minibuf, all_frames) */
+
+DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
+       0)
   (window, minibuf, all_frames)
      register Lisp_Object window, minibuf, all_frames;
 {
@@ -841,8 +878,13 @@ windows, eventually ending up back at the window you started with.\n\
                       (WINDOW_FRAME
                        (XWINDOW (window)))))
                   : Qnil);
+  else if (EQ (all_frames, Qvisible))
+    ;
   else if (! EQ (all_frames, Qt))
     all_frames = Qnil;
+  /* Now all_frames is t meaning search all frames,
+     nil meaning search just current frame,
+     or a window, meaning search the frame that window belongs to.  */
 
   /* Do this loop at least once, to get the next window, and perhaps
      again, if we hit the minibuffer and that is not acceptable.  */
@@ -892,7 +934,11 @@ windows, eventually ending up back at the window you started with.\n\
   return window;
 }
 
-DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
+/* This comment supplies the doc string for `previous-window',
+   for make-docfile to see.  We cannot put this in the real DEFUN
+   due to limits in the Unix cpp.
+
+DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
   "Return the window preceeding WINDOW in canonical ordering of windows.\n\
 If omitted, WINDOW defaults to the selected window.\n\
 \n\
@@ -910,12 +956,18 @@ count.\n\
 \n\
 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
-above.  If neither nil nor t, restrict to WINDOW's frame.\n\
+above.  ALL-FRAMES = `visible' means include windows on all visible frames.\n\
+Anything else means restrict to WINDOW's frame.\n\
 \n\
 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
 `previous-window' to iterate through the entire cycle of acceptable\n\
 windows, eventually ending up back at the window you started with.\n\
 `next-window' traverses the same cycle, in the reverse order.")
+  (window, minibuf, all_frames)  */
+
+
+DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
+       0)
   (window, minibuf, all_frames)
      register Lisp_Object window, minibuf, all_frames;
 {
@@ -943,8 +995,13 @@ windows, eventually ending up back at the window you started with.\n\
                       (WINDOW_FRAME
                        (XWINDOW (window)))))
                   : Qnil);
+  else if (EQ (all_frames, Qvisible))
+    ;
   else if (! EQ (all_frames, Qt))
     all_frames = Qnil;
+  /* Now all_frames is t meaning search all frames,
+     nil meaning search just current frame,
+     or a window, meaning search the frame that window belongs to.  */
 
   /* Do this loop at least once, to get the previous window, and perhaps
      again, if we hit the minibuffer and that is not acceptable.  */
@@ -973,7 +1030,12 @@ windows, eventually ending up back at the window you started with.\n\
                 met.  */
              tem = prev_frame (tem, all_frames);
 #endif
-           tem = FRAME_ROOT_WINDOW (XFRAME (tem));
+           /* If this frame has a minibuffer, find that window first,
+              because it is conceptually the last window in that frame.  */
+           if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
+             tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
+           else
+             tem = FRAME_ROOT_WINDOW (XFRAME (tem));
 
            break;
          }
@@ -1036,8 +1098,10 @@ argument ALL_FRAMES is non-nil, cycle through all frames.")
 \f
 /* Look at all windows, performing an operation specified by TYPE
    with argument OBJ.
-   If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
-   frame.  If FRAMES is a frame, just look at windows on that frame.
+   If FRAMES is Qt, look at all frames;
+                Qnil, look at just the selected frame;
+               Qvisible, look at visible frames;
+               a frame, just look at windows on that frame.
    If MINI is non-zero, perform the operation on minibuffer windows too.
 */
 
@@ -1049,7 +1113,7 @@ enum window_loop
   DELETE_OTHER_WINDOWS,                /* Arg is window not to delete */
   DELETE_BUFFER_WINDOWS,       /* Arg is buffer */
   GET_LARGEST_WINDOW,
-  UNSHOW_BUFFER,               /* Arg is buffer */
+  UNSHOW_BUFFER                /* Arg is buffer */
 };
 
 static Lisp_Object
@@ -1063,6 +1127,8 @@ window_loop (type, obj, mini, frames)
   register Lisp_Object next_window;
   register Lisp_Object last_window;
   FRAME_PTR frame;
+  Lisp_Object frame_arg;
+  frame_arg = Qt;
 
 #ifdef MULTI_FRAME
   /* If we're only looping through windows on a particular frame,
@@ -1074,10 +1140,18 @@ window_loop (type, obj, mini, frames)
     frame = selected_frame;
   else
     frame = 0;
+  if (frame)
+    frame_arg = Qlambda;
+  else if (EQ (frames, Qvisible))
+    frame_arg = frames;
 #else
   frame = 0;
 #endif
 
+  /* frame_arg is Qlambda to stick to one frame,
+     Qvisible to consider all visible frames,
+     or Qt otherwise.  */
+
   /* Pick a window to start with.  */
   if (XTYPE (obj) == Lisp_Window)
     w = obj;
@@ -1093,40 +1167,25 @@ window_loop (type, obj, mini, frames)
      We can't just wait until we hit the first window again, because
      it might be deleted.  */
 
-#ifdef MULTI_FRAME
-  if (frame)
-    last_window = Fprevious_window (w, (mini ? Qt : Qnil), Qlambda);
-  else
-#endif /* MULTI_FRAME */
-    /* We know frame is 0, so we're looping through all frames.
-       Or we know this isn't a MULTI_FRAME Emacs, so who cares?  */
-    last_window = Fprevious_window (w, mini ? Qt : Qnil, Qt);
+  last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
 
   best_window = Qnil;
   for (;;)
     {
+      FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
+
       /* Pick the next window now, since some operations will delete
         the current window.  */
-#ifdef MULTI_FRAME
-      if (frame)
-       next_window = Fnext_window (w, (mini ? Qt : Qnil), Qlambda);
-      else
-#endif                         /* MULTI_FRAME */
-       /* We know frame is 0, so we're looping through all frames.
-          Or we know this isn't a MULTI_FRAME Emacs, so who cares?  */
-       next_window = Fnext_window (w, mini ? Qt : Qnil, Qt);
+      next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
 
-      if (!MINI_WINDOW_P (XWINDOW (w))
+      /* Note that we do not pay attention here to whether
+        the frame is visible, since Fnext_window skips non-visible frames
+        if that is desired, under the control of frame_arg.  */
+      if (! MINI_WINDOW_P (XWINDOW (w))
          || (mini && minibuf_level > 0))
        switch (type)
          {
          case GET_BUFFER_WINDOW:
-#if 0
-           /* Ignore invisible and iconified frames.  */
-           if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
-               || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
-             break;
-#endif
            if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
              return w;
            break;
@@ -1134,14 +1193,8 @@ window_loop (type, obj, mini, frames)
          case GET_LRU_WINDOW:
            /* t as arg means consider only full-width windows */
            if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
-               != FRAME_WIDTH (frame))
+               != FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
              break;
-#if 0
-           /* Ignore invisible and iconified frames.  */
-           if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
-               || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
-             break;
-#endif
            /* Ignore dedicated windows and minibuffers.  */
            if (MINI_WINDOW_P (XWINDOW (w))
                || !NILP (XWINDOW (w)->dedicated))
@@ -1164,12 +1217,14 @@ window_loop (type, obj, mini, frames)
                   on the frame, find a new buffer to display there.  */
                if (NILP (XWINDOW (w)->parent))
                  {
-                   Lisp_Object new_buffer = Fother_buffer (obj, Qnil);
+                   Lisp_Object new_buffer;
+                   new_buffer = Fother_buffer (obj, Qnil);
                    if (NILP (new_buffer))
                      new_buffer
                        = Fget_buffer_create (build_string ("*scratch*"));
                    Fset_window_buffer (w, new_buffer);
-                   Fset_buffer (XWINDOW (w)->buffer);
+                   if (EQ (w, selected_window))
+                     Fset_buffer (XWINDOW (w)->buffer);
                  }
                else
                  Fdelete_window (w);
@@ -1177,12 +1232,6 @@ window_loop (type, obj, mini, frames)
            break;
 
          case GET_LARGEST_WINDOW:
-#if 0
-           /* Ignore invisible and iconified frames.  */
-           if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
-               || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
-             break;
-#endif
            /* Ignore dedicated windows and minibuffers.  */
            if (MINI_WINDOW_P (XWINDOW (w))
                || !NILP (XWINDOW (w)->dedicated))
@@ -1202,7 +1251,8 @@ window_loop (type, obj, mini, frames)
            if (EQ (XWINDOW (w)->buffer, obj))
              {
                /* Find another buffer to show in this window.  */
-               Lisp_Object another_buffer = Fother_buffer (obj, Qnil);
+               Lisp_Object another_buffer;
+               another_buffer = Fother_buffer (obj, Qnil);
                if (NILP (another_buffer))
                  another_buffer
                    = Fget_buffer_create (build_string ("*scratch*"));
@@ -1224,24 +1274,28 @@ window_loop (type, obj, mini, frames)
 
 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
   "Return the window least recently selected or used for display.\n\
-If optional argument FRAMES is t, search all frames.  If FRAME is a\n\
-frame, search only that frame.\n")
-  (frames)
-    Lisp_Object frames;
+If optional argument FRAME is `visible', search all visible frames.\n\
+If FRAME is t, search all frames.\n\
+If FRAME is nil, search only the selected frame.\n\
+If FRAME is a frame, search only that frame.")
+  (frame)
+    Lisp_Object frame;
 {
   register Lisp_Object w;
   /* First try for a window that is full-width */
-  w = window_loop (GET_LRU_WINDOW, Qt, 0, frames);
+  w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
   if (!NILP (w) && !EQ (w, selected_window))
     return w;
   /* If none of them, try the rest */
-  return window_loop (GET_LRU_WINDOW, Qnil, 0, frames);
+  return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
 }
 
 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
   "Return the largest window in area.\n\
-If optional argument FRAMES is t, search all frames.  If FRAME is a\n\
-frame, search only that frame.\n")
+If optional argument FRAME is `visible', search all visible frames.\n\
+If FRAME is t, search all frames.\n\
+If FRAME is nil, search only the selected frame.\n\
+If FRAME is a frame, search only that frame.")
   (frame)
     Lisp_Object frame;
 {
@@ -1251,8 +1305,10 @@ frame, search only that frame.\n")
 
 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
   "Return a window currently displaying BUFFER, or nil if none.\n\
-If optional argument FRAMES is t, search all frames.  If FRAME is a\n\
-frame, search only that frame.\n")
+If optional argument FRAME is `visible', search all visible frames.\n\
+If FRAME is t, search all frames.\n\
+If FRAME is nil, search only the selected frame.\n\
+If FRAME is a frame, search only that frame.")
   (buffer, frame)
     Lisp_Object buffer, frame;
 {
@@ -1266,13 +1322,19 @@ frame, search only that frame.\n")
 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
   0, 1, "",
   "Make WINDOW (or the selected window) fill its frame.\n\
-Only the frame WINDOW is on is affected.")
+Only the frame WINDOW is on is affected.\n\
+This function tries to reduce display jumps\n\
+by keeping the text previously visible in WINDOW\n\
+in the same place on the frame.  Doing this depends on\n\
+the value of (window-start WINDOW), so if calling this function\n\
+in a program gives strange scrolling, make sure the window-start\n\
+value is reasonable when this function is called.")
   (window)
      Lisp_Object window;
 {
   struct window *w;
-  int opoint = point;
   struct buffer *obuf = current_buffer;
+  int opoint;
   int top;
 
   if (NILP (window))
@@ -1283,28 +1345,47 @@ Only the frame WINDOW is on is affected.")
   w = XWINDOW (window);
   top = XFASTINT (w->top);
 
-  window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME(w));
+  window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
 
   Fset_buffer (w->buffer);
+  opoint = point;
   SET_PT (marker_position (w->start));
-  Frecenter (make_number (top));
+  /* Like Frecenter but avoid setting w->force_start.  */
+  Fvertical_motion (make_number (- (top - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w))))),
+                   window);
+  Fset_marker (w->start, make_number (PT), w->buffer);
+  w->start_at_line_beg = Fbolp ();
 
-  set_buffer_internal (obuf);
   SET_PT (opoint);
+  set_buffer_internal (obuf);
   return Qnil;
 }
 
 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
-  1, 1, "bDelete windows on (buffer): ",
-  "Delete all windows showing BUFFER.")
-  (buffer)
-     Lisp_Object buffer;
+  1, 2, "bDelete windows on (buffer): ",
+  "Delete all windows showing BUFFER.\n\
+Optional second argument FRAME controls which frames are affected.\n\
+If nil or omitted, delete all windows showing BUFFER in any frame.\n\
+If t, delete only windows showing BUFFER in the selected frame.\n\
+If `visible', delete all windows showing BUFFER in any visible frame.\n\
+If a frame, delete only windows showing BUFFER in that frame.")
+  (buffer, frame)
+     Lisp_Object buffer, frame;
 {
+#ifdef MULTI_FRAME
+  /* FRAME uses t and nil to mean the opposite of what window_loop
+     expects.  */
+  if (! FRAMEP (frame))
+    frame = NILP (frame) ? Qt : Qnil;
+#else
+  frame = Qt;
+#endif
+
   if (!NILP (buffer))
     {
       buffer = Fget_buffer (buffer);
       CHECK_BUFFER (buffer, 0);
-      window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, Qt);
+      window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
     }
   return Qnil;
 }
@@ -1352,13 +1433,16 @@ check_frame_size (frame, rows, cols)
      FRAME_PTR frame;
      int *rows, *cols;
 {
-  /* For height, we have to see whether the frame has a minibuffer, and
-     whether it wants a mode line.  */
+  /* For height, we have to see:
+     whether the frame has a minibuffer, 
+     whether it wants a mode line, and
+     whether it has a menu bar.  */
   int min_height =
-    ((FRAME_MINIBUF_ONLY_P (frame)
-      || ! FRAME_HAS_MINIBUF_P (frame))
-     ? MIN_SAFE_WINDOW_HEIGHT
+    (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
+     : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
      : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
+  if (FRAME_MENU_BAR_LINES (frame) > 0)
+    min_height += FRAME_MENU_BAR_LINES (frame);
 
   if (*rows < min_height)
     *rows = min_height;
@@ -1523,6 +1607,9 @@ BUFFER can be a buffer or buffer name.")
     }
 
   w->buffer = buffer;
+  w->window_end_pos = 0;
+  w->window_end_valid = Qnil;
+  w->hscroll = 0;
   Fset_marker (w->pointm,
               make_number (BUF_PT (XBUFFER (buffer))),
               buffer);
@@ -1530,6 +1617,7 @@ BUFFER can be a buffer or buffer name.")
                         make_number (XBUFFER (buffer)->last_window_start),
                         buffer);
   w->start_at_line_beg = Qnil;
+  w->force_start = Qnil;
   XFASTINT (w->last_modified) = 0;
   windows_or_buffers_changed++;
   if (EQ (window, selected_window))
@@ -1567,7 +1655,7 @@ before each command.")
   if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
     {
       XFRAME (WINDOW_FRAME (w))->selected_window = window;
-      Fselect_frame (WINDOW_FRAME (w), Qnil);
+      Fhandle_switch_frame (WINDOW_FRAME (w), Qnil);
     }
   else
     selected_frame->selected_window = window;
@@ -1596,12 +1684,13 @@ before each command.")
 }
 
 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
-       "BDisplay buffer:\nP",
+       "BDisplay buffer: \nP",
   "Make BUFFER appear in some window but don't select it.\n\
 BUFFER can be a buffer or a buffer name.\n\
 If BUFFER is shown already in some window, just use that one,\n\
 unless the window is the selected window and the optional second\n\
 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
+If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
 Returns the window displaying BUFFER.")
   (buffer, not_this_window)
      register Lisp_Object buffer, not_this_window;
@@ -1618,7 +1707,9 @@ Returns the window displaying BUFFER.")
       && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
     return selected_window;
 
-  window = Fget_buffer_window (buffer, Qnil);
+  /* If pop_up_frames,
+     look for a window showing BUFFER on any visible frame.  */
+  window = Fget_buffer_window (buffer, pop_up_frames ? Qvisible : Qnil);
   if (!NILP (window)
       && (NILP (not_this_window) || !EQ (window, selected_window)))
     return window;
@@ -1632,7 +1723,7 @@ Returns the window displaying BUFFER.")
        = Fframe_selected_window (call0 (Vpop_up_frame_function));
       Fset_window_buffer (window, buffer);
 #if 0
-      Fselect_frame (XWINDOW (window)->frame, Qnil);
+      Fhandle_switch_frame (XWINDOW (window)->frame, Qnil);
 #endif
       return window;
     }
@@ -1644,8 +1735,9 @@ Returns the window displaying BUFFER.")
 #endif
       )
     {
-      Lisp_Object frames = Qnil;
-      
+      Lisp_Object frames;
+
+      frames = Qnil;      
 #ifdef MULTI_FRAME
       if (FRAME_MINIBUF_ONLY_P (selected_frame))
        XSET (frames, Lisp_Frame, last_nonminibuf_frame);
@@ -2087,7 +2179,7 @@ window_scroll (window, n, noerror)
 
   if (NILP (tem))
     {
-      Fvertical_motion (make_number (- ht / 2));
+      Fvertical_motion (make_number (- (ht / 2)), window);
       XFASTINT (tem) = point;
       Fset_marker (w->start, tem, w->buffer);
       w->force_start = Qt;
@@ -2095,7 +2187,7 @@ window_scroll (window, n, noerror)
 
   SET_PT (marker_position (w->start));
   lose = n < 0 && point == BEGV;
-  Fvertical_motion (make_number (n));
+  Fvertical_motion (make_number (n), window);
   pos = point;
   bolp = Fbolp ();
   SET_PT (opoint);
@@ -2119,11 +2211,11 @@ window_scroll (window, n, noerror)
       if (n < 0)
        {
          SET_PT (pos);
-         tem = Fvertical_motion (make_number (ht));
+         tem = Fvertical_motion (make_number (ht), window);
          if (point > opoint || XFASTINT (tem) < ht)
            SET_PT (opoint);
          else
-           Fvertical_motion (make_number (-1));
+           Fvertical_motion (make_number (-1), window);
        }
     }
   else
@@ -2173,6 +2265,7 @@ scroll_command (n, direction)
 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
   "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
 A near full screen is `next-screen-context-lines' less than a full screen.\n\
+Negative ARG means scroll downward.\n\
 When calling from a program, supply a number as argument or nil.")
   (n)
      Lisp_Object n;
@@ -2184,6 +2277,7 @@ When calling from a program, supply a number as argument or nil.")
 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
   "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
 A near full screen is `next-screen-context-lines' less than a full screen.\n\
+Negative ARG means scroll upward.\n\
 When calling from a program, supply a number as argument or nil.")
   (n)
      Lisp_Object n;
@@ -2195,10 +2289,10 @@ When calling from a program, supply a number as argument or nil.")
 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
   "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
 The next window is the one below the current one; or the one at the top\n\
-if the current one is at the bottom.\n\
+if the current one is at the bottom.  Negative ARG means scroll downward.\n\
 When calling from a program, supply a number as argument or nil.\n\
 \n\
-If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
+If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
 specifies the window to scroll.\n\
 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
 showing that buffer, popping the buffer up if necessary.")
@@ -2267,7 +2361,7 @@ showing that buffer, popping the buffer up if necessary.")
   return Qnil;
 }
 \f
-DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 1, 1, "P",
+DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
   "Scroll selected window display ARG columns left.\n\
 Default for ARG is window width minus 2.")
   (arg)
@@ -2285,7 +2379,7 @@ Default for ARG is window width minus 2.")
                                      + XINT (arg)));
 }
 
-DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 1, 1, "P",
+DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
   "Scroll selected window display ARG columns right.\n\
 Default for ARG is window width minus 2.")
   (arg)
@@ -2314,6 +2408,7 @@ redraws with point in the center of the current window.")
   register struct window *w = XWINDOW (selected_window);
   register int ht = window_internal_height (w);
   register int opoint = point;
+  Lisp_Object window;
 
   if (NILP (n))
     {
@@ -2337,7 +2432,8 @@ redraws with point in the center of the current window.")
 
   XSETINT (n, - XINT (n));
 
-  Fvertical_motion (n);
+  XSET (window, Lisp_Window, w);
+  Fvertical_motion (n, window);
   Fset_marker (w->start, make_number (point), w->buffer);
   w->start_at_line_beg = Fbolp ();
 
@@ -2359,6 +2455,7 @@ negative means relative to bottom of window.")
   register struct window *w = XWINDOW (selected_window);
   register int height = window_internal_height (w);
   register int start;
+  Lisp_Object window;
 
   if (NILP (arg))
     XFASTINT (arg) = height / 2;
@@ -2370,9 +2467,10 @@ negative means relative to bottom of window.")
     }
 
   start = marker_position (w->start);
+  XSET (window, Lisp_Window, w);
   if (start < BEGV || start > ZV)
     {
-      Fvertical_motion (make_number (- height / 2));
+      Fvertical_motion (make_number (- (height / 2)), window);
       Fset_marker (w->start, make_number (point), w->buffer);
       w->start_at_line_beg = Fbolp ();
       w->force_start = Qt;
@@ -2380,14 +2478,14 @@ negative means relative to bottom of window.")
   else
     SET_PT (start);
 
-  return Fvertical_motion (arg);
+  return Fvertical_motion (arg, window);
 }
 \f
 struct save_window_data
   {
     int size_from_Lisp_Vector_struct;
     struct Lisp_Vector *next_from_Lisp_Vector_struct;
-    Lisp_Object frame_width, frame_height;
+    Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
     Lisp_Object selected_frame;
     Lisp_Object current_window;
     Lisp_Object current_buffer;
@@ -2436,9 +2534,8 @@ DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_
 }
 
 
-DEFUN ("set-window-configuration",
-       Fset_window_configuration, Sset_window_configuration,
-       1, 1, 0,
+DEFUN ("set-window-configuration", Fset_window_configuration,
+  Sset_window_configuration, 1, 1, 0,
   "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
 CONFIGURATION must be a value previously returned\n\
 by `current-window-configuration' (which see).")
@@ -2481,10 +2578,14 @@ by `current-window-configuration' (which see).")
         back.  We keep track of the prevailing height in these variables.  */
       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);
 
       if (XFASTINT (data->frame_height) != previous_frame_height
          || XFASTINT (data->frame_width) != previous_frame_width)
        change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
+      if (XFASTINT (data->frame_menu_bar_lines)
+         != previous_frame_menu_bar_lines)
+       x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
 
       windows_or_buffers_changed++;
 
@@ -2571,8 +2672,8 @@ by `current-window-configuration' (which see).")
                      XBUFFER (p->buffer) == current_buffer)
                    Fgoto_char (w->pointm);
                }
-             else if (NILP (XBUFFER (w->buffer)->name))
-               /* Else if window's old buffer is dead too, get a live one.  */
+             else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
+               /* Else unless window has a live buffer, get one.  */
                {
                  w->buffer = Fcdr (Fcar (Vbuffer_alist));
                  /* This will set the markers to beginning of visible
@@ -2583,8 +2684,7 @@ by `current-window-configuration' (which see).")
                }
              else
                /* Keeping window's old buffer; make sure the markers
-                  are real.  Else if window's old buffer is dead too,
-                  get a live one.  */
+                  are real.  */
                {
                  /* Set window markers at start of visible range.  */
                  if (XMARKER (w->start)->buffer == 0)
@@ -2614,7 +2714,7 @@ by `current-window-configuration' (which see).")
          when the frame's old selected window has been deleted.  */
 #ifdef MULTI_FRAME
       if (f != selected_frame && ! FRAME_TERMCAP_P (f))
-       Fselect_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
+       Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
 #endif
 #endif
 
@@ -2623,16 +2723,18 @@ by `current-window-configuration' (which see).")
          || previous_frame_width != FRAME_WIDTH (f))
        change_frame_size (f, previous_frame_height, previous_frame_width,
                           0, 0);
+      if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
+       x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
     }
 
 #ifdef MULTI_FRAME
   /* Fselect_window will have made f the selected frame, so we
-     reselect the proper frame here.  Fselect_frame will change the
+     reselect the proper frame here.  Fhandle_switch_frame will change the
      selected window too, but that doesn't make the call to
      Fselect_window above totally superfluous; it still sets f's
      selected window.  */
   if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
-    Fselect_frame (data->selected_frame, Qnil);
+    Fhandle_switch_frame (data->selected_frame, Qnil);
 #endif
 
   if (!NILP (new_current_buffer))
@@ -2785,6 +2887,7 @@ redirection (see `redirect-frame-focus').")
                                  Qnil));
   XFASTINT (data->frame_width) = FRAME_WIDTH (f);
   XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
+  XFASTINT (data->frame_menu_bar_lines) = FRAME_MENU_BAR_LINES (f);
 #ifdef MULTI_FRAME
   XSET (data->selected_frame, Lisp_Frame, selected_frame);
 #endif
@@ -2873,8 +2976,8 @@ syms_of_window ()
   Qwindowp = intern ("windowp");
   staticpro (&Qwindowp);
 
-  Qlive_window_p = intern ("live-window-p");
-  staticpro (&Qlive_window_p);
+  Qwindow_live_p = intern ("window-live-p");
+  staticpro (&Qwindow_live_p);
 
 #ifndef MULTI_FRAME
   /* Make sure all windows get marked */
@@ -2894,21 +2997,6 @@ Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
 work using this function.");
   Vdisplay_buffer_function = Qnil;
 
-  DEFVAR_LISP ("mouse-event", &Vmouse_event,
-     "The last mouse-event object.  A list of four elements:\n\
-  ((X-POS Y-POS) WINDOW FRAME-PART KEYSEQ).\n\
-KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
-WINDOW is the window that the click applies do.\n\
-If FRAME-PART is non-nil, the event was on a scroll bar;\n\
-then Y-POS is really the total length of the scroll bar, while X-POS is\n\
-the relative position of the scroll bar's value within that total length.\n\
-FRAME-PART is one of the following symbols:\n\
- `vertical-scroll-bar', `vertical-slider',\n\
- `vertical-thumbup', `vertical-thumbdown',\n\
- `horizontal-scroll-bar', `horizontal-slider',\n\
- `horizontal-thumbleft', `horizontal-thumbright'");
-  Vmouse_event = Qnil;
-
   DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
     "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
   Vminibuf_scroll_window = Qnil;
@@ -2917,7 +3005,6 @@ FRAME-PART is one of the following symbols:\n\
     "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
   Vother_window_scroll_buffer = Qnil;
 
-#ifdef MULTI_FRAME
   DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
     "*Non-nil means `display-buffer' should make a separate frame.");
   pop_up_frames = 0;
@@ -2929,7 +3016,6 @@ It is called with no arguments and should return a newly created frame.\n\
 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
 where `pop-up-frame-alist' would hold the default frame parameters.");
   Vpop_up_frame_function = Qnil;
-#endif
 
   DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
     "*Non-nil means display-buffer should make new windows.");
@@ -2956,7 +3042,7 @@ If there is only one window, it is split regardless of this value.");
   defsubr (&Sminibuffer_window);
   defsubr (&Swindow_minibuffer_p);
   defsubr (&Swindowp);
-  defsubr (&Slive_window_p);
+  defsubr (&Swindow_live_p);
   defsubr (&Spos_visible_in_window_p);
   defsubr (&Swindow_buffer);
   defsubr (&Swindow_height);