XEmacs 21.4.5 "Civil Service".
[chise/xemacs-chise.git.1] / src / frame.c
index a17ea93..c98d0c3 100644 (file)
@@ -102,7 +102,7 @@ Lisp_Object Qvisible, Qiconic, Qinvisible, Qvisible_iconic, Qinvisible_iconic;
 Lisp_Object Qnomini, Qvisible_nomini, Qiconic_nomini, Qinvisible_nomini;
 Lisp_Object Qvisible_iconic_nomini, Qinvisible_iconic_nomini;
 
-Lisp_Object Qset_specifier, Qset_glyph_image, Qset_face_property;
+Lisp_Object Qset_specifier, Qset_face_property;
 Lisp_Object Qface_property_instance;
 
 Lisp_Object Qframe_property_alias;
@@ -121,8 +121,6 @@ static struct display_line title_string_display_line;
    the dynamic allocation time adds up. */
 static Emchar_dynarr *title_string_emchar_dynarr;
 
-EXFUN (Fset_frame_properties, 2);
-
 \f
 static Lisp_Object
 mark_frame (Lisp_Object obj)
@@ -132,8 +130,6 @@ mark_frame (Lisp_Object obj)
 #define MARKED_SLOT(x) mark_object (f->x)
 #include "frameslots.h"
 
-  mark_subwindow_cachels (f->subwindow_cachels);
-
   if (FRAME_LIVE_P (f)) /* device is nil for a dead frame */
     MAYBE_FRAMEMETH (f, mark_frame, (f));
 
@@ -202,20 +198,19 @@ allocate_frame_core (Lisp_Object device)
   XWINDOW (root_window)->pixel_width = 10;
   XWINDOW (root_window)->pixel_height = 9;
 
-  /* The size of the minibuffer window is now set in x_create_frame
-     in xfns.c. */
-
   f->root_window = root_window;
   f->selected_window = root_window;
   f->last_nonminibuf_window = root_window;
 
   /* cache of subwindows visible on frame */
-  f->subwindow_cachels    = Dynarr_new (subwindow_cachel);
+  f->subwindow_instance_cache    = make_weak_list (WEAK_LIST_SIMPLE);
 
   /* associated exposure ignore list */
   f->subwindow_exposures = 0;
   f->subwindow_exposures_tail = 0;
 
+  FRAME_SET_PAGENUMBER (f, 1);
+
   /* Choose a buffer for the frame's root window.  */
   XWINDOW (root_window)->buffer = Qt;
   {
@@ -270,7 +265,9 @@ setup_frame_without_minibuffer (struct frame *f, Lisp_Object mini_window)
              FRAME_CONSOLE (XFRAME (XWINDOW (mini_window)->frame))))
     error ("frame and minibuffer must be on the same console");
 
-  if (NILP (mini_window))
+  /* Do not create a default minibuffer frame on printer devices.  */
+  if (NILP (mini_window)
+      && DEVICE_DISPLAY_P (XDEVICE (FRAME_DEVICE (f))))
     {
       struct console *con = XCONSOLE (FRAME_CONSOLE (f));
       /* Use default-minibuffer-frame if possible.  */
@@ -285,8 +282,13 @@ setup_frame_without_minibuffer (struct frame *f, Lisp_Object mini_window)
     }
 
   /* Install the chosen minibuffer window, with proper buffer.  */
-  store_minibuf_frame_prop (f, mini_window);
-  Fset_window_buffer (mini_window, Vminibuffer_zero, Qt);
+  if (!NILP (mini_window))
+    {
+      store_minibuf_frame_prop (f, mini_window);
+      Fset_window_buffer (mini_window, Vminibuffer_zero, Qt);
+    }
+  else
+    f->minibuffer_window = Qnil;
 }
 
 /* Make a frame containing only a minibuffer window.  */
@@ -380,7 +382,7 @@ See `set-frame-properties', `default-x-frame-plist', and
   else
     name = build_string ("emacs");
 
-  if (!NILP (Fstring_match (make_string ((CONST Bufbyte *) "\\.", 2), name,
+  if (!NILP (Fstring_match (make_string ((const Bufbyte *) "\\.", 2), name,
                            Qnil, Qnil)))
     signal_simple_error (". not allowed in frame names", name);
 
@@ -466,20 +468,14 @@ See `set-frame-properties', `default-x-frame-plist', and
 #endif
       reset_face_cachels (XWINDOW (FRAME_SELECTED_WINDOW (f)));
       reset_glyph_cachels (XWINDOW (FRAME_SELECTED_WINDOW (f)));
-      reset_subwindow_cachels (f);
-      change_frame_size (f, f->height, f->width, 0);
 
+      change_frame_size (f, f->height, f->width, 0);
     }
 
   MAYBE_FRAMEMETH (f, init_frame_2, (f, props));
   Fset_frame_properties (frame, props);
   MAYBE_FRAMEMETH (f, init_frame_3, (f));
 
-  /* now initialise the gutters, this won't change the frame size
-     so is ok here. */
-  if (!DEVICE_STREAM_P (d))
-    init_frame_gutters (f);
-
   /* Hallelujah, praise the lord. */
   f->init_finished = 1;
 
@@ -505,6 +501,18 @@ See `set-frame-properties', `default-x-frame-plist', and
   MAYBE_FRAMEMETH (f, after_init_frame, (f, first_frame_on_device,
                                         first_frame_on_console));
 
+  if (!DEVICE_STREAM_P (d))
+    {
+      /* Now initialise the gutters. This won't change the frame size,
+         but is needed as input to the layout that change_frame_size
+         will eventually do. Unfortunately gutter sizing code relies
+         on the frame in question being visible so we can't do this
+         earlier. */
+      init_frame_gutters (f);
+
+      change_frame_size (f, f->height, f->width, 0);
+    }
+
   if (first_frame_on_device)
     {
       if (first_frame_on_console)
@@ -905,19 +913,19 @@ set_frame_selected_window (struct frame *f, Lisp_Object window)
   f->selected_window = window;
   if (!MINI_WINDOW_P (XWINDOW (window)) || FRAME_MINIBUF_ONLY_P (f))
     {
-#ifdef HAVE_TOOLBARS
       if (!EQ (f->last_nonminibuf_window, window))
        {
+#ifdef HAVE_TOOLBARS
          MARK_TOOLBAR_CHANGED;
+#endif
          MARK_GUTTER_CHANGED;
        }
-#endif
       f->last_nonminibuf_window = window;
     }
 }
 
 DEFUN ("set-frame-selected-window", Fset_frame_selected_window, 2, 2, 0, /*
-Set the selected window of frame object FRAME to WINDOW.
+Set the selected window of FRAME to WINDOW.
 If FRAME is nil, the selected frame is used.
 If FRAME is the selected frame, this makes WINDOW the selected window.
 */
@@ -964,7 +972,7 @@ is_surrogate_for_selected_frame (struct frame *f)
 }
 
 static int
-frame_matches_frametype (Lisp_Object frame, Lisp_Object type)
+frame_matches_frame_spec (Lisp_Object frame, Lisp_Object type)
 {
   struct frame *f = XFRAME (frame);
 
@@ -1025,160 +1033,141 @@ frame_matches_frametype (Lisp_Object frame, Lisp_Object type)
 }
 
 int
-device_matches_console_spec (Lisp_Object frame, Lisp_Object device,
-                            Lisp_Object console)
+device_matches_device_spec (Lisp_Object device, Lisp_Object device_spec)
 {
-  if (EQ (console, Qwindow_system))
+  if (EQ (device_spec, Qwindow_system))
     return DEVICE_WIN_P (XDEVICE (device));
-  if (NILP (console))
-    console = (DEVICE_CONSOLE (XDEVICE (FRAME_DEVICE (XFRAME (frame)))));
-  if (DEVICEP (console))
-    return EQ (device, console);
-  if (CONSOLEP (console))
-    return EQ (DEVICE_CONSOLE (XDEVICE (device)), console);
-  if (valid_console_type_p (console))
-    return EQ (DEVICE_TYPE (XDEVICE (device)), console);
+  if (DEVICEP (device_spec))
+    return EQ (device, device_spec);
+  if (CONSOLEP (device_spec))
+    return EQ (DEVICE_CONSOLE (XDEVICE (device)), device_spec);
+  if (valid_console_type_p (device_spec))
+    return EQ (DEVICE_TYPE (XDEVICE (device)), device_spec);
   return 1;
 }
 
 /* Return the next frame in the frame list after FRAME.
-   FRAMETYPE and CONSOLE control which frames and devices
+   WHICH-FRAMES and WHICH-DEVICES control which frames and devices
    are considered; see `next-frame'. */
 
-static Lisp_Object
-next_frame_internal (Lisp_Object frame, Lisp_Object frametype,
-                    Lisp_Object console, int called_from_delete_device)
+Lisp_Object
+next_frame (Lisp_Object frame, Lisp_Object which_frames, Lisp_Object which_devices)
 {
+  Lisp_Object first = Qnil;
+  Lisp_Object devcons, concons;
   int passed = 0;
-  int started_over = 0;
 
-  /* If this frame is dead, it won't be in frame_list, and we'll loop
-     forever.  Forestall that.  */
   CHECK_LIVE_FRAME (frame);
 
-  while (1)
+  DEVICE_LOOP_NO_BREAK (devcons, concons)
     {
-      Lisp_Object devcons, concons;
+      Lisp_Object device = XCAR (devcons);
+      Lisp_Object frmcons;
 
-      DEVICE_LOOP_NO_BREAK (devcons, concons)
+      if (!device_matches_device_spec (device, which_devices))
        {
-         Lisp_Object device = XCAR (devcons);
-         Lisp_Object frmcons;
+         if (EQ (device, FRAME_DEVICE (XFRAME (frame))))
+           passed = 1;
+         continue;
+       }
 
-         if (!device_matches_console_spec (frame, device, console))
-           continue;
+      DEVICE_FRAME_LOOP (frmcons, XDEVICE (device))
+       {
+         Lisp_Object f = XCAR (frmcons);
 
-         DEVICE_FRAME_LOOP (frmcons, XDEVICE (device))
+         if (passed)
+           {
+             if (frame_matches_frame_spec (f, which_frames))
+               return f;
+           }
+         else
            {
-             Lisp_Object f = XCAR (frmcons);
-             if (passed)
+             if (EQ (frame, f))
                {
-                 /* #### Doing this here is bad and is now
-                     unnecessary.  The real bug was that f->iconified
-                     was never, ever updated unless a user explicitly
-                     called frame-iconified-p.  That has now been
-                     fixed.  With this change removed all of the other
-                     changes made to support this routine having the
-                     called_from_delete_device arg could be removed.
-                     But it is too close to release to do that now. */
-#if 0
-                 /* Make sure the visibility and iconified flags are
-                     up-to-date unless we're being deleted. */
-                 if (!called_from_delete_device)
-                   {
-                     Fframe_iconified_p (f);
-                     Fframe_visible_p (f);
-                   }
-#endif
-
-                 /* Decide whether this frame is eligible to be returned.  */
-
-                 /* If we've looped all the way around without finding any
-                    eligible frames, return the original frame.  */
-                 if (EQ (f, frame))
-                   return f;
-
-                 if (frame_matches_frametype (f, frametype))
-                   return f;
+                 passed = 1;
+               }
+             else
+               {
+                 if (NILP (first) && frame_matches_frame_spec (f, which_frames))
+                   first = f;
                }
-
-             if (EQ (frame, f))
-               passed++;
            }
        }
-      /* We hit the end of the list, and need to start over again. */
-      if (started_over)
-       return Qnil;
-      started_over++;
     }
-}
 
-Lisp_Object
-next_frame (Lisp_Object frame, Lisp_Object frametype, Lisp_Object console)
-{
-  return next_frame_internal (frame, frametype, console, 0);
+  if (NILP (first))
+    /* We went through the whole frame list without finding a single
+       acceptable frame.  Return the original frame.  */
+    return frame;
+  else
+    /* There were no acceptable frames in the list after FRAME; otherwise,
+       we would have returned directly from the loop.  Since FIRST is the last
+       acceptable frame in the list, return it.  */
+    return first;
 }
 
 /* Return the previous frame in the frame list before FRAME.
-   FRAMETYPE and CONSOLE control which frames and devices
+   WHICH-FRAMES and WHICH-DEVICES control which frames and devices
    are considered; see `next-frame'. */
 
 Lisp_Object
-prev_frame (Lisp_Object frame, Lisp_Object frametype, Lisp_Object console)
+previous_frame (Lisp_Object frame, Lisp_Object which_frames, Lisp_Object which_devices)
 {
   Lisp_Object devcons, concons;
-  Lisp_Object prev;
+  Lisp_Object last = Qnil;
 
-  /* If this frame is dead, it won't be in frame_list, and we'll loop
-     forever.  Forestall that.  */
   CHECK_LIVE_FRAME (frame);
 
-  prev = Qnil;
   DEVICE_LOOP_NO_BREAK (devcons, concons)
     {
       Lisp_Object device = XCAR (devcons);
       Lisp_Object frmcons;
 
-      if (!device_matches_console_spec (frame, device, console))
-       continue;
+      if (!device_matches_device_spec (device, which_devices))
+       {
+         if (EQ (device, FRAME_DEVICE (XFRAME (frame)))
+             && !NILP (last))
+           return last;
+         continue;
+       }
 
       DEVICE_FRAME_LOOP (frmcons, XDEVICE (device))
        {
          Lisp_Object f = XCAR (frmcons);
 
-         if (EQ (frame, f) && !NILP (prev))
-           return prev;
-
-         /* Decide whether this frame is eligible to be returned,
-            according to frametype.  */
-
-         if (frame_matches_frametype (f, frametype))
-           prev = f;
-
+         if (EQ (frame, f))
+           {
+             if (!NILP (last))
+               return last;
+           }
+         else
+           {
+             if (frame_matches_frame_spec (f, which_frames))
+               last = f;
+           }
        }
     }
 
-  /* We've scanned the entire list.  */
-  if (NILP (prev))
+  if (NILP (last))
     /* We went through the whole frame list without finding a single
        acceptable frame.  Return the original frame.  */
     return frame;
   else
     /* There were no acceptable frames in the list before FRAME; otherwise,
-       we would have returned directly from the loop.  Since PREV is the last
+       we would have returned directly from the loop.  Since LAST is the last
        acceptable frame in the list, return it.  */
-    return prev;
+    return last;
 }
 
 DEFUN ("next-frame", Fnext_frame, 0, 3, 0, /*
 Return the next frame of the right type in the frame list after FRAME.
-FRAMETYPE controls which frames are eligible to be returned; all
+WHICH-FRAMES controls which frames are eligible to be returned; all
 others will be skipped.  Note that if there is only one eligible
 frame, then `next-frame' called repeatedly will always return
 the same frame, and if there is no eligible frame, then FRAME is
 returned.
 
-Possible values for FRAMETYPE are
+Possible values for WHICH-FRAMES are
 
 'visible                Consider only frames that are visible.
 'iconic                         Consider only frames that are iconic.
@@ -1196,43 +1185,44 @@ Possible values for FRAMETYPE are
                         frames.
 any other value                 Consider all frames.
 
-If FRAMETYPE is omitted, 'nomini is used.  A FRAMETYPE of 0 (a number)
-is treated like 'iconic, for backwards compatibility.
+If WHICH-FRAMES is omitted, 'nomini is used.  A value for WHICH-FRAMES
+of 0 (a number) is treated like 'iconic, for backwards compatibility.
 
-If FRAMETYPE is a window, include only its own frame and any frame now
-using that window as the minibuffer.
+If WHICH-FRAMES is a window, include only its own frame and any frame
+now using that window as the minibuffer.
 
-Optional third argument CONSOLE controls which consoles or devices the
-returned frame may be on.  If CONSOLE is a console, return frames only
-on that console.  If CONSOLE is a device, return frames only on that
-device.  If CONSOLE is a console type, return frames only on consoles
-of that type.  If CONSOLE is 'window-system, return any frames on any
-window-system consoles.  If CONSOLE is nil or omitted, return frames only
-on the FRAME's console.  Otherwise, all frames are considered.
+The optional third argument WHICH-DEVICES further clarifies on which
+devices to search for frames as specified by WHICH-FRAMES.
+If nil or omitted, search all devices on FRAME's console.
+If a device, only search that device.
+If a console, search all devices on that console.
+If a device type, search all devices of that type.
+If `window-system', search all window-system devices.
+Any other non-nil value means search all devices.
 */
-       (frame, frametype, console))
+       (frame, which_frames, which_devices))
 {
   XSETFRAME (frame, decode_frame (frame));
 
-  return next_frame (frame, frametype, console);
+  return next_frame (frame, which_frames, which_devices);
 }
 
 DEFUN ("previous-frame", Fprevious_frame, 0, 3, 0, /*
 Return the next frame of the right type in the frame list after FRAME.
-FRAMETYPE controls which frames are eligible to be returned; all
+WHICH-FRAMES controls which frames are eligible to be returned; all
 others will be skipped.  Note that if there is only one eligible
 frame, then `previous-frame' called repeatedly will always return
 the same frame, and if there is no eligible frame, then FRAME is
 returned.
 
-See `next-frame' for an explanation of the FRAMETYPE and CONSOLE
+See `next-frame' for an explanation of the WHICH-FRAMES and WHICH-DEVICES
 arguments.
 */
-       (frame, frametype, console))
+       (frame, which_frames, which_devices))
 {
   XSETFRAME (frame, decode_frame (frame));
 
-  return prev_frame (frame, frametype, console);
+  return previous_frame (frame, which_frames, which_devices);
 }
 
 /* Return any frame for which PREDICATE is non-zero, or return Qnil
@@ -1264,23 +1254,15 @@ find_some_frame (int (*predicate) (Lisp_Object, void *),
    (Exception: if F is a stream frame, it's OK to delete if
    any other frames exist.) */
 
-static int
-other_visible_frames_internal (struct frame *f, int called_from_delete_device)
+int
+other_visible_frames (struct frame *f)
 {
   Lisp_Object frame;
 
   XSETFRAME (frame, f);
   if (FRAME_STREAM_P (f))
-    return !EQ (frame, next_frame_internal (frame, Qt, Qt,
-                                           called_from_delete_device));
-  return !EQ (frame, next_frame_internal (frame, Qvisible_iconic_nomini, Qt,
-                                         called_from_delete_device));
-}
-
-int
-other_visible_frames (struct frame *f)
-{
-  return other_visible_frames_internal (f, 0);
+    return !EQ (frame, next_frame (frame, Qt, Qt));
+  return !EQ (frame, next_frame (frame, Qvisible_iconic_nomini, Qt));
 }
 
 /* Delete frame F.
@@ -1322,9 +1304,8 @@ delete_frame_internal (struct frame *f, int force,
   console = DEVICE_CONSOLE (d);
   con = XCONSOLE (console);
 
-  if (!called_from_delete_device &&
-      !(MAYBE_INT_DEVMETH (d, device_implementation_flags, ())
-       & XDEVIMPF_FRAMELESS_OK))
+  if (!called_from_delete_device
+      && !DEVICE_IMPL_FLAG (d, XDEVIMPF_FRAMELESS_OK))
     {
       /* If we're deleting the only non-minibuffer frame on the
         device, delete the device. */
@@ -1343,7 +1324,7 @@ delete_frame_internal (struct frame *f, int force,
      losing any way of communicating with the still running XEmacs process.
      So we put it back.  */
   if (!force && !allow_deletion_of_last_visible_frame &&
-      !other_visible_frames_internal (f, called_from_delete_device))
+      !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
@@ -1469,22 +1450,17 @@ delete_frame_internal (struct frame *f, int force,
 
       next = DEVMETH_OR_GIVEN (d, get_frame_parent, (f), Qnil);
       if (NILP (next) || EQ (next, frame) || ! FRAME_LIVE_P (XFRAME (next)))
-       next = next_frame_internal (frame, Qvisible, device,
-                                   called_from_delete_device);
+       next = next_frame (frame, Qvisible, device);
       if (NILP (next) || EQ (next, frame))
-       next = next_frame_internal (frame, Qvisible, console,
-                                   called_from_delete_device);
+       next = next_frame (frame, Qvisible, console);
       if (NILP (next) || EQ (next, frame))
-       next = next_frame_internal (frame, Qvisible, Qt,
-                                   called_from_delete_device);
+       next = next_frame (frame, Qvisible, Qt);
       if (NILP (next) || EQ (next, frame))
-       next = next_frame_internal (frame, Qt, device,
-                                   called_from_delete_device);
+       next = next_frame (frame, Qt, device);
       if (NILP (next) || EQ (next, frame))
-       next = next_frame_internal (frame, Qt, console,
-                                   called_from_delete_device);
+       next = next_frame (frame, Qt, console);
       if (NILP (next) || EQ (next, frame))
-       next = next_frame_internal (frame, Qt, Qt, called_from_delete_device);
+       next = next_frame (frame, Qt, Qt);
 
       /* if we haven't found another frame at this point
         then there aren't any. */
@@ -1506,9 +1482,7 @@ delete_frame_internal (struct frame *f, int force,
           */
          if (!EQ (device, FRAME_DEVICE(XFRAME(next))))
            {
-               Lisp_Object next_f =
-                   next_frame_internal (frame, Qt, device,
-                                        called_from_delete_device);
+               Lisp_Object next_f = next_frame (frame, Qt, device);
                if (NILP (next_f) || EQ (next_f, frame))
                  set_device_selected_frame (d, Qnil);
                else
@@ -1546,6 +1520,12 @@ delete_frame_internal (struct frame *f, int force,
   free_frame_toolbars (f);
 #endif
   free_frame_gutters (f);
+  /* Unfortunately deleting the frame will also delete the parent of
+     all of the subwindow instances current on the frame. I think this
+     can lead to bad things when trying to finalize the
+     instances. Thus we loop over all instance caches calling the
+     finalize method for each instance. */
+  free_frame_subwindow_instances (f);
 
   /* This must be done before the window and window_mirror structures
      are freed.  The scrollbar information is attached to them. */
@@ -1557,11 +1537,7 @@ delete_frame_internal (struct frame *f, int force,
   f->root_window = Qnil;
 
   /* clear out the cached glyph information */
-  if (f->subwindow_cachels)
-    {
-      Dynarr_free (f->subwindow_cachels);
-      f->subwindow_cachels = 0;
-    }
+  f->subwindow_instance_cache = Qnil;
 
   /* Remove the frame now from the list.  This way, any events generated
      on this frame by the maneuvers below will disperse themselves. */
@@ -1735,13 +1711,14 @@ mouse_pixel_position_1 (struct device *d, Lisp_Object *frame,
 
 DEFUN ("mouse-pixel-position", Fmouse_pixel_position, 0, 1, 0, /*
 Return a list (WINDOW X . Y) giving the current mouse window and position.
-The position is given in pixel units, where (0, 0) is the upper-left corner.
+The position is given in pixel units, where (0, 0) is the upper-left corner
+of the window.
 
 When the cursor is not over a window, the return value is a list (nil nil).
 
 DEVICE specifies the device on which to read the mouse position, and
 defaults to the selected device.  If the device is a mouseless terminal
-or Emacs hasn't been programmed to read its mouse position, it returns
+or XEmacs hasn't been programmed to read its mouse position, it returns
 the device's selected window for WINDOW and nil for X and Y.
 */
        (device))
@@ -1984,7 +1961,7 @@ Return non NIL if FRAME is now "visible" (actually in use for display).
 A frame that is not visible is not updated, and, if it works through a
 window system, may not show at all.
 N.B. Under X "visible" means Mapped. It the window is mapped but not
-actually visible on screen then frame_visible returns 'hidden.
+actually visible on screen then `frame-visible-p' returns 'hidden.
 */
        (frame))
 {
@@ -2023,8 +2000,8 @@ frame is iconified, it will not be visible.
 DEFUN ("visible-frame-list", Fvisible_frame_list, 0, 1, 0, /*
 Return a list of all frames now "visible" (being updated).
 If DEVICE is specified only frames on that device will be returned.
-Note that under virtual window managers not all these frame are necessarily
-really updated.
+Note that under virtual window managers not all these frames are
+necessarily really updated.
 */
        (device))
 {
@@ -2087,8 +2064,61 @@ doesn't support multiple overlapping frames, this function does nothing.
   return Qnil;
 }
 
+\f
+DEFUN ("disable-frame", Fdisable_frame, 1, 1, 0, /*
+Disable frame FRAME, so that it cannot have the focus or receive user input.
+This is normally used during modal dialog boxes.
+WARNING: Be very careful not to wedge XEmacs!
+Use an `unwind-protect' that re-enables the frame to avoid this.
+*/
+       (frame))
+{
+  struct frame *f = decode_frame (frame);
+
+  f->disabled = 1;
+  MAYBE_FRAMEMETH (f, disable_frame, (f));
+  return Qnil;
+}
+
+DEFUN ("enable-frame", Fenable_frame, 1, 1, 0, /*
+Enable frame FRAME, so that it can have the focus and receive user input.
+Frames are normally enabled, unless explicitly disabled using `disable-frame'.
+*/
+       (frame))
+{
+  struct frame *f = decode_frame (frame);
+  f->disabled = 0;
+  MAYBE_FRAMEMETH (f, enable_frame, (f));
+  return Qnil;
+}
+
 /* Ben thinks there is no need for `redirect-frame-focus' or `frame-focus',
    crockish FSFmacs functions.  See summary on focus in event-stream.c. */
+\f
+DEFUN ("print-job-page-number", Fprint_job_page_number, 1, 1, 0, /*
+Return current page number for the print job FRAME.
+*/
+       (frame))
+{
+  CHECK_PRINTER_FRAME (frame);
+  return make_int (FRAME_PAGENUMBER (XFRAME (frame)));
+}
+
+DEFUN ("print-job-eject-page", Fprint_job_eject_page, 1, 1, 0, /*
+Eject page in the print job FRAME.
+*/
+       (frame))
+{
+  struct frame *f;
+
+  CHECK_PRINTER_FRAME (frame);
+  f = XFRAME (frame);
+  FRAMEMETH (f, eject_page, (f));
+  FRAME_SET_PAGENUMBER (f, 1 + FRAME_PAGENUMBER (f));
+  f->clear = 1;
+
+  return Qnil;
+}
 
 \f
 /***************************************************************************/
@@ -2232,8 +2262,9 @@ The following symbols etc. have predefined meanings:
 
  minibuffer    Gives the minibuffer behavior for this frame.  Either
                t (frame has its own minibuffer), `only' (frame is
-               a minibuffer-only frame), or a window (frame uses that
-               window, which is on another frame, as the minibuffer).
+               a minibuffer-only frame), `none' (frame has no minibuffer)
+               or a window (frame uses that window, which is on another
+               frame, as the minibuffer).
 
  unsplittable  If non-nil, frame cannot be split by `display-buffer'.
 
@@ -2247,7 +2278,13 @@ The following symbols etc. have predefined meanings:
  left-toolbar-visible-p, right-toolbar-visible-p, toolbar-buttons-captioned-p,
  top-toolbar-border-width, bottom-toolbar-border-width,
  left-toolbar-border-width, right-toolbar-border-width,
- modeline-shadow-thickness, has-modeline-p
+ modeline-shadow-thickness, has-modeline-p,
+ default-gutter, top-gutter, bottom-gutter, left-gutter, right-gutter,
+ default-gutter-height, default-gutter-width, top-gutter-height,
+ bottom-gutter-height, left-gutter-width, right-gutter-width,
+ default-gutter-visible-p, top-gutter-visible-p, bottom-gutter-visible-p,
+ left-gutter-visible-p, right-gutter-visible-p, top-gutter-border-width,
+ bottom-gutter-border-width, left-gutter-border-width, right-gutter-border-width,
                [Giving the name of any built-in specifier variable is
                equivalent to calling `set-specifier' on the specifier,
                with a locale of FRAME.  Giving the name to `frame-property'
@@ -2368,6 +2405,7 @@ recognized for particular types of frames.
 
 DEFUN ("frame-property", Fframe_property, 2, 3, 0, /*
 Return FRAME's value for property PROPERTY.
+Return DEFAULT if there is no such property.
 See `set-frame-properties' for the built-in property names.
 */
        (frame, property, default_))
@@ -2563,21 +2601,21 @@ Specify that the frame FRAME has LINES lines.
 Optional third arg non-nil means that redisplay should use LINES lines
 but that the idea of the actual height of the frame should not be changed.
 */
-       (frame, rows, pretend))
+       (frame, lines, pretend))
 {
   struct frame *f = decode_frame (frame);
   int height, width;
   XSETFRAME (frame, f);
-  CHECK_INT (rows);
+  CHECK_INT (lines);
 
   if (window_system_pixelated_geometry (frame))
     {
-      char_to_real_pixel_size (f, 0, XINT (rows), 0, &height);
+      char_to_real_pixel_size (f, 0, XINT (lines), 0, &height);
       width = FRAME_PIXWIDTH (f);
     }
   else
     {
-      height = XINT (rows);
+      height = XINT (lines);
       width = FRAME_WIDTH (f);
     }
 
@@ -2613,7 +2651,7 @@ but that the idea of the actual width of the frame should not be changed.
 }
 
 DEFUN ("set-frame-size", Fset_frame_size, 3, 4, 0, /*
-Set the size of FRAME to COLS by ROWS.
+Set the size of FRAME to COLS by ROWS, measured in characters.
 Optional fourth arg non-nil means that redisplay should use COLS by ROWS
 but that the idea of the actual size of the frame should not be changed.
 */
@@ -2851,8 +2889,6 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth)
     - FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f)
     - 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f);
 
-  new_pixwidth += 2 * f->internal_border_width;
-
   /* Adjust the width for the end glyph which may be a different width
      than the default character width. */
   {
@@ -2874,7 +2910,14 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth)
 
   if (new_pixheight)
     {
-      XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = FRAME_TOP_BORDER_END (f);
+      /* Adjust for gutters here so that we always get set
+         properly. */
+      new_pixheight -=
+       (FRAME_TOP_GUTTER_BOUNDS (f)
+        + FRAME_BOTTOM_GUTTER_BOUNDS (f));
+
+      XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top
+       = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f);
 
       if (FRAME_HAS_MINIBUF_P (f)
          && ! FRAME_MINIBUF_ONLY_P (f))
@@ -2900,7 +2943,10 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth)
                                new_pixheight - minibuf_height, 0);
 
          XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top =
-           new_pixheight - minibuf_height + FRAME_TOP_BORDER_END (f);
+           FRAME_TOP_BORDER_END (f) +
+           FRAME_TOP_GUTTER_BOUNDS (f) +
+           FRAME_BOTTOM_GUTTER_BOUNDS (f) +
+           new_pixheight - minibuf_height;
 
          set_window_pixheight (FRAME_MINIBUF_WINDOW (f), minibuf_height, 0);
        }
@@ -2915,13 +2961,20 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth)
 
   if (new_pixwidth)
     {
-      XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = FRAME_LEFT_BORDER_END (f);
+      /* Adjust for gutters here so that we always get set
+         properly. */
+      new_pixwidth -=
+       (FRAME_LEFT_GUTTER_BOUNDS (f)
+        + FRAME_RIGHT_GUTTER_BOUNDS (f));
+
+      XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left =
+       FRAME_LEFT_BORDER_END (f) + FRAME_LEFT_GUTTER_BOUNDS (f);
       set_window_pixwidth (FRAME_ROOT_WINDOW (f), new_pixwidth, 0);
 
       if (FRAME_HAS_MINIBUF_P (f))
        {
          XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_left =
-           FRAME_LEFT_BORDER_END (f);
+           FRAME_LEFT_BORDER_END (f) + FRAME_LEFT_GUTTER_BOUNDS (f);
          set_window_pixwidth (FRAME_MINIBUF_WINDOW (f), new_pixwidth, 0);
        }
 
@@ -2940,6 +2993,7 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth)
     }
 
   MARK_FRAME_TOOLBARS_CHANGED (f);
+  MARK_FRAME_GUTTERS_CHANGED (f);
   MARK_FRAME_CHANGED (f);
   f->echo_area_garbaged = 1;
 }
@@ -2952,9 +3006,15 @@ change_frame_size (struct frame *f, int newheight, int newwidth, int delay)
      So deal. */
   check_frame_size (f, &newheight, &newwidth);
 
+  /* Unconditionally mark that the frame has changed size. This is
+     because many things need to know after the
+     fact. f->size_change_pending will get reset below. The most that
+     can happen is that we will cycle through redisplay once more
+     --andy. */
+  MARK_FRAME_SIZE_CHANGED (f);
+
   if (delay || in_display || gc_in_progress)
     {
-      MARK_FRAME_SIZE_CHANGED (f);
       f->new_width = newwidth;
       f->new_height = newheight;
       return;
@@ -3122,6 +3182,8 @@ init_frame (void)
 void
 syms_of_frame (void)
 {
+  INIT_LRECORD_IMPLEMENTATION (frame);
+
   defsymbol (&Qdelete_frame_hook, "delete-frame-hook");
   defsymbol (&Qselect_frame_hook, "select-frame-hook");
   defsymbol (&Qdeselect_frame_hook, "deselect-frame-hook");
@@ -3182,7 +3244,6 @@ syms_of_frame (void)
   defsymbol (&Qborder_width, "border-width");
   /* Qwidth, Qheight, Qleft, Qtop in general.c */
   defsymbol (&Qset_specifier, "set-specifier");
-  defsymbol (&Qset_glyph_image, "set-glyph-image");
   defsymbol (&Qset_face_property, "set-face-property");
   defsymbol (&Qface_property_instance, "face-property-instance");
   defsymbol (&Qframe_property_alias, "frame-property-alias");
@@ -3220,6 +3281,8 @@ syms_of_frame (void)
   DEFSUBR (Fvisible_frame_list);
   DEFSUBR (Fraise_frame);
   DEFSUBR (Flower_frame);
+  DEFSUBR (Fdisable_frame);
+  DEFSUBR (Fenable_frame);
   DEFSUBR (Fframe_property);
   DEFSUBR (Fframe_properties);
   DEFSUBR (Fset_frame_properties);
@@ -3232,6 +3295,8 @@ syms_of_frame (void)
   DEFSUBR (Fset_frame_size);
   DEFSUBR (Fset_frame_position);
   DEFSUBR (Fset_frame_pointer);
+  DEFSUBR (Fprint_job_page_number);
+  DEFSUBR (Fprint_job_eject_page);
 }
 
 void
@@ -3345,11 +3410,17 @@ visible frames.
   Vsynchronize_minibuffers = Qnil;
 
   DEFVAR_LISP ("frame-title-format", &Vframe_title_format /*
-Controls the title of the X window corresponding to the selected frame.
+Controls the title of the window-system window of the selected frame.
 This is the same format as `modeline-format' with the exception that
 %- is ignored.
 */ );
+/* #### I would change this unilaterally but for the wrath of the Kyles
+of the world. */
+#ifdef WIN32_NATIVE
+  Vframe_title_format = build_string ("%b - XEmacs");
+#else
   Vframe_title_format = build_string ("%S: %b");
+#endif
 
   DEFVAR_LISP ("frame-icon-title-format", &Vframe_icon_title_format /*
 Controls the title of the icon corresponding to the selected frame.
@@ -3359,8 +3430,9 @@ See also the variable `frame-title-format'.
 
   DEFVAR_LISP ("default-frame-name", &Vdefault_frame_name /*
 The default name to assign to newly-created frames.
-This can be overridden by arguments to `make-frame'.
-This must be a string.
+This can be overridden by arguments to `make-frame'.  This must be a string.
+This is used primarily for picking up X resources, and is *not* the title
+of the frame. (See `frame-title-format'.)
 */ );
 #ifndef INFODOCK
   Vdefault_frame_name = build_string ("emacs");