First Edition.
[bpt/emacs.git] / src / window.c
index 1c46dc8..c196937 100644 (file)
@@ -22,13 +22,13 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 #include "lisp.h"
 #include "buffer.h"
+#include "keyboard.h"
 #include "frame.h"
 #include "window.h"
 #include "commands.h"
 #include "indent.h"
 #include "termchar.h"
 #include "disptab.h"
-#include "keyboard.h"
 #include "dispextern.h"
 #include "blockinput.h"
 #include "intervals.h"
@@ -62,20 +62,20 @@ 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, int *));
 static void size_window P_ ((Lisp_Object, int, int, int));
-static int foreach_window_1 P_ ((struct window *, int (*fn) (), int, int,
-                                int, int, int, int, int, int, int));
-static int freeze_window_start P_ ((struct window *, int));
+static int freeze_window_start P_ ((struct window *, void *));
 static int window_fixed_size_p P_ ((struct window *, int, int));
 static void enlarge_window P_ ((Lisp_Object, int, int));
 static Lisp_Object window_list P_ ((void));
-static int add_window_to_list P_ ((struct window *, Lisp_Object *));
-static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
+static int add_window_to_list P_ ((struct window *, void *));
+static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
+                                  Lisp_Object));
 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
                                    Lisp_Object, int));
 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
                                         Lisp_Object *));
-
-
+static int foreach_window_1 P_ ((struct window *,
+                                int (* fn) (struct window *, void *),
+                                void *));
 
 /* This is the window in which the terminal's cursor should
    be left when nothing is being done with it.  This must
@@ -126,6 +126,10 @@ int pop_up_windows;
 
 int pop_up_frames;
 
+/* Nonzero means reuse existing frames for displaying buffers.  */
+
+int display_buffer_reuse_frames;
+
 /* Non-nil means use this function instead of default */
 
 Lisp_Object Vpop_up_frame_function;
@@ -510,7 +514,9 @@ coordinates_in_window (w, x, y)
           && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
     /* On the top line.  */
     return 4;
-  else if (*x < left_x || *x >= right_x)
+  /* Need to say "*x > right_x" rather than >=, since on character
+     terminals, the vertical line's x coordinate is right_x.  */
+  else if (*x < left_x || *x > right_x)
     {
       /* Other lines than the mode line don't include flags areas and
         scroll bars on the left.  */
@@ -520,9 +526,10 @@ coordinates_in_window (w, x, y)
       *y -= top_y;
       return *x < left_x ? 5 : 6;
     }
+  /* Here, too, "*x > right_x" is because of character terminals.  */
   else if (!w->pseudo_window_p
           && !WINDOW_RIGHTMOST_P (w)
-          && *x >= right_x - CANON_X_UNIT (f))
+          && *x > right_x - CANON_X_UNIT (f))
     /* On the border on the right side of the window?  Assume that
        this area begins at RIGHT_X minus a canonical char width.  */
     return 3;
@@ -604,24 +611,33 @@ If they are on the border between WINDOW and its right sibling,\n\
 
 
 /* Callback for foreach_window, used in window_from_coordinates.
-   Check if window W contains coordinates *X/*Y.  If it does, return W
-   in *WINDOW, as Lisp_Object, and return in *PART the part of the
-   window under coordinates *X/*Y.  Return zero from this function to
-   stop iterating over windows.  */
+   Check if window W contains coordinates specified by USER_DATA which
+   is actually a pointer to a struct check_window_data CW.
+
+   Check if window W contains coordinates *CW->x and *CW->y.  If it
+   does, return W in *CW->window, as Lisp_Object, and return in
+   *CW->part the part of the window under coordinates *X,*Y.  Return
+   zero from this function to stop iterating over windows.  */
+
+struct check_window_data
+{
+  Lisp_Object *window;
+  int *x, *y, *part;
+};
 
 static int
-check_window_containing (w, window, x, y, part)
+check_window_containing (w, user_data)
      struct window *w;
-     Lisp_Object *window;
-     int *x, *y, *part;
+     void *user_data;
 {
+  struct check_window_data *cw = (struct check_window_data *) user_data;
   int found;
 
-  found = coordinates_in_window (w, x, y);
+  found = coordinates_in_window (w, cw->x, cw->y);
   if (found)
     {
-      *part = found - 1;
-      XSETWINDOW (*window, w);
+      *cw->part = found - 1;
+      XSETWINDOW (*cw->window, w);
     }
   
   return !found;
@@ -652,9 +668,11 @@ window_from_coordinates (f, x, y, part, tool_bar_p)
      int tool_bar_p;
 {
   Lisp_Object window;
+  struct check_window_data cw;
 
   window = Qnil;
-  foreach_window (f, check_window_containing, &window, &x, &y, part);
+  cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
+  foreach_window (f, check_window_containing, &cw);
   
   /* If not found above, see if it's in the tool bar window, if a tool
      bar exists.  */
@@ -768,29 +786,29 @@ if it isn't already recorded.")
       && ! (! NILP (w->window_end_valid)
            && XFASTINT (w->last_modified) >= MODIFF))
     {
-      int opoint = PT, opoint_byte = PT_BYTE;
+      struct text_pos startp;
+      struct it it;
 
       /* 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.  */
+         rmail had already narrowed the buffer.  */
       if (XMARKER (w->start)->charpos < BEGV)
-       TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
+       SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
       else if (XMARKER (w->start)->charpos > ZV)
-       TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
+       SET_TEXT_POS (startp, 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);
+       SET_TEXT_POS_FROM_MARKER (startp, w->start);
+
+      /* Cannot use Fvertical_motion because that function doesn't
+        cope with variable-height lines.  */
+      start_display (&it, w, startp);
+      move_it_vertically (&it, window_box_height (w));
+      value = make_number (IT_CHARPOS (it));
     }
   else
-    XSETINT (value,
-            BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
+    XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
 
   return value;
 }
@@ -884,20 +902,21 @@ struct Lisp_Char_Table *
 window_display_table (w)
      struct window *w;
 {
-  Lisp_Object tem;
-  tem = w->display_table;
-  if (DISP_TABLE_P (tem))
-    return XCHAR_TABLE (tem);
-  if (NILP (w->buffer))
-    return 0;
+  struct Lisp_Char_Table *dp = NULL;
+
+  if (DISP_TABLE_P (w->display_table))
+    dp = XCHAR_TABLE (w->display_table);
+  else if (BUFFERP (w->buffer))
+    {
+      struct buffer *b = XBUFFER (w->buffer);
+      
+      if (DISP_TABLE_P (b->display_table))
+       dp = XCHAR_TABLE (b->display_table);
+      else if (DISP_TABLE_P (Vstandard_display_table))
+       dp = XCHAR_TABLE (Vstandard_display_table);
+    }
 
-  tem = XBUFFER (w->buffer)->display_table;
-  if (DISP_TABLE_P (tem))
-    return XCHAR_TABLE (tem);
-  tem = Vstandard_display_table;
-  if (DISP_TABLE_P (tem))
-    return XCHAR_TABLE (tem);
-  return 0;
+  return dp;
 }
 
 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
@@ -1180,14 +1199,16 @@ delete_window (window)
                             Window List
  ***********************************************************************/
 
-/* Add window W to *LIST.  This is a callback function for
-   foreach_window, used in function window_list.  */
+/* Add window W to *USER_DATA.  USER_DATA is actually a Lisp_Object
+   pointer.  This is a callback function for foreach_window, used in
+   function window_list.  */
 
 static int
-add_window_to_list (w, list)
+add_window_to_list (w, user_data)
      struct window *w;
-     Lisp_Object *list;
+     void *user_data;
 {
+  Lisp_Object *list = (Lisp_Object *) user_data;
   Lisp_Object window;
   XSETWINDOW (window, w);
   *list = Fcons (window, *list);
@@ -1226,24 +1247,23 @@ window_list ()
 }
 
 
-/* Value is non-zero if WINODW satisfies the constraints given by
-   MINIBUF and ALL_FRAMES.
+/* Value is non-zero if WINDOW satisfies the constraints given by
+   OWINDOW, MINIBUF and ALL_FRAMES.
 
-   MINIBUF t means WINDOW may be a minibuffer window.
-   MINIBUF `lambda' means it may not be a minibuffer window.
-   MINIBUF being a window means WINDOW must be equal to MINIBUF.
+   MINIBUF     t means WINDOW may be minibuffer windows.
+               `lambda' means WINDOW may not be a minibuffer window.
+               a window means a specific minibuffer window
 
-   ALL_FRAMES t means WINDOW may be on any frame.
-   ALL_FRAMES nil means WINDOW must not be on a minibuffer-only frame.
-   ALL_FRAMES `visible' means WINDOW must be on a visible frame.
-   ALL_FRAMES 0 means WINDOW must be on a visible or iconified frame.
-   ALL_FRAMES being a frame means WINDOW must be on that frame.
-   ALL_FRAMES being a window means WINDOW must be on a frame using
-   the same minibuffer as ALL_FRAMES.  */
+   ALL_FRAMES  t means search all frames,
+               nil means search just current frame,
+               `visible' means search just visible frames,
+               0 means search visible and iconified frames,
+               a window means search the frame that window belongs to,
+               a frame means consider windows on that frame, only.  */
 
 static int
-candidate_window_p (window, minibuf, all_frames)
-     Lisp_Object window, minibuf, all_frames;
+candidate_window_p (window, owindow, minibuf, all_frames)
+     Lisp_Object window, owindow, minibuf, all_frames;
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
@@ -1259,8 +1279,13 @@ candidate_window_p (window, minibuf, all_frames)
          If it is a window, consider only that one.  */
       candidate_p = 0;
     }
+  else if (EQ (all_frames, Qt))
+    candidate_p = 1;
   else if (NILP (all_frames))
-    candidate_p = !FRAME_MINIBUF_ONLY_P (f);
+    {
+      xassert (WINDOWP (owindow));
+      candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
+    }
   else if (EQ (all_frames, Qvisible))
     {
       FRAME_SAMPLE_VISIBILITY (f);
@@ -1271,12 +1296,12 @@ candidate_window_p (window, minibuf, all_frames)
       FRAME_SAMPLE_VISIBILITY (f);
       candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
     }
-  else if (FRAMEP (all_frames))
-    candidate_p = EQ (all_frames, w->frame);
   else if (WINDOWP (all_frames))
     candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
                   || EQ (XWINDOW (all_frames)->frame, w->frame)
                   || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
+  else if (FRAMEP (all_frames))
+    candidate_p = EQ (all_frames, w->frame);
 
   return candidate_p;
 }
@@ -1356,7 +1381,7 @@ next_window (window, minibuf, all_frames, next_p)
       /* Scan forward from WINDOW to the end of the window list.  */
       if (CONSP (list))
        for (list = XCDR (list); CONSP (list); list = XCDR (list))
-         if (candidate_window_p (XCAR (list), minibuf, all_frames))
+         if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
            break;
 
       /* Scan from the start of the window list up to WINDOW.  */
@@ -1364,7 +1389,7 @@ next_window (window, minibuf, all_frames, next_p)
        for (list = Vwindow_list;
             CONSP (list) && !EQ (XCAR (list), window);
             list = XCDR (list))
-         if (candidate_window_p (XCAR (list), minibuf, all_frames))
+         if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
            break;
 
       if (CONSP (list))
@@ -1386,7 +1411,8 @@ next_window (window, minibuf, all_frames, next_p)
              if (WINDOWP (candidate))
                break;
            }
-         else if (candidate_window_p (XCAR (list), minibuf, all_frames))
+         else if (candidate_window_p (XCAR (list), window, minibuf,
+                                      all_frames))
            candidate = XCAR (list);
        }
 
@@ -1507,10 +1533,10 @@ argument ALL_FRAMES is non-nil, cycle through all frames.")
 
 
 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
-  "Return a list windows in canonical ordering.\n\
+  "Return a list of windows in canonical ordering.\n\
 Arguments are like for `next-window'.")
   (window, minibuf, all_frames)
-     Lisp_Object minibuf, all_frames;
+     Lisp_Object window, minibuf, all_frames;
 {
   Lisp_Object tail, list;
 
@@ -1518,10 +1544,10 @@ Arguments are like for `next-window'.")
   list = Qnil;
   
   for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
-    if (candidate_window_p (XCAR (tail), minibuf, all_frames))
+    if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
       list = Fcons (XCAR (tail), list);
   
-  return list;
+  return Fnreverse (list);
 }
 
 
@@ -1550,32 +1576,31 @@ enum window_loop
 static Lisp_Object
 window_loop (type, obj, mini, frames)
      enum window_loop type;
-     register Lisp_Object obj, frames;
+     Lisp_Object obj, frames;
      int mini;
 {
-  register Lisp_Object w;
-  register Lisp_Object best_window;
-  register Lisp_Object next_window;
-  register Lisp_Object last_window;
-  FRAME_PTR frame;
-  Lisp_Object frame_arg;
-  frame_arg = Qt;
-
+  Lisp_Object window, windows, best_window, frame_arg;
+  struct frame *f;
+  struct gcpro gcpro1;
+  
   /* If we're only looping through windows on a particular frame,
      frame points to that frame.  If we're looping through windows
      on all frames, frame is 0.  */
   if (FRAMEP (frames))
-    frame = XFRAME (frames);
+    f = XFRAME (frames);
   else if (NILP (frames))
-    frame = SELECTED_FRAME ();
+    f = SELECTED_FRAME ();
   else
-    frame = 0;
-  if (frame)
+    f = NULL;
+  
+  if (f)
     frame_arg = Qlambda;
   else if (XFASTINT (frames) == 0)
     frame_arg = frames;
   else if (EQ (frames, Qvisible))
     frame_arg = frames;
+  else
+    frame_arg = Qt;
 
   /* frame_arg is Qlambda to stick to one frame,
      Qvisible to consider all visible frames,
@@ -1583,11 +1608,11 @@ window_loop (type, obj, mini, frames)
 
   /* Pick a window to start with.  */
   if (WINDOWP (obj))
-    w = obj;
-  else if (frame)
-    w = FRAME_SELECTED_WINDOW (frame);
+    window = obj;
+  else if (f)
+    window = FRAME_SELECTED_WINDOW (f);
   else
-    w = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
+    window = 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
@@ -1596,178 +1621,165 @@ window_loop (type, obj, mini, frames)
      We can't just wait until we hit the first window again, because
      it might be deleted.  */
 
-  last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
-
+  windows = Fwindow_list (window, mini ? Qt : Qnil, frame_arg);
+  GCPRO1 (windows);
   best_window = Qnil;
-  for (;;)
+
+  for (; CONSP (windows); windows = CDR (windows))
     {
-      /* Pick the next window now, since some operations will delete
-        the current window.  */
-      next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
-
-      /* 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))
+      struct window *w;
+      
+      window = XCAR (windows);
+      w = XWINDOW (window);
+      
+      /* Note that we do not pay attention here to whether the frame
+        is visible, since Fwindow_list skips non-visible frames if
+        that is desired, under the control of frame_arg.  */
+      if (!MINI_WINDOW_P (w)
          /* For UNSHOW_BUFFER, we must always consider all windows.  */
          || type == UNSHOW_BUFFER
          || (mini && minibuf_level > 0))
        switch (type)
          {
          case GET_BUFFER_WINDOW:
-           if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj)
+           if (EQ (w->buffer, obj)
                /* Don't find any minibuffer window
                   except the one that is currently in use.  */
-               && (MINI_WINDOW_P (XWINDOW (w))
-                   ? EQ (w, minibuf_window) : 1))
-             return w;
+               && (MINI_WINDOW_P (w)
+                   ? EQ (window, minibuf_window)
+                   : 1))
+             {
+               UNGCPRO;
+               return window;
+             }
            break;
 
          case GET_LRU_WINDOW:
            /* t as arg means consider only full-width windows */
-           if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (XWINDOW (w)))
+           if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
              break;
            /* Ignore dedicated windows and minibuffers.  */
-           if (MINI_WINDOW_P (XWINDOW (w))
-               || !NILP (XWINDOW (w)->dedicated))
+           if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
              break;
            if (NILP (best_window)
                || (XFASTINT (XWINDOW (best_window)->use_time)
-                   > XFASTINT (XWINDOW (w)->use_time)))
-             best_window = w;
+                   > XFASTINT (w->use_time)))
+             best_window = window;
            break;
 
          case DELETE_OTHER_WINDOWS:
-           if (XWINDOW (w) != XWINDOW (obj))
-             Fdelete_window (w);
+           if (!EQ (window, obj))
+             Fdelete_window (window);
            break;
 
          case DELETE_BUFFER_WINDOWS:
-           if (EQ (XWINDOW (w)->buffer, obj))
+           if (EQ (w->buffer, obj))
              {
-               FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
+               struct frame *f = XFRAME (WINDOW_FRAME (w));
 
                /* If this window is dedicated, and in a frame of its own,
                   kill the frame.  */
-               if (EQ (w, FRAME_ROOT_WINDOW (f))
-                   && !NILP (XWINDOW (w)->dedicated)
+               if (EQ (window, FRAME_ROOT_WINDOW (f))
+                   && !NILP (w->dedicated)
                    && other_visible_frames (f))
                  {
                    /* Skip the other windows on this frame.
                       There might be one, the minibuffer!  */
-                   if (! EQ (w, last_window))
-                     while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
-                       {
-                         /* As we go, check for the end of the loop.
-                            We mustn't start going around a second time.  */
-                         if (EQ (next_window, last_window))
-                           {
-                             last_window = w;
-                             break;
-                           }
-                         next_window = Fnext_window (next_window,
-                                                     mini ? Qt : Qnil,
-                                                     frame_arg);
-                       }
+                   while (CONSP (XCDR (windows))
+                          && EQ (XWINDOW (XCAR (windows))->frame,
+                                 XWINDOW (XCAR (XCDR (windows)))->frame))
+                     windows = XCDR (windows);
+                   
                    /* Now we can safely delete the frame.  */
-                   Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
+                   Fdelete_frame (w->frame, Qnil);
+                 }
+               else if (NILP (w->parent))
+                 {
+                   /* If we're deleting the buffer displayed in the
+                      only window on the frame, find a new buffer to
+                      display there.  */
+                   Lisp_Object buffer;
+                   buffer = Fother_buffer (obj, Qnil, w->frame);
+                   if (NILP (buffer))
+                     buffer = Fget_buffer_create (build_string ("*scratch*"));
+                   Fset_window_buffer (window, buffer);
+                   if (EQ (window, selected_window))
+                     Fset_buffer (w->buffer);
                  }
                else
-                 /* If we're deleting the buffer displayed in the only window
-                    on the frame, find a new buffer to display there.  */
-                 if (NILP (XWINDOW (w)->parent))
-                   {
-                     Lisp_Object new_buffer;
-                     new_buffer = Fother_buffer (obj, Qnil,
-                                                 XWINDOW (w)->frame);
-                     if (NILP (new_buffer))
-                       new_buffer
-                         = Fget_buffer_create (build_string ("*scratch*"));
-                     Fset_window_buffer (w, new_buffer);
-                     if (EQ (w, selected_window))
-                       Fset_buffer (XWINDOW (w)->buffer);
-                   }
-                 else
-                   Fdelete_window (w);
+                 Fdelete_window (window);
              }
            break;
 
          case GET_LARGEST_WINDOW:
-           /* Ignore dedicated windows and minibuffers.  */
-           if (MINI_WINDOW_P (XWINDOW (w))
-               || !NILP (XWINDOW (w)->dedicated)
-               || NILP (best_window))
-             break;
            {
-             struct window *best_window_ptr = XWINDOW (best_window);
-             struct window *w_ptr = XWINDOW (w);
-             if (NILP (best_window)
-                 || (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width)
-                     > (XFASTINT (best_window_ptr->height)
-                        * XFASTINT (best_window_ptr->width))))
-               best_window = w;
+             /* Ignore dedicated windows and minibuffers.  */
+             if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
+               break;
+             
+             if (NILP (best_window))
+               best_window = window;
+             else
+               {
+                 struct window *b = XWINDOW (best_window);
+                 if (XFASTINT (w->height) * XFASTINT (w->width)
+                     > XFASTINT (b->height) * XFASTINT (b->width))
+                   best_window = window;
+               }
            }
            break;
 
          case UNSHOW_BUFFER:
-           if (EQ (XWINDOW (w)->buffer, obj))
+           if (EQ (w->buffer, obj))
              {
+               Lisp_Object buffer;
+               struct frame *f = XFRAME (w->frame);
+               
                /* Find another buffer to show in this window.  */
-               Lisp_Object another_buffer;
-               FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
-               another_buffer = Fother_buffer (obj, Qnil, XWINDOW (w)->frame);
-               if (NILP (another_buffer))
-                 another_buffer
-                   = Fget_buffer_create (build_string ("*scratch*"));
+               buffer = Fother_buffer (obj, Qnil, w->frame);
+               if (NILP (buffer))
+                 buffer = Fget_buffer_create (build_string ("*scratch*"));
+               
                /* If this window is dedicated, and in a frame of its own,
                   kill the frame.  */
-               if (EQ (w, FRAME_ROOT_WINDOW (f))
-                   && !NILP (XWINDOW (w)->dedicated)
+               if (EQ (window, FRAME_ROOT_WINDOW (f))
+                   && !NILP (w->dedicated)
                    && other_visible_frames (f))
                  {
                    /* Skip the other windows on this frame.
                       There might be one, the minibuffer!  */
-                   if (! EQ (w, last_window))
-                     while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
-                       {
-                         /* As we go, check for the end of the loop.
-                            We mustn't start going around a second time.  */
-                         if (EQ (next_window, last_window))
-                           {
-                             last_window = w;
-                             break;
-                           }
-                         next_window = Fnext_window (next_window,
-                                                     mini ? Qt : Qnil,
-                                                     frame_arg);
-                       }
+                   while (CONSP (XCDR (windows))
+                          && EQ (XWINDOW (XCAR (windows))->frame,
+                                 XWINDOW (XCAR (XCDR (windows)))->frame))
+                     windows = XCDR (windows);
+                   
                    /* Now we can safely delete the frame.  */
-                   Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
+                   Fdelete_frame (w->frame, Qnil);
                  }
                else
                  {
                    /* Otherwise show a different buffer in the window.  */
-                   XWINDOW (w)->dedicated = Qnil;
-                   Fset_window_buffer (w, another_buffer);
-                   if (EQ (w, selected_window))
-                     Fset_buffer (XWINDOW (w)->buffer);
+                   w->dedicated = Qnil;
+                   Fset_window_buffer (window, buffer);
+                   if (EQ (window, selected_window))
+                     Fset_buffer (w->buffer);
                  }
              }
            break;
 
            /* Check for a window that has a killed buffer.  */
          case CHECK_ALL_WINDOWS:
-           if (! NILP (XWINDOW (w)->buffer)
-               && NILP (XBUFFER (XWINDOW (w)->buffer)->name))
+           if (! NILP (w->buffer)
+               && NILP (XBUFFER (w->buffer)->name))
              abort ();
-         }
-
-      if (EQ (w, last_window))
-       break;
+           break;
 
-      w = next_window;
+         case WINDOW_LOOP_UNUSED:
+           break;
+         }
     }
 
+  UNGCPRO;
   return best_window;
 }
 
@@ -2722,6 +2734,8 @@ 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.\n\
+If `display-reuse-frames' is non-nil, and another frame is currently\n\
+displaying BUFFER, then simply raise that frame.\n\
 \n\
 The variables `special-display-buffer-names', `special-display-regexps',\n\
 `same-window-buffer-names', and `same-window-regexps' customize how certain\n\
@@ -2733,7 +2747,7 @@ If FRAME is t, search all frames.\n\
 If FRAME is a frame, search only that frame.\n\
 If FRAME is nil, search only the selected frame\n\
  (actually the last nonminibuffer frame),\n\
- unless `pop-up-frames' is non-nil,\n\
+ unless `pop-up-frames' or `display-reuse-frames' is non-nil,\n\
  which means search visible and iconified frames.")
   (buffer, not_this_window, frame)
      register Lisp_Object buffer, not_this_window, frame;
@@ -2764,21 +2778,22 @@ If FRAME is nil, search only the selected frame\n\
        }
     }
 
-  /* If pop_up_frames,
+  /* If the user wants pop-up-frames or display-reuse-frames, then
      look for a window showing BUFFER on any visible or iconified frame.
      Otherwise search only the current frame.  */
   if (! NILP (frame))
     tem = frame;
-  else if (pop_up_frames || last_nonminibuf_frame == 0)
+  else if (pop_up_frames
+          || display_buffer_reuse_frames
+          || last_nonminibuf_frame == 0)
     XSETFASTINT (tem, 0);
   else
     XSETFRAME (tem, last_nonminibuf_frame);
+  
   window = Fget_buffer_window (buffer, tem);
   if (!NILP (window)
       && (NILP (not_this_window) || !EQ (window, selected_window)))
-    {
-      return display_buffer_1 (window);
-    }
+    return display_buffer_1 (window);
 
   /* Certain buffer names get special handling.  */
   if (!NILP (Vspecial_display_function) && NILP (swp))
@@ -3467,6 +3482,8 @@ shrink_window_lowest_first (w, height)
       Lisp_Object last_child;
       int delta = old_height - height;
       int last_top;
+
+      last_child = Qnil;
       
       /* Find the last child.  We are taking space from lowest windows
         first, so we iterate over children from the last child
@@ -4741,6 +4758,8 @@ delete_all_subwindows (w)
   w->buffer = Qnil;
   w->vchild = Qnil;
   w->hchild = Qnil;
+
+  Vwindow_list = Qnil;
 }
 \f
 static int
@@ -5088,42 +5107,39 @@ non-negative multiple of the canonical character height of WINDOW.")
 \f
 /* Call FN for all leaf windows on frame F.  FN is called with the
    first argument being a pointer to the leaf window, and with
-   additional arguments A1..A9.  Stops when FN returns 0.  */
+   additional argument USER_DATA.  Stops when FN returns 0.  */
 
 void
-foreach_window (f, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+foreach_window (f, fn, user_data)
      struct frame *f;
-     int (* fn) ();
-     int a1, a2, a3, a4, a5, a6, a7, a8, a9;
+     int (* fn) P_ ((struct window *, void *));
+     void *user_data;
 {
-  foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)),
-                   fn, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+  foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
 }
 
 
 /* Helper function for foreach_window.  Call FN for all leaf windows
    reachable from W.  FN is called with the first argument being a
-   pointer to the leaf window, and with additional arguments A1..A9.
+   pointer to the leaf window, and with additional argument USER_DATA.
    Stop when FN returns 0.  Value is 0 if stopped by FN.  */
 
 static int
-foreach_window_1 (w, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+foreach_window_1 (w, fn, user_data)
      struct window *w;
-     int (* fn) ();
-     int a1, a2, a3, a4, a5, a6, a7, a8, a9;
+     int (* fn) P_ ((struct window *, void *));
+     void *user_data;
 {
   int cont;
   
   for (cont = 1; w && cont;)
     {
       if (!NILP (w->hchild))
-       cont = foreach_window_1 (XWINDOW (w->hchild),
-                                fn, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+       cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
       else if (!NILP (w->vchild))
-       cont = foreach_window_1 (XWINDOW (w->vchild),
-                                fn, a1, a2, a3, a4, a5, a6, a7, a8, a9);
-      else if (fn (w, a1, a2, a3, a4, a5, a6, a7, a8, a9) == 0)
-       cont = 0;
+       cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
+      else 
+       cont = fn (w, user_data);
       
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
     }
@@ -5133,22 +5149,22 @@ foreach_window_1 (w, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
 
 
 /* Freeze or unfreeze the window start of W if unless it is a
-   mini-window or the selected window.  FREEZE_P non-zero means freeze
+   mini-window or the selected window.  FREEZE_P non-null means freeze
    the window start.  */
 
 static int
 freeze_window_start (w, freeze_p)
      struct window *w;
-     int freeze_p;
+     void *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;
+    freeze_p = NULL;
   
-  w->frozen_window_start_p = freeze_p;
+  w->frozen_window_start_p = freeze_p != NULL;
   return 1;
 }
 
@@ -5162,7 +5178,7 @@ freeze_window_starts (f, freeze_p)
      struct frame *f;
      int freeze_p;
 {
-  foreach_window (f, freeze_window_start, freeze_p);
+  foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
 }
 
 \f
@@ -5363,6 +5379,11 @@ work using this function.");
     "*Non-nil means `display-buffer' should make a separate frame.");
   pop_up_frames = 0;
 
+  DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
+    "*Non-nil means `display-buffer' should reuse frames.\n\
+If the buffer in question is already displayed in a frame, raise that frame.");
+  display_buffer_reuse_frames = 0;
+
   DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
     "Function to call to handle automatic new frame creation.\n\
 It is called with no arguments and should return a newly created frame.\n\