]> code.delx.au - gnu-emacs/blobdiff - src/frame.c
(Fset_text_properties): Special case for getting
[gnu-emacs] / src / frame.c
index ce1c45779d0fa027566a9e84c560f04914dffdef..5c6e44e936adea11deeeb5b807e2bc4cc1a5bb83 100644 (file)
@@ -1,5 +1,5 @@
 /* Generic frame functions.
-   Copyright (C) 1989, 1992 Free Software Foundation.
+   Copyright (C) 1993, 1994 Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -17,16 +17,17 @@ 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 <stdio.h>
+#include <config.h>
 
-#include "config.h"
+#include <stdio.h>
 #include "lisp.h"
 #include "frame.h"
+#include "termhooks.h"
+#include "window.h"
 
 #ifdef MULTI_FRAME
 
-#include "window.h"
-#include "termhooks.h"
+#include "buffer.h"
 
 /* These help us bind and responding to switch-frame events.  */
 #include "commands.h"
@@ -73,20 +74,23 @@ Lisp_Object Vdefault_frame_alist;
 
 /*&&& symbols declared here &&&*/
 Lisp_Object Qframep;
-Lisp_Object Qlive_frame_p;
+Lisp_Object Qframe_live_p;
 Lisp_Object Qheight;
 Lisp_Object Qicon;
 Lisp_Object Qminibuffer;
 Lisp_Object Qmodeline;
 Lisp_Object Qname;
-Lisp_Object Qnone;
 Lisp_Object Qonly;
 Lisp_Object Qunsplittable;
+Lisp_Object Qmenu_bar_lines;
 Lisp_Object Qwidth;
 Lisp_Object Qx;
+Lisp_Object Qvisible;
 
 extern Lisp_Object Vminibuffer_list;
 extern Lisp_Object get_minibuffer ();
+extern Lisp_Object Fhandle_switch_frame ();
+extern Lisp_Object Fredirect_frame_focus ();
 \f
 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
   "Return non-nil if OBJECT is a frame.\n\
@@ -96,7 +100,7 @@ Also see `live-frame-p'.")
   (object)
      Lisp_Object object;
 {
-  if (XTYPE (object) != Lisp_Frame)
+  if (!FRAMEP (object))
     return Qnil;
   switch (XFRAME (object)->output_method)
     {
@@ -109,7 +113,7 @@ Also see `live-frame-p'.")
     }
 }
 
-DEFUN ("live-frame-p", Flive_frame_p, Slive_frame_p, 1, 1, 0,
+DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
   "Return non-nil if OBJECT is a frame which has not been deleted.\n\
 Value is nil if OBJECT is not a live frame.  If object is a live\n\
 frame, the return value indicates what sort of output device it is\n\
@@ -145,18 +149,27 @@ make_frame (mini_p)
   f->current_glyphs = 0;
   f->desired_glyphs = 0;
   f->visible = 0;
+  f->async_visible = 0;
   f->display.nothing = 0;
   f->iconified = 0;
+  f->async_iconified = 0;
   f->wants_modeline = 1;
   f->auto_raise = 0;
   f->auto_lower = 0;
   f->no_split = 0;
   f->garbaged = 0;
   f->has_minibuffer = mini_p;
-  f->focus_frame = frame;
+  f->focus_frame = Qnil;
   f->explicit_name = 0;
-
+  f->can_have_scroll_bars = 0;
+  f->has_vertical_scroll_bars = 0;
   f->param_alist = Qnil;
+  f->scroll_bars = Qnil;
+  f->condemned_scroll_bars = Qnil;
+  f->face_alist = Qnil;
+  f->menu_bar_items = Qnil;
+  f->menu_bar_vector = Qnil;
+  f->menu_bar_items_used = 0;
 
   root_window = make_window ();
   if (mini_p)
@@ -184,14 +197,14 @@ make_frame (mini_p)
   f->width = 10;
   f->height = 10;
 
-  XFASTINT (XWINDOW (root_window)->width) = 10;
-  XFASTINT (XWINDOW (root_window)->height) = (mini_p ? 9 : 10);
+  XSETFASTINT (XWINDOW (root_window)->width, 10);
+  XSETFASTINT (XWINDOW (root_window)->height, (mini_p ? 9 : 10));
 
   if (mini_p)
     {
-      XFASTINT (XWINDOW (mini_window)->width) = 10;
-      XFASTINT (XWINDOW (mini_window)->top) = 9;
-      XFASTINT (XWINDOW (mini_window)->height) = 1;
+      XSETFASTINT (XWINDOW (mini_window)->width, 10);
+      XSETFASTINT (XWINDOW (mini_window)->top, 9);
+      XSETFASTINT (XWINDOW (mini_window)->height, 1);
     }
 
   /* Choose a buffer for the frame's root window.  */
@@ -220,9 +233,7 @@ make_frame (mini_p)
   f->selected_window = root_window;
   /* Make sure this window seems more recently used than
      a newly-created, never-selected window.  */
-  XFASTINT (XWINDOW (f->selected_window)->use_time) = ++window_select_count;
-
-  Vframe_list = Fcons (frame, Vframe_list);
+  XSETFASTINT (XWINDOW (f->selected_window)->use_time, ++window_select_count);
 
   return f;
 }
@@ -240,7 +251,7 @@ make_frame_without_minibuffer (mini_window)
   /* Choose the minibuffer window to use.  */
   if (NILP (mini_window))
     {
-      if (XTYPE (Vdefault_minibuffer_frame) != Lisp_Frame)
+      if (!FRAMEP (Vdefault_minibuffer_frame))
        error ("default-minibuffer-frame must be set when creating minibufferless frames");
       if (! FRAME_LIVE_P (XFRAME (Vdefault_minibuffer_frame)))
        error ("default-minibuffer-frame must be a live frame");
@@ -248,7 +259,7 @@ make_frame_without_minibuffer (mini_window)
     }
   else
     {
-      CHECK_WINDOW (mini_window, 0);
+      CHECK_LIVE_WINDOW (mini_window, 0);
     }
 
   /* Make a frame containing just a root window.  */
@@ -274,7 +285,7 @@ make_minibuffer_frame ()
   register Lisp_Object mini_window;
   register Lisp_Object frame;
 
-  XSET (frame, Lisp_Frame, f);
+  XSETFRAME (frame, f);
 
   f->auto_raise = 0;
   f->auto_lower = 0;
@@ -307,27 +318,25 @@ struct frame *
 make_terminal_frame ()
 {
   register struct frame *f;
+  Lisp_Object frame;
 
   Vframe_list = Qnil;
   f = make_frame (1);
+
+  XSETFRAME (frame, f);
+  Vframe_list = Fcons (frame, Vframe_list);
+
   f->name = build_string ("terminal");
-  f->visible = 1;
+  FRAME_SET_VISIBLE (f, 1);
   f->display.nothing = 1;   /* Nonzero means frame isn't deleted.  */
-  XSET (Vterminal_frame, Lisp_Frame, f);
+  XSETFRAME (Vterminal_frame, f);
   return f;
 }
 \f
-DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
-  "Select the frame FRAME.  FRAME's selected window becomes \"the\"\n\
-selected window.  If the optional parameter NO-ENTER is non-nil, don't\n\
-focus on that frame.\n\
-\n\
-This function is interactive, and may be bound to the ``switch-frame''\n\
-event; when invoked this way, it switches to the frame named in the\n\
-event.  When called from lisp, FRAME may be a ``switch-frame'' event;\n\
-if it is, select the frame named in the event.")
-  (frame, no_enter)
+static Lisp_Object
+do_switch_frame (frame, no_enter, track)
      Lisp_Object frame, no_enter;
+     int track;
 {
   /* If FRAME is a switch-frame event, extract the frame we should
      switch to.  */
@@ -336,49 +345,153 @@ if it is, select the frame named in the event.")
       && CONSP (XCONS (frame)->cdr))
     frame = XCONS (XCONS (frame)->cdr)->car;
 
-  CHECK_LIVE_FRAME (frame, 0);
+  /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
+     a switch-frame event to arrive after a frame is no longer live,
+     especially when deleting the initial frame during startup.  */
+  CHECK_FRAME (frame, 0);
+  if (! FRAME_LIVE_P (XFRAME (frame)))
+    return Qnil;
 
   if (selected_frame == XFRAME (frame))
     return frame;
 
-  selected_frame = XFRAME (frame);
-  if (! FRAME_MINIBUF_ONLY_P (selected_frame))
-    last_nonminibuf_frame = selected_frame;
+  /* This is too greedy; it causes inappropriate focus redirection
+     that's hard to get rid of.  */
+#if 0
+  /* If a frame's focus has been redirected toward the currently
+     selected frame, we should change the redirection to point to the
+     newly selected frame.  This means that if the focus is redirected
+     from a minibufferless frame to a surrogate minibuffer frame, we
+     can use `other-window' to switch between all the frames using
+     that minibuffer frame, and the focus redirection will follow us
+     around.  */
+  if (track)
+    {
+      Lisp_Object tail;
 
-  Fselect_window (XFRAME (frame)->selected_window);
+      for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+       {
+         Lisp_Object focus;
+
+         if (!FRAMEP (XCONS (tail)->car))
+           abort ();
 
+         focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
+
+         if (FRAMEP (focus) && XFRAME (focus) == selected_frame)
+           Fredirect_frame_focus (XCONS (tail)->car, frame);
+       }
+    }
+#else /* ! 0 */
+  /* Instead, apply it only to the frame we're pointing to.  */
 #ifdef HAVE_X_WINDOWS
-#ifdef MULTI_FRAME
-  if (FRAME_X_P (XFRAME (frame))
-      && NILP (no_enter))
+  if (track)
     {
-      Ffocus_frame (frame);
+      Lisp_Object focus, xfocus;
+
+      xfocus = x_get_focus_frame ();
+      if (FRAMEP (xfocus))
+       {
+         focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
+         if (FRAMEP (focus) && XFRAME (focus) == selected_frame)
+           Fredirect_frame_focus (xfocus, frame);
+       }
     }
-#endif
-#endif
+#endif /* HAVE_X_WINDOWS */
+#endif /* ! 0 */
+
+  selected_frame = XFRAME (frame);
+  if (! FRAME_MINIBUF_ONLY_P (selected_frame))
+    last_nonminibuf_frame = selected_frame;
+
+  Fselect_window (XFRAME (frame)->selected_window);
   choose_minibuf_frame ();
 
+  /* We want to make sure that the next event generates a frame-switch
+     event to the appropriate frame.  This seems kludgy to me, but
+     before you take it out, make sure that evaluating something like
+     (select-window (frame-root-window (new-frame))) doesn't end up
+     with your typing being interpreted in the new frame instead of
+     the one you're actually typing in.  */
+  internal_last_event_frame = Qnil;
+
   return frame;
 }
 
+DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
+  "Select the frame FRAME.\n\
+Subsequent editing commands apply to its selected window.\n\
+The selection of FRAME lasts until the next time the user does\n\
+something to select a different frame, or until the next time this\n\
+function is called.")
+  (frame, no_enter)
+    Lisp_Object frame, no_enter;
+{
+  return do_switch_frame (frame, no_enter, 1);
+}
+
+
+DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
+  "Handle a switch-frame event EVENT.\n\
+Switch-frame events are usually bound to this function.\n\
+A switch-frame event tells Emacs that the window manager has requested\n\
+that the user's events be directed to the frame mentioned in the event.\n\
+This function selects the selected window of the frame of EVENT.\n\
+\n\
+If EVENT is frame object, handle it as if it were a switch-frame event\n\
+to that frame.")
+  (frame, no_enter)
+     Lisp_Object frame, no_enter;
+{
+  return do_switch_frame (frame, no_enter, 0);
+}
+
+
 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
   "Return the frame that is now selected.")
   ()
 {
   Lisp_Object tem;
-  XSET (tem, Lisp_Frame, selected_frame);
+  XSETFRAME (tem, selected_frame);
   return tem;
 }
-
+\f
 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
   "Return the frame object that window WINDOW is on.")
   (window)
      Lisp_Object window;
 {
-  CHECK_WINDOW (window, 0);
+  CHECK_LIVE_WINDOW (window, 0);
   return XWINDOW (window)->frame;
 }
 
+DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
+  "Returns the topmost, leftmost window of FRAME.\n\
+If omitted, FRAME defaults to the currently selected frame.")
+  (frame)
+     Lisp_Object frame;
+{
+  Lisp_Object w;
+
+  if (NILP (frame))
+    w = selected_frame->root_window;
+  else
+    {
+      CHECK_LIVE_FRAME (frame, 0);
+      w = XFRAME (frame)->root_window;
+    }
+  while (NILP (XWINDOW (w)->buffer))
+    {
+      if (! NILP (XWINDOW (w)->hchild))
+       w = XWINDOW (w)->hchild;
+      else if (! NILP (XWINDOW (w)->vchild))
+       w = XWINDOW (w)->vchild;
+      else
+       abort ();
+    }
+  return w;
+}
+
 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
        "Returns the root-window of FRAME.\n\
 If omitted, FRAME defaults to the currently selected frame.")
@@ -386,7 +499,7 @@ If omitted, FRAME defaults to the currently selected frame.")
      Lisp_Object frame;
 {
   if (NILP (frame))
-    XSET (frame, Lisp_Frame, selected_frame);
+    XSETFRAME (frame, selected_frame);
   else
     CHECK_LIVE_FRAME (frame, 0);
 
@@ -401,13 +514,37 @@ If omitted, FRAME defaults to the currently selected frame.")
      Lisp_Object frame;
 {
   if (NILP (frame))
-    XSET (frame, Lisp_Frame, selected_frame);
+    XSETFRAME (frame, selected_frame);
   else
     CHECK_LIVE_FRAME (frame, 0);
 
   return XFRAME (frame)->selected_window;
 }
 
+DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
+       Sset_frame_selected_window, 2, 2, 0,
+  "Set the selected window of frame object FRAME to WINDOW.\n\
+If FRAME is nil, the selected frame is used.\n\
+If FRAME is the selected frame, this makes WINDOW the selected window.")
+  (frame, window)
+     Lisp_Object frame, window;
+{
+  if (NILP (frame))
+    XSETFRAME (frame, selected_frame);
+  else
+    CHECK_LIVE_FRAME (frame, 0);
+
+  CHECK_LIVE_WINDOW (window, 1);
+
+  if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
+    error ("In `set-frame-selected-window', WINDOW is not on FRAME");
+
+  if (XFRAME (frame) == selected_frame)
+    return Fselect_window (window);
+
+  return XFRAME (frame)->selected_window = window;
+}
+\f
 DEFUN ("frame-list", Fframe_list, Sframe_list,
        0, 0, 0,
        "Return a list of all frames.")
@@ -416,13 +553,14 @@ DEFUN ("frame-list", Fframe_list, Sframe_list,
   return Fcopy_sequence (Vframe_list);
 }
 
-#ifdef MULTI_FRAME
-
 /* Return the next frame in the frame list after FRAME.
    If MINIBUF is nil, exclude minibuffer-only frames.
-   If MINIBUF is a window, include only frames using that window for
-   their minibuffer.
-   If MINIBUF is non-nil, and not a window, include all frames.  */
+   If MINIBUF is a window, include only its own frame
+   and any frame now using that window as the minibuffer.
+   If MINIBUF is `visible', include all visible frames.
+   If MINIBUF is 0, include all visible and iconified frames.
+   Otherwise, include all frames.  */
+
 Lisp_Object
 next_frame (frame, minibuf)
      Lisp_Object frame;
@@ -435,11 +573,16 @@ next_frame (frame, minibuf)
   if (! CONSP (Vframe_list))
     abort ();
 
+  /* If this frame is dead, it won't be in Vframe_list, and we'll loop
+     forever.  Forestall that.  */
+  CHECK_LIVE_FRAME (frame, 0);
+
   while (1)
     for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
       {
-       Lisp_Object f = XCONS (tail)->car;
+       Lisp_Object f;
 
+       f = XCONS (tail)->car;
        if (passed)
          {
            /* Decide whether this frame is eligible to be returned.  */
@@ -455,9 +598,27 @@ next_frame (frame, minibuf)
                if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
                  return f;
              }
-           else if (XTYPE (minibuf) == Lisp_Window)
+           else if (EQ (minibuf, Qvisible))
+             {
+               FRAME_SAMPLE_VISIBILITY (XFRAME (f));
+               if (FRAME_VISIBLE_P (XFRAME (f)))
+                 return f;
+             }
+           else if (XFASTINT (minibuf) == 0)
+             {
+               FRAME_SAMPLE_VISIBILITY (XFRAME (f));
+               if (FRAME_VISIBLE_P (XFRAME (f))
+                   || FRAME_ICONIFIED_P (XFRAME (f)))
+                 return f;
+             }
+           else if (WINDOWP (minibuf))
              {
-               if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
+               if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
+                   /* Check that F either is, or has forwarded its focus to,
+                      MINIBUF's frame.  */
+                   && (EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
+                       || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
+                              FRAME_FOCUS_FRAME (XFRAME (f)))))
                  return f;
              }
            else
@@ -469,14 +630,14 @@ next_frame (frame, minibuf)
       }
 }
 
-#if 0
-/* Nobody seems to be using this code right now.  */
-
 /* Return the previous frame in the frame list before FRAME.
    If MINIBUF is nil, exclude minibuffer-only frames.
-   If MINIBUF is a window, include only frames using that window for
-   their minibuffer.
-   If MINIBUF is non-nil and not a window, include all frames.  */
+   If MINIBUF is a window, include only its own frame
+   and any frame now using that window as the minibuffer.
+   If MINIBUF is `visible', include all visible frames.
+   If MINIBUF is 0, include all visible and iconified frames.
+   Otherwise, include all frames.  */
+
 Lisp_Object
 prev_frame (frame, minibuf)
      Lisp_Object frame;
@@ -492,9 +653,10 @@ prev_frame (frame, minibuf)
   prev = Qnil;
   for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
     {
-      Lisp_Object f = XCONS (tail)->car;
+      Lisp_Object f;
 
-      if (XTYPE (f) != Lisp_Frame)
+      f = XCONS (tail)->car;
+      if (!FRAMEP (f))
        abort ();
 
       if (EQ (frame, f) && !NILP (prev))
@@ -507,9 +669,27 @@ prev_frame (frame, minibuf)
          if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
            prev = f;
        }
-      else if (XTYPE (minibuf) == Lisp_Window)
+      else if (WINDOWP (minibuf))
+       {
+         if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
+             /* Check that F either is, or has forwarded its focus to,
+                MINIBUF's frame.  */
+             && (EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
+                 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
+                        FRAME_FOCUS_FRAME (XFRAME (f)))))
+           prev = f;
+       }
+      else if (EQ (minibuf, Qvisible))
        {
-         if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf))
+         FRAME_SAMPLE_VISIBILITY (XFRAME (f));
+         if (FRAME_VISIBLE_P (XFRAME (f)))
+           prev = f;
+       }
+      else if (XFASTINT (minibuf) == 0)
+       {
+         FRAME_SAMPLE_VISIBILITY (XFRAME (f));
+         if (FRAME_VISIBLE_P (XFRAME (f))
+             || FRAME_ICONIFIED_P (XFRAME (f)))
            prev = f;
        }
       else
@@ -527,44 +707,114 @@ prev_frame (frame, minibuf)
        acceptable frame in the list, return it.  */
     return prev;
 }
-#endif
+
 
 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
   "Return the next frame in the frame list after FRAME.\n\
-By default, skip minibuffer-only frames.
+By default, skip minibuffer-only frames.\n\
 If omitted, FRAME defaults to the selected frame.\n\
-If optional argument MINIFRAME is non-nil, include minibuffer-only frames.\n\
-If MINIFRAME is a window, include only frames using that window for their\n\
-minibuffer.\n\
-If MINIFRAME is non-nil and not a window, include all frames.")
+If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
+If MINIBUF is a window, include only its own frame\n\
+and any frame now using that window as the minibuffer.\n\
+If MINIFRAME is `visible', include all visible frames.\n\
+If MINIBUF is 0, include all visible and iconified frames.\n\
+Otherwise, include all frames.")
   (frame, miniframe)
      Lisp_Object frame, miniframe;
 {
   Lisp_Object tail;
 
   if (NILP (frame))
-    XSET (frame, Lisp_Frame, selected_frame);
+    XSETFRAME (frame, selected_frame);
   else
     CHECK_LIVE_FRAME (frame, 0);
 
   return next_frame (frame, miniframe);
 }
-#endif /* MULTI_FRAME */
+
+DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
+  "Return the previous frame in the frame list before FRAME.\n\
+By default, skip minibuffer-only frames.\n\
+If omitted, FRAME defaults to the selected frame.\n\
+If optional argument MINIFRAME is nil, exclude minibuffer-only frames.\n\
+If MINIBUF is a window, include only its own frame\n\
+and any frame now using that window as the minibuffer.\n\
+If MINIFRAME is `visible', include all visible frames.\n\
+If MINIBUF is 0, include all visible and iconified frames.\n\
+Otherwise, include all frames.")
+  (frame, miniframe)
+     Lisp_Object frame, miniframe;
+{
+  Lisp_Object tail;
+
+  if (NILP (frame))
+    XSETFRAME (frame, selected_frame);
+  else
+    CHECK_LIVE_FRAME (frame, 0);
+
+  return prev_frame (frame, miniframe);
+}
 \f
-DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 1, "",
+/* Return 1 if it is ok to delete frame F;
+   0 if all frames aside from F are invisible.
+   (Exception: if F is the terminal frame, and we are using X, return 1.)  */
+
+int
+other_visible_frames (f)
+     FRAME_PTR f;
+{
+  /* We know the selected frame is visible,
+     so if F is some other frame, it can't be the sole visible one.  */
+  if (f == selected_frame)
+    {
+      Lisp_Object frames;
+      int count = 0;
+
+      for (frames = Vframe_list;
+          CONSP (frames);
+          frames = XCONS (frames)->cdr)
+       {
+         Lisp_Object this;
+
+         this = XCONS (frames)->car;
+         /* Verify that the frame's window still exists
+            and we can still talk to it.  And note any recent change
+            in visibility.  */
+#ifdef HAVE_X_WINDOWS
+         if (FRAME_X_P (XFRAME (this)))
+           {
+             x_sync (this);
+             FRAME_SAMPLE_VISIBILITY (XFRAME (this));
+           }
+#endif
+
+         if (FRAME_VISIBLE_P (XFRAME (this))
+             || FRAME_ICONIFIED_P (XFRAME (this))
+             /* Allow deleting the terminal frame when at least
+                one X frame exists!  */
+             || (FRAME_X_P (XFRAME (this)) && !FRAME_X_P (f)))
+           count++;
+       }
+      return count > 1;
+    }
+  return 1;
+}
+
+DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
   "Delete FRAME, permanently eliminating it from use.\n\
 If omitted, FRAME defaults to the selected frame.\n\
-A frame may not be deleted if its minibuffer is used by other frames.")
-  (frame)
-     Lisp_Object frame;
+A frame may not be deleted if its minibuffer is used by other frames.\n\
+Normally, you may not delete a frame if all other frames are invisible,\n\
+but if the second optional argument FORCE is non-nil, you may do so.")
+  (frame, force)
+     Lisp_Object frame, force;
 {
   struct frame *f;
-  union display displ;
 
   if (EQ (frame, Qnil))
     {
       f = selected_frame;
-      XSET (frame, Lisp_Frame, f);
+      XSETFRAME (frame, f);
     }
   else
     {
@@ -573,11 +823,10 @@ A frame may not be deleted if its minibuffer is used by other frames.")
     }
 
   if (! FRAME_LIVE_P (f))
-    return;
+    return Qnil;
 
-  /* Are there any other frames besides this one?  */
-  if (f == selected_frame && EQ (next_frame (frame, Qt), frame))
-    error ("Attempt to delete the only frame");
+  if (NILP (force) && !other_visible_frames (f))
+    error ("Attempt to delete the sole visible or iconified frame");
 
   /* Does this frame have a minibuffer, and is it the surrogate
      minibuffer for any other frame?  */
@@ -589,21 +838,20 @@ A frame may not be deleted if its minibuffer is used by other frames.")
           CONSP (frames);
           frames = XCONS (frames)->cdr)
        {
-         Lisp_Object this = XCONS (frames)->car;
+         Lisp_Object this;
+         this = XCONS (frames)->car;
 
          if (! EQ (this, frame)
              && EQ (frame,
-                    (WINDOW_FRAME
-                     (XWINDOW
-                      (FRAME_MINIBUF_WINDOW
-                       (XFRAME (this)))))))
+                    WINDOW_FRAME (XWINDOW
+                                  (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
            error ("Attempt to delete a surrogate minibuffer frame");
        }
     }
 
   /* Don't let the frame remain selected.  */
   if (f == selected_frame)
-    Fselect_frame (next_frame (frame, Qt), Qnil);
+    Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
 
   /* Don't allow minibuf_window to remain on a deleted frame.  */
   if (EQ (f->minibuffer_window, minibuf_window))
@@ -613,16 +861,49 @@ A frame may not be deleted if its minibuffer is used by other frames.")
       minibuf_window = selected_frame->minibuffer_window;
     }
 
-  Vframe_list = Fdelq (frame, Vframe_list);
-  f->visible = 0;
-  displ = f->display;
-  f->display.nothing = 0;
+  /* Clear any X selections for this frame.  */
+#ifdef HAVE_X_WINDOWS
+  if (FRAME_X_P (f))
+    x_clear_frame_selections (f);
+#endif
+
+  /* Mark all the windows that used to be on FRAME as deleted, and then
+     remove the reference to them.  */
+  delete_all_subwindows (XWINDOW (f->root_window));
+  f->root_window = Qnil;
 
+  Vframe_list = Fdelq (frame, Vframe_list);
+  FRAME_SET_VISIBLE (f, 0);
+
+  if (FRAME_CURRENT_GLYPHS (f))
+    free_frame_glyphs (f, FRAME_CURRENT_GLYPHS (f));
+  if (FRAME_DESIRED_GLYPHS (f))
+    free_frame_glyphs (f, FRAME_DESIRED_GLYPHS (f));
+  if (FRAME_TEMP_GLYPHS (f))
+    free_frame_glyphs (f, FRAME_TEMP_GLYPHS (f));
+  if (FRAME_INSERT_COST (f))
+    free (FRAME_INSERT_COST (f));
+  if (FRAME_DELETEN_COST (f))
+    free (FRAME_DELETEN_COST (f));
+  if (FRAME_INSERTN_COST (f))
+    free (FRAME_INSERTN_COST (f));
+  if (FRAME_DELETE_COST (f))
+    free (FRAME_DELETE_COST (f));
+
+  /* Since some events are handled at the interrupt level, we may get
+     an event for f at any time; if we zero out the frame's display
+     now, then we may trip up the event-handling code.  Instead, we'll
+     promise that the display of the frame must be valid until we have
+     called the window-system-dependent frame destruction routine.  */
+
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (f))
-    x_destroy_window (f, displ);
+    x_destroy_window (f);
 #endif
 
+  f->display.nothing = 0;
+
   /* If we've deleted the last_nonminibuf_frame, then try to find
      another one.  */
   if (f == last_nonminibuf_frame)
@@ -652,15 +933,17 @@ A frame may not be deleted if its minibuffer is used by other frames.")
       Lisp_Object frames;
 
       /* The last frame we saw with a minibuffer, minibuffer-only or not.  */
-      Lisp_Object frame_with_minibuf = Qnil;
+      Lisp_Object frame_with_minibuf;
 
+      frame_with_minibuf = Qnil;
       for (frames = Vframe_list;
           CONSP (frames);
           frames = XCONS (frames)->cdr)
        {
-         Lisp_Object this = XCONS (frames)->car;
+         Lisp_Object this;
 
-         if (XTYPE (this) != Lisp_Frame)
+         this = XCONS (frames)->car;
+         if (!FRAMEP (this))
            abort ();
          f = XFRAME (this);
 
@@ -691,29 +974,75 @@ A frame may not be deleted if its minibuffer is used by other frames.")
 
 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
   "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
+The position is given in character cells, where (0, 0) is the\n\
+upper-left corner.\n\
 If Emacs is running on a mouseless terminal or hasn't been programmed\n\
 to read the mouse position, it returns the selected frame for FRAME\n\
 and nil for X and Y.")
   ()
 {
-  Lisp_Object x, y, dummy;
   FRAME_PTR f;
+  Lisp_Object lispy_dummy;
+  enum scroll_bar_part party_dummy;
+  Lisp_Object x, y;
+  int col, row;
+  unsigned long long_dummy;
+
+  f = selected_frame;
+  x = y = Qnil;
 
+  /* It's okay for the hook to refrain from storing anything.  */
   if (mouse_position_hook)
-    (*mouse_position_hook) (&f, &x, &y, &dummy);
-  else
+    (*mouse_position_hook) (&f,
+                           &lispy_dummy, &party_dummy,
+                           &x, &y,
+                           &long_dummy);
+  if (! NILP (x))
     {
-      f = selected_frame;
-      x = y = Qnil;
+      col = XINT (x);
+      row = XINT (y);
+      pixel_to_glyph_coords (f, col, row, &col, &row, 0, 1);
+      XSETINT (x, col);
+      XSETINT (y, row);
     }
+  XSETFRAME (lispy_dummy, f);
+  return Fcons (lispy_dummy, Fcons (x, y));
+}
 
-  XSET (dummy, Lisp_Frame, f);
-  return Fcons (dummy, Fcons (make_number (x), make_number (y)));
+DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
+       Smouse_pixel_position, 0, 0, 0,
+  "Return a list (FRAME X . Y) giving the current mouse frame and position.\n\
+The position is given in pixel units, where (0, 0) is the\n\
+upper-left corner.\n\
+If Emacs is running on a mouseless terminal or hasn't been programmed\n\
+to read the mouse position, it returns the selected frame for FRAME\n\
+and nil for X and Y.")
+  ()
+{
+  FRAME_PTR f;
+  Lisp_Object lispy_dummy;
+  enum scroll_bar_part party_dummy;
+  Lisp_Object x, y;
+  int col, row;
+  unsigned long long_dummy;
+
+  f = selected_frame;
+  x = y = Qnil;
+
+  /* It's okay for the hook to refrain from storing anything.  */
+  if (mouse_position_hook)
+    (*mouse_position_hook) (&f,
+                           &lispy_dummy, &party_dummy,
+                           &x, &y,
+                           &long_dummy);
+  XSETFRAME (lispy_dummy, f);
+  return Fcons (lispy_dummy, Fcons (x, y));
 }
 
 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
-  "Move the mouse pointer to the center of cell (X,Y) in FRAME.\n\
-WARNING:  If you use this under X, you should do `unfocus-frame' afterwards.")
+  "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
+WARNING:  If you use this under X windows,\n\
+you should call `unfocus-frame' afterwards.")
   (frame, x, y)
      Lisp_Object frame, x, y;
 {
@@ -721,6 +1050,7 @@ WARNING:  If you use this under X, you should do `unfocus-frame' afterwards.")
   CHECK_NUMBER (x, 2);
   CHECK_NUMBER (y, 1);
 
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (XFRAME (frame)))
     /* Warping the mouse will cause  enternotify and focus events. */
@@ -729,101 +1059,96 @@ WARNING:  If you use this under X, you should do `unfocus-frame' afterwards.")
 
   return Qnil;
 }
-\f
-#if 0
-/* ??? Can this be replaced with a Lisp function?
-   It is used in minibuf.c.  Can we get rid of that?
-   Yes.  All uses in minibuf.c are gone, and parallels to these
-   functions have been defined in frame.el.  */
 
-DEFUN ("frame-configuration", Fframe_configuration, Sframe_configuration,
-       0, 0, 0,
-  "Return object describing current frame configuration.\n\
-The frame configuration is the current mouse position and selected frame.\n\
-This object can be given to `restore-frame-configuration'\n\
-to restore this frame configuration.")
-  ()
-{
-  Lisp_Object c, time;
-  
-  c = Fmake_vector (make_number(4), Qnil);
-  XVECTOR (c)->contents[0] = Fselected_frame();
-  if (mouse_position_hook)
-    (*mouse_position_hook) (&XVECTOR (c)->contents[1]
-                           &XVECTOR (c)->contents[2],
-                           &XVECTOR (c)->contents[3],
-                           &time);
-  return c;
-}
-
-DEFUN ("restore-frame-configuration", Frestore_frame_configuration,
-       Srestore_frame_configuration,
-       1, 1, 0,
-  "Restores frame configuration CONFIGURATION.")
-  (config)
-  Lisp_Object config;
+DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
+       Sset_mouse_pixel_position, 3, 3, 0,
+  "Move the mouse pointer to pixel position (X,Y) in FRAME.\n\
+WARNING:  If you use this under X windows,\n\
+you should call `unfocus-frame' afterwards.")
+  (frame, x, y)
+     Lisp_Object frame, x, y;
 {
-  Lisp_Object x_pos, y_pos, frame;
-
-  CHECK_VECTOR (config, 0);
-  if (XVECTOR (config)->size != 3)
-    {
-      error ("Wrong size vector passed to restore-frame-configuration");
-    }
-  frame = XVECTOR (config)->contents[0];
   CHECK_LIVE_FRAME (frame, 0);
+  CHECK_NUMBER (x, 2);
+  CHECK_NUMBER (y, 1);
 
-  Fselect_frame (frame, Qnil);
-
-#if 0
-  /* This seems to interfere with the frame selection mechanism. jla */
-  x_pos = XVECTOR (config)->contents[2];
-  y_pos = XVECTOR (config)->contents[3];
-  set_mouse_position (frame, XINT (x_pos), XINT (y_pos));
+  /* I think this should be done with a hook.  */
+#ifdef HAVE_X_WINDOWS
+  if (FRAME_X_P (XFRAME (frame)))
+    /* Warping the mouse will cause  enternotify and focus events. */
+    x_set_mouse_pixel_position (XFRAME (frame), x, y);
 #endif
 
-  return frame;
-}    
-#endif
+  return Qnil;
+}
 \f
 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
-       0, 1, 0,
+       0, 1, "",
   "Make the frame FRAME visible (assuming it is an X-window).\n\
-Also raises the frame so that nothing obscures it.\n\
 If omitted, FRAME defaults to the currently selected frame.")
   (frame)
      Lisp_Object frame;
 {
   if (NILP (frame))
-    XSET (frame, Lisp_Frame, selected_frame);
+    XSETFRAME (frame, selected_frame);
 
   CHECK_LIVE_FRAME (frame, 0);
 
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (XFRAME (frame)))
-    x_make_frame_visible (XFRAME (frame));
+    {
+      FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
+      x_make_frame_visible (XFRAME (frame));
+    }
 #endif
 
+  /* Make menu bar update for the Buffers and Frams menus.  */
+  windows_or_buffers_changed++;
+
   return frame;
 }
 
 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
-       0, 1, "",
+       0, 2, "",
   "Make the frame FRAME invisible (assuming it is an X-window).\n\
-If omitted, FRAME defaults to the currently selected frame.")
-  (frame)
-     Lisp_Object frame;
+If omitted, FRAME defaults to the currently selected frame.\n\
+Normally you may not make FRAME invisible if all other frames are invisible,\n\
+but if the second optional argument FORCE is non-nil, you may do so.")
+  (frame, force)
+     Lisp_Object frame, force;
 {
   if (NILP (frame))
-    XSET (frame, Lisp_Frame, selected_frame);
+    XSETFRAME (frame, selected_frame);
 
   CHECK_LIVE_FRAME (frame, 0);
 
+  if (NILP (force) && !other_visible_frames (XFRAME (frame)))
+    error ("Attempt to make invisible the sole visible or iconified frame");
+
+#if 0 /* This isn't logically necessary, and it can do GC.  */
+  /* Don't let the frame remain selected.  */
+  if (XFRAME (frame) == selected_frame)
+    Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
+#endif
+
+  /* Don't allow minibuf_window to remain on a deleted frame.  */
+  if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
+    {
+      Fset_window_buffer (selected_frame->minibuffer_window,
+                         XWINDOW (minibuf_window)->buffer);
+      minibuf_window = selected_frame->minibuffer_window;
+    }
+
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (XFRAME (frame)))
     x_make_frame_invisible (XFRAME (frame));
 #endif
 
+  /* Make menu bar update for the Buffers and Frams menus.  */
+  windows_or_buffers_changed++;
+
   return Qnil;
 }
 
@@ -835,15 +1160,33 @@ If omitted, FRAME defaults to the currently selected frame.")
      Lisp_Object frame;
 {
   if (NILP (frame))
-    XSET (frame, Lisp_Frame, selected_frame);
+    XSETFRAME (frame, selected_frame);
   
   CHECK_LIVE_FRAME (frame, 0);
 
+#if 0 /* This isn't logically necessary, and it can do GC.  */
+  /* Don't let the frame remain selected.  */
+  if (XFRAME (frame) == selected_frame)
+    Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
+#endif
+
+  /* Don't allow minibuf_window to remain on a deleted frame.  */
+  if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
+    {
+      Fset_window_buffer (selected_frame->minibuffer_window,
+                         XWINDOW (minibuf_window)->buffer);
+      minibuf_window = selected_frame->minibuffer_window;
+    }
+
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (XFRAME (frame)))
       x_iconify_frame (XFRAME (frame));
 #endif
 
+  /* Make menu bar update for the Buffers and Frams menus.  */
+  windows_or_buffers_changed++;
+
   return Qnil;
 }
 
@@ -858,9 +1201,11 @@ Return the symbol `icon' if frame is visible only as an icon.")
 {
   CHECK_LIVE_FRAME (frame, 0);
 
-  if (XFRAME (frame)->visible)
+  FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
+
+  if (FRAME_VISIBLE_P (XFRAME (frame)))
     return Qt;
-  if (XFRAME (frame)->iconified)
+  if (FRAME_ICONIFIED_P (XFRAME (frame)))
     return Qicon;
   return Qnil;
 }
@@ -878,43 +1223,97 @@ DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
   for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
     {
       frame = XCONS (tail)->car;
-      if (XTYPE (frame) != Lisp_Frame)
+      if (!FRAMEP (frame))
        continue;
       f = XFRAME (frame);
-      if (f->visible)
+      if (FRAME_VISIBLE_P (f))
        value = Fcons (frame, value);
     }
   return value;
 }
 
 
+DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 1, 1, 0,
+  "Bring FRAME to the front, so it occludes any frames it overlaps.\n\
+If FRAME is invisible, make it visible.\n\
+If Emacs is displaying on an ordinary terminal or some other device which\n\
+doesn't support multiple overlapping frames, this function does nothing.")
+  (frame)
+     Lisp_Object frame;
+{
+  CHECK_LIVE_FRAME (frame, 0);
+
+  /* Do like the documentation says. */
+  Fmake_frame_visible (frame);
+
+  if (frame_raise_lower_hook)
+    (*frame_raise_lower_hook) (XFRAME (frame), 1);
+
+  return Qnil;
+}
+
+/* Should we have a corresponding function called Flower_Power?  */
+DEFUN ("lower-frame", Flower_frame, Slower_frame, 1, 1, 0,
+  "Send FRAME to the back, so it is occluded by any frames that overlap it.\n\
+If Emacs is displaying on an ordinary terminal or some other device which\n\
+doesn't support multiple overlapping frames, this function does nothing.")
+  (frame)
+     Lisp_Object frame;
+{
+  CHECK_LIVE_FRAME (frame, 0);
+  
+  if (frame_raise_lower_hook)
+    (*frame_raise_lower_hook) (XFRAME (frame), 0);
+
+  return Qnil;
+}
+
 \f
 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
        1, 2, 0,
   "Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.\n\
-This means that, after reading a keystroke typed at FRAME,\n\
-`last-event-frame' will be FOCUS-FRAME.\n\
+In other words, switch-frame events caused by events in FRAME will\n\
+request a switch to FOCUS-FRAME, and `last-event-frame' will be\n\
+FOCUS-FRAME after reading an event typed at FRAME.\n\
 \n\
-If FOCUS-FRAME is omitted or eq to FRAME, any existing redirection is\n\
+If FOCUS-FRAME is omitted or nil, any existing redirection is\n\
 cancelled, and the frame again receives its own keystrokes.\n\
 \n\
-The redirection lasts until the next call to `redirect-frame-focus'\n\
-or `select-frame'.\n\
+Focus redirection is useful for temporarily redirecting keystrokes to\n\
+a surrogate minibuffer frame when a frame doesn't have its own\n\
+minibuffer window.\n\
+\n\
+A frame's focus redirection can be changed by select-frame.  If frame\n\
+FOO is selected, and then a different frame BAR is selected, any\n\
+frames redirecting their focus to FOO are shifted to redirect their\n\
+focus to BAR.  This allows focus redirection to work properly when the\n\
+user switches from one frame to another using `select-window'.\n\
 \n\
-This is useful for temporarily redirecting keystrokes to the minibuffer\n\
-window when a frame doesn't have its own minibuffer.")
+This means that a frame whose focus is redirected to itself is treated\n\
+differently from a frame whose focus is redirected to nil; the former\n\
+is affected by select-frame, while the latter is not.\n\
+\n\
+The redirection lasts until `redirect-frame-focus' is called to change it.")
   (frame, focus_frame)
     Lisp_Object frame, focus_frame;
 {
-  CHECK_LIVE_FRAME (frame, 0);
+  /* Note that we don't check for a live frame here.  It's reasonable
+     to redirect the focus of a frame you're about to delete, if you
+     know what other frame should receive those keystrokes.  */
+  CHECK_FRAME (frame, 0);
 
-  if (NILP (focus_frame))
-    focus_frame = frame;
-  else
+  if (! NILP (focus_frame))
     CHECK_LIVE_FRAME (focus_frame, 1);
 
   XFRAME (frame)->focus_frame = focus_frame;
 
+  /* I think this should be done with a hook.  */
+#ifdef HAVE_X_WINDOWS
+  if (!NILP (focus_frame) && ! EQ (focus_frame, frame)
+      && FRAME_X_P (XFRAME (focus_frame)))
+    Ffocus_frame (focus_frame);
+#endif
+
   if (frame_rehighlight_hook)
     (*frame_rehighlight_hook) ();
   
@@ -924,11 +1323,13 @@ window when a frame doesn't have its own minibuffer.")
 
 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
   "Return the frame to which FRAME's keystrokes are currently being sent.\n\
+This returns nil if FRAME's focus is not redirected.\n\
 See `redirect-frame-focus'.")
   (frame)
     Lisp_Object frame;
 {
   CHECK_LIVE_FRAME (frame, 0);
+
   return FRAME_FOCUS_FRAME (XFRAME (frame));
 }
 
@@ -974,14 +1375,13 @@ store_frame_param (f, prop, val)
   else
     Fsetcdr (tem, val);
 
-  if (EQ (prop, Qminibuffer)
-      && XTYPE (val) == Lisp_Window)
+  if (EQ (prop, Qminibuffer) && WINDOWP (val))
     {
       if (! MINI_WINDOW_P (XWINDOW (val)))
        error ("Surrogate minibuffer windows must be minibuffer windows.");
 
       if (FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
-       error ("Can't change the surrogate minibuffer of a frame with its own minibuffer.");
+       error ("can't change the surrogate minibuffer of a frame with its own minibuffer");
 
       /* Install the chosen minibuffer window, with proper buffer.  */
       f->minibuffer_window = val;
@@ -997,7 +1397,7 @@ If FRAME is omitted, return information on the currently selected frame.")
      Lisp_Object frame;
 {
   Lisp_Object alist;
-  struct frame *f;
+  FRAME_PTR f;
 
   if (EQ (frame, Qnil))
     f = selected_frame;
@@ -1007,24 +1407,32 @@ If FRAME is omitted, return information on the currently selected frame.")
       f = XFRAME (frame);
     }
 
-  if (f->display.nothing == 0)
+  if (!FRAME_LIVE_P (f))
     return Qnil;
 
   alist = Fcopy_alist (f->param_alist);
   store_in_alist (&alist, Qname, f->name);
-  store_in_alist (&alist, Qheight, make_number (f->height));
-  store_in_alist (&alist, Qwidth, make_number (f->width));
-  store_in_alist (&alist, Qmodeline, (f->wants_modeline ? Qt : Qnil));
+  store_in_alist (&alist, Qheight, make_number (FRAME_HEIGHT (f)));
+  store_in_alist (&alist, Qwidth, make_number (FRAME_WIDTH (f)));
+  store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
   store_in_alist (&alist, Qminibuffer,
-                 (! FRAME_HAS_MINIBUF_P (f) ? Qnone
-                  : (FRAME_MINIBUF_ONLY_P (f) ? Qonly
-                   : FRAME_MINIBUF_WINDOW (f))));
-  store_in_alist (&alist, Qunsplittable, (f->no_split ? Qt : Qnil));
+                 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
+                  : FRAME_MINIBUF_ONLY_P (f) ? Qonly
+                  : FRAME_MINIBUF_WINDOW (f)));
+  store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
 
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (f))
     x_report_frame_params (f, &alist);
+  else
 #endif
+    {
+      /* This ought to be correct in f->param_alist for an X frame.  */
+      Lisp_Object lines;
+      XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
+      store_in_alist (&alist, Qmenu_bar_lines, lines);
+    }
   return alist;
 }
 
@@ -1048,6 +1456,7 @@ The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
       f = XFRAME (frame);
     }
 
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (f))
 #if 1
@@ -1067,47 +1476,113 @@ The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
   return Qnil;
 }
 \f
-
-#if 0
-/* This function isn't useful enough by itself to include; we need to
-   add functions to allow the user to find the size of a font before
-   this is actually useful.  */
-
-DEFUN ("frame-pixel-size", Fframe_pixel_size, 
-       Sframe_pixel_size, 1, 1, 0,
-  "Return a cons (width . height) of FRAME's size in pixels.")
+DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
+  0, 1, 0,
+  "Height in pixels of a line in the font in frame FRAME.\n\
+If FRAME is omitted, the selected frame is used.\n\
+For a terminal frame, the value is always 1.")
   (frame)
      Lisp_Object frame;
 {
-  register struct frame *f;
-  int width, height;
+  struct frame *f;
 
-  CHECK_LIVE_FRAME (frame, 0);
-  f = XFRAME (frame);
-  
-  return Fcons (make_number (x_pixel_width (f)),
-               make_number (x_pixel_height (f)));
-}
+  if (NILP (frame))
+    f = selected_frame;
+  else
+    {
+      CHECK_FRAME (frame, 0);
+      f = XFRAME (frame);
+    }
+
+#ifdef HAVE_X_WINDOWS
+  if (FRAME_X_P (f))
+    return make_number (x_char_height (f));
+  else
 #endif
+    return make_number (1);
+}
 
-#if 0
-/* These functions have no C callers, and can be written nicely in lisp.  */
 
-DEFUN ("frame-height", Fframe_height, Sframe_height, 0, 0, 0,
-  "Return number of lines available for display on selected frame.")
-  ()
+DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
+  0, 1, 0,
+  "Width in pixels of characters in the font in frame FRAME.\n\
+If FRAME is omitted, the selected frame is used.\n\
+The width is the same for all characters, because\n\
+currently Emacs supports only fixed-width fonts.\n\
+For a terminal screen, the value is always 1.")
+  (frame)
+     Lisp_Object frame;
 {
-  return make_number (FRAME_HEIGHT (selected_frame));
+  struct frame *f;
+
+  if (NILP (frame))
+    f = selected_frame;
+  else
+    {
+      CHECK_FRAME (frame, 0);
+      f = XFRAME (frame);
+    }
+
+#ifdef HAVE_X_WINDOWS
+  if (FRAME_X_P (f))
+    return make_number (x_char_width (f));
+  else
+#endif
+    return make_number (1);
 }
 
-DEFUN ("frame-width", Fframe_width, Sframe_width, 0, 0, 0,
-  "Return number of columns available for display on selected frame.")
-  ()
+DEFUN ("frame-pixel-height", Fframe_pixel_height, 
+       Sframe_pixel_height, 0, 1, 0,
+  "Return a FRAME's height in pixels.\n\
+For a terminal frame, the result really gives the height in characters.\n\
+If FRAME is omitted, the selected frame is used.")
+  (frame)
+     Lisp_Object frame;
 {
-  return make_number (FRAME_WIDTH (selected_frame));
-}
+  struct frame *f;
+
+  if (NILP (frame))
+    f = selected_frame;
+  else
+    {
+      CHECK_FRAME (frame, 0);
+      f = XFRAME (frame);
+    }
+
+#ifdef HAVE_X_WINDOWS
+  if (FRAME_X_P (f))
+    return make_number (x_pixel_height (f));
+  else
 #endif
+    return make_number (FRAME_HEIGHT (f));
+}
+
+DEFUN ("frame-pixel-width", Fframe_pixel_width, 
+       Sframe_pixel_width, 0, 1, 0,
+  "Return FRAME's width in pixels.\n\
+For a terminal frame, the result really gives the width in characters.\n\
+If FRAME is omitted, the selected frame is used.")
+  (frame)
+     Lisp_Object frame;
+{
+  struct frame *f;
 
+  if (NILP (frame))
+    f = selected_frame;
+  else
+    {
+      CHECK_FRAME (frame, 0);
+      f = XFRAME (frame);
+    }
+
+#ifdef HAVE_X_WINDOWS
+  if (FRAME_X_P (f))
+    return make_number (x_pixel_width (f));
+  else
+#endif
+    return make_number (FRAME_WIDTH (f));
+}
+\f
 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
   "Specify that the frame FRAME has LINES lines.\n\
 Optional third arg non-nil means that redisplay should use LINES lines\n\
@@ -1126,11 +1601,12 @@ but that the idea of the actual height of the frame should not be changed.")
       f = XFRAME (frame);
     }
 
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (f))
     {
       if (XINT (rows) != f->width)
-       x_set_window_size (f, f->width, XINT (rows));
+       x_set_window_size (f, 1, f->width, XINT (rows));
     }
   else
 #endif
@@ -1155,11 +1631,12 @@ but that the idea of the actual width of the frame should not be changed.")
       f = XFRAME (frame);
     }
 
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (f))
     {
       if (XINT (cols) != f->width)
-       x_set_window_size (f, XINT (cols), f->height);
+       x_set_window_size (f, 1, XINT (cols), f->height);
     }
   else
 #endif
@@ -1180,11 +1657,12 @@ DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
   CHECK_NUMBER (rows, 1);
   f = XFRAME (frame);
 
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (f))
     {
       if (XINT (rows) != f->height || XINT (cols) != f->width)
-       x_set_window_size (f, XINT (cols), XINT (rows));
+       x_set_window_size (f, 1, XINT (cols), XINT (rows));
     }
   else
 #endif
@@ -1196,9 +1674,9 @@ DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
 DEFUN ("set-frame-position", Fset_frame_position, 
        Sset_frame_position, 3, 3, 0,
   "Sets position of FRAME in pixels to XOFFSET by YOFFSET.\n\
-If XOFFSET or YOFFSET are negative, they are interpreted relative to\n\
-the leftmost or bottommost position FRAME could occupy without going\n\
-off the screen.")
+This is actually the position of the upper left corner of the frame.\n\
+Negative values for XOFFSET or YOFFSET are interpreted relative to\n\
+the rightmost or bottommost possible position (that stays within the screen).")
   (frame, xoffset, yoffset)
      Lisp_Object frame, xoffset, yoffset;
 {
@@ -1210,54 +1688,15 @@ off the screen.")
   CHECK_NUMBER (yoffset, 2);
   f = XFRAME (frame);
 
+  /* I think this should be done with a hook.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (f))
-    x_set_offset (f, XINT (xoffset), XINT (yoffset));
+    x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
 #endif
 
   return Qt;
 }
 
-\f
-#ifndef HAVE_X11
-DEFUN ("rubber-band-rectangle", Frubber_band_rectangle, Srubber_band_rectangle,
-       3, 3, "",
-  "Ask user to specify a window position and size on FRAME with the mouse.\n\
-Arguments are FRAME, NAME and GEO.  NAME is a name to be displayed as\n\
-the purpose of this rectangle.  GEO is an X-windows size spec that can\n\
-specify defaults for some sizes/positions.  If GEO specifies everything,\n\
-the mouse is not used.\n\
-Returns a list of five values: (FRAME LEFT TOP WIDTH HEIGHT).")
-  (frame, name, geo)
-     Lisp_Object frame;
-     Lisp_Object name;
-     Lisp_Object geo;
-{
-  int vals[4];
-  Lisp_Object nums[4];
-  int i;
-
-  CHECK_FRAME (frame, 0);
-  CHECK_STRING (name, 1);
-  CHECK_STRING (geo, 2);
-
-  switch (XFRAME (frame)->output_method)
-    {
-    case output_x_window:
-      x_rubber_band (XFRAME (frame), &vals[0], &vals[1], &vals[2], &vals[3],
-                    XSTRING (geo)->data, XSTRING (name)->data);
-      break;
-
-    default:
-      return Qnil;
-    }
-
-  for (i = 0; i < 4; i++)
-    XFASTINT (nums[i]) = vals[i];
-  return Fcons (frame, Flist (4, nums));
-  return Qnil;
-}
-#endif /* not HAVE_X11 */
 \f
 choose_minibuf_frame ()
 {
@@ -1284,8 +1723,8 @@ syms_of_frame ()
   /*&&& init symbols here &&&*/
   Qframep = intern ("framep");
   staticpro (&Qframep);
-  Qlive_frame_p = intern ("live-frame-p");
-  staticpro (&Qlive_frame_p);
+  Qframe_live_p = intern ("frame-live-p");
+  staticpro (&Qframe_live_p);
   Qheight = intern ("height");
   staticpro (&Qheight);
   Qicon = intern ("icon");
@@ -1296,16 +1735,18 @@ syms_of_frame ()
   staticpro (&Qmodeline);
   Qname = intern ("name");
   staticpro (&Qname);
-  Qnone = intern ("none");
-  staticpro (&Qnone);
   Qonly = intern ("only");
   staticpro (&Qonly);
   Qunsplittable = intern ("unsplittable");
   staticpro (&Qunsplittable);
+  Qmenu_bar_lines = intern ("menu-bar-lines");
+  staticpro (&Qmenu_bar_lines);
   Qwidth = intern ("width");
   staticpro (&Qwidth);
   Qx = intern ("x");
   staticpro (&Qx);
+  Qvisible = intern ("visible");
+  staticpro (&Qvisible);
 
   staticpro (&Vframe_list);
 
@@ -1342,17 +1783,23 @@ For values specific to the separate minibuffer frame, see\n\
   Vdefault_frame_alist = Qnil;
 
   defsubr (&Sframep);
-  defsubr (&Slive_frame_p);
+  defsubr (&Sframe_live_p);
+  defsubr (&Shandle_switch_frame);
   defsubr (&Sselect_frame);
   defsubr (&Sselected_frame);
   defsubr (&Swindow_frame);
   defsubr (&Sframe_root_window);
+  defsubr (&Sframe_first_window);
   defsubr (&Sframe_selected_window);
+  defsubr (&Sset_frame_selected_window);
   defsubr (&Sframe_list);
   defsubr (&Snext_frame);
+  defsubr (&Sprevious_frame);
   defsubr (&Sdelete_frame);
   defsubr (&Smouse_position);
+  defsubr (&Smouse_pixel_position);
   defsubr (&Sset_mouse_position);
+  defsubr (&Sset_mouse_pixel_position);
 #if 0
   defsubr (&Sframe_configuration);
   defsubr (&Srestore_frame_configuration);
@@ -1362,50 +1809,92 @@ For values specific to the separate minibuffer frame, see\n\
   defsubr (&Siconify_frame);
   defsubr (&Sframe_visible_p);
   defsubr (&Svisible_frame_list);
+  defsubr (&Sraise_frame);
+  defsubr (&Slower_frame);
   defsubr (&Sredirect_frame_focus);
   defsubr (&Sframe_focus);
   defsubr (&Sframe_parameters);
   defsubr (&Smodify_frame_parameters);
-#if 0
-  defsubr (&Sframe_pixel_size);
-  defsubr (&Sframe_height);
-  defsubr (&Sframe_width);
-#endif
+  defsubr (&Sframe_char_height);
+  defsubr (&Sframe_char_width);
+  defsubr (&Sframe_pixel_height);
+  defsubr (&Sframe_pixel_width);
   defsubr (&Sset_frame_height);
   defsubr (&Sset_frame_width);
   defsubr (&Sset_frame_size);
   defsubr (&Sset_frame_position);
-#ifndef HAVE_X11
-  defsubr (&Srubber_band_rectangle);
-#endif /* HAVE_X11 */
 }
 
 keys_of_frame ()
 {
-  initial_define_lispy_key (global_map, "switch-frame", "select-frame");
+  initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");
+  initial_define_lispy_key (global_map, "delete-frame", "handle-delete-frame");
 }
-
+\f
 #else /* not MULTI_FRAME */
 
 /* If we're not using multi-frame stuff, we still need to provide some
    support functions.  */
 
+Lisp_Object Qheight;
+Lisp_Object Qminibuffer;
+Lisp_Object Qmodeline;
+Lisp_Object Qname;
+Lisp_Object Qunsplittable;
+Lisp_Object Qmenu_bar_lines;
+Lisp_Object Qwidth;
+
+Lisp_Object Vterminal_frame;
+
 /* Unless this function is defined, providing set-frame-height and
    set-frame-width doesn't help compatibility any, since they both
    want this as their first argument.  */
 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
-  "Return the frame that is now selected.")
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
   ()
 {
   Lisp_Object tem;
-  XFASTINT (tem) = 0;
+  XSETFASTINT (tem, 0);
   return tem;
 }
 
+DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
+  0)
+  (frame)
+     Lisp_Object frame;
+{
+  Lisp_Object w;
+
+  w = FRAME_ROOT_WINDOW (selected_frame);
+
+  while (NILP (XWINDOW (w)->buffer))
+    {
+      if (! NILP (XWINDOW (w)->hchild))
+       w = XWINDOW (w)->hchild;
+      else if (! NILP (XWINDOW (w)->vchild))
+       w = XWINDOW (w)->vchild;
+      else
+       abort ();
+    }
+  return w;
+}
+
+DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (object)
+     Lisp_Object object;
+{
+  return Qnil;
+}
+
 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
-  "Specify that the frame FRAME has LINES lines.\n\
-Optional third arg non-nil means that redisplay should use LINES lines\n\
-but that the idea of the actual height of the frame should not be changed.")
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
   (frame, rows, pretend)
      Lisp_Object frame, rows, pretend;
 {
@@ -1416,9 +1905,9 @@ but that the idea of the actual height of the frame should not be changed.")
 }
 
 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
-  "Specify that the frame FRAME has COLS columns.\n\
-Optional third arg non-nil means that redisplay should use COLS columns\n\
-but that the idea of the actual width of the frame should not be changed.")
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
   (frame, cols, pretend)
      Lisp_Object frame, cols, pretend;
 {
@@ -1429,7 +1918,9 @@ but that the idea of the actual width of the frame should not be changed.")
 }
 
 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
-  "Sets size of FRAME to COLS by ROWS, measured in characters.")
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
   (frame, cols, rows)
      Lisp_Object frame, cols, rows;
 {
@@ -1440,21 +1931,70 @@ DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
 
   return Qnil;
 }
-
-DEFUN ("frame-height", Fframe_height, Sframe_height, 0, 0, 0,
-  "Return number of lines available for display on selected frame.")
-  ()
+\f
+DEFUN ("frame-height", Fframe_height, Sframe_height, 0, 1, 0,
+  "Return number of lines available for display on FRAME.\n\
+If FRAME is omitted, describe the currently selected frame.")
+  (frame)
+    Lisp_Object frame;
 {
   return make_number (FRAME_HEIGHT (selected_frame));
 }
 
-DEFUN ("frame-width", Fframe_width, Sframe_width, 0, 0, 0,
-  "Return number of columns available for display on selected frame.")
-  ()
+DEFUN ("frame-width", Fframe_width, Sframe_width, 0, 1, 0,
+  "Return number of columns available for display on FRAME.\n\
+If FRAME is omitted, describe the currently selected frame.")
+  (frame)
+    Lisp_Object frame;
 {
   return make_number (FRAME_WIDTH (selected_frame));
 }
 
+DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
+  0, 1, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (frame)
+     Lisp_Object frame;
+{
+  return make_number (1);
+}
+
+
+DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
+  0, 1, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (frame)
+     Lisp_Object frame;
+{
+  return make_number (1);
+}
+
+DEFUN ("frame-pixel-height", Fframe_pixel_height, 
+       Sframe_pixel_height, 0, 1, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (frame)
+     Lisp_Object frame;
+{
+  return make_number (FRAME_HEIGHT (f));
+}
+
+DEFUN ("frame-pixel-width", Fframe_pixel_width, 
+       Sframe_pixel_width, 0, 1, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (frame)
+     Lisp_Object frame;
+{
+  return make_number (FRAME_WIDTH (f));
+}
+
 /* These are for backward compatibility with Emacs 18.  */
 
 DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
@@ -1483,8 +2023,111 @@ but that the idea of the actual width of the screen should not be changed.")
   return Qnil;
 }
 
+DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  ()
+{
+  return Fcons (Qnil, Fcons (Qnil, Qnil));
+}
+\f
+void
+store_in_alist (alistptr, prop, val)
+     Lisp_Object *alistptr, val;
+     Lisp_Object prop;
+{
+  register Lisp_Object tem;
+
+  tem = Fassq (prop, *alistptr);
+  if (EQ (tem, Qnil))
+    *alistptr = Fcons (Fcons (prop, val), *alistptr);
+  else
+    Fsetcdr (tem, val);
+}
+
+DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (frame)
+     Lisp_Object frame;
+{
+  Lisp_Object alist;
+  FRAME_PTR f;
+
+  if (EQ (frame, Qnil))
+    f = selected_frame;
+  else
+    {
+      CHECK_FRAME (frame, 0);
+      f = XFRAME (frame);
+    }
+
+  if (!FRAME_LIVE_P (f))
+    return Qnil;
+
+  alist = Qnil;
+  store_in_alist (&alist, Qname, build_string ("emacs"));
+  store_in_alist (&alist, Qheight, make_number (FRAME_HEIGHT (f)));
+  store_in_alist (&alist, Qwidth, make_number (FRAME_WIDTH (f)));
+  store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
+  store_in_alist (&alist, Qminibuffer, FRAME_MINIBUF_WINDOW (f));
+  store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
+  store_in_alist (&alist, Qmenu_bar_lines, (FRAME_MENU_BAR_LINES (f)));
+
+  return alist;
+}
+
+DEFUN ("modify-frame-parameters", Fmodify_frame_parameters, 
+       Smodify_frame_parameters, 2, 2, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (frame, alist)
+     Lisp_Object frame, alist;
+{
+  return Qnil;
+}
+
+DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (frame)
+     Lisp_Object frame;
+{
+  return Qt;
+}
+
 syms_of_frame ()
 {
+  Qheight = intern ("height");
+  staticpro (&Qheight);
+  Qminibuffer = intern ("minibuffer");
+  staticpro (&Qminibuffer);
+  Qmodeline = intern ("modeline");
+  staticpro (&Qmodeline);
+  Qname = intern ("name");
+  staticpro (&Qname);
+  Qunsplittable = intern ("unsplittable");
+  staticpro (&Qunsplittable);
+  Qmenu_bar_lines = intern ("menu-bar-lines");
+  staticpro (&Qmenu_bar_lines);
+  Qwidth = intern ("width");
+  staticpro (&Qwidth);
+
+  DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
+    "The initial frame-object, which represents Emacs's stdout.");
+  XSETFASTINT (Vterminal_frame, 0);
+
+  defsubr (&Sselected_frame);
+  defsubr (&Sframe_first_window);
+  defsubr (&Sframep);
+  defsubr (&Sframe_char_height);
+  defsubr (&Sframe_char_width);
+  defsubr (&Sframe_pixel_height);
+  defsubr (&Sframe_pixel_width);
   defsubr (&Sset_frame_height);
   defsubr (&Sset_frame_width);
   defsubr (&Sset_frame_size);
@@ -1494,6 +2137,10 @@ syms_of_frame ()
   Ffset (intern ("screen-height"), intern ("frame-height"));
   defsubr (&Sframe_width);
   Ffset (intern ("screen-width"), intern ("frame-width"));
+  defsubr (&Smouse_position);
+  defsubr (&Sframe_parameters);
+  defsubr (&Smodify_frame_parameters);
+  defsubr (&Sframe_live_p);
 }
 
 keys_of_frame ()
@@ -1501,7 +2148,3 @@ keys_of_frame ()
 }
 
 #endif /* not MULTI_FRAME */
-
-
-
-