]> code.delx.au - gnu-emacs/blobdiff - src/frame.c
(Fset_frame_height): Call do_pending_window_change.
[gnu-emacs] / src / frame.c
index 8dea582b7c8a1518fab9c15349aee78d229cf9fe..831721201cc5b62c359e941047314e42aa7e78ab 100644 (file)
@@ -1,5 +1,5 @@
 /* Generic frame functions.
-   Copyright (C) 1993, 1994, 1995 Free Software Foundation.
+   Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -21,12 +21,24 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 
 #include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
 #include "lisp.h"
+#include "charset.h"
+#ifdef HAVE_X_WINDOWS
+#include "xterm.h"
+#endif
 #include "frame.h"
+#ifdef HAVE_WINDOW_SYSTEM
+#include "fontset.h"
+#endif
 #include "termhooks.h"
+#include "dispextern.h"
 #include "window.h"
 #ifdef MSDOS
 #include "msdos.h"
+#include "dosfns.h"
 #endif
 
 /* Evaluate this expression to rebuild the section of syms_of_frame
@@ -73,12 +85,14 @@ Lisp_Object Qname;
 Lisp_Object Qonly;
 Lisp_Object Qunsplittable;
 Lisp_Object Qmenu_bar_lines;
+Lisp_Object Qtoolbar_lines;
 Lisp_Object Qwidth;
 Lisp_Object Qx;
-Lisp_Object Qwin32;
+Lisp_Object Qw32;
 Lisp_Object Qpc;
 Lisp_Object Qvisible;
 Lisp_Object Qbuffer_predicate;
+Lisp_Object Qbuffer_list;
 Lisp_Object Qtitle;
 
 Lisp_Object Vterminal_frame;
@@ -108,18 +122,22 @@ syms_of_frame_1 ()
   staticpro (&Qunsplittable);
   Qmenu_bar_lines = intern ("menu-bar-lines");
   staticpro (&Qmenu_bar_lines);
+  Qtoolbar_lines = intern ("toolbar-lines");
+  staticpro (&Qtoolbar_lines);
   Qwidth = intern ("width");
   staticpro (&Qwidth);
   Qx = intern ("x");
   staticpro (&Qx);
-  Qwin32 = intern ("win32");
-  staticpro (&Qwin32);
+  Qw32 = intern ("w32");
+  staticpro (&Qw32);
   Qpc = intern ("pc");
   staticpro (&Qpc);
   Qvisible = intern ("visible");
   staticpro (&Qvisible);
   Qbuffer_predicate = intern ("buffer-predicate");
   staticpro (&Qbuffer_predicate);
+  Qbuffer_list = intern ("buffer-list");
+  staticpro (&Qbuffer_list);
   Qtitle = intern ("title");
   staticpro (&Qtitle);
 
@@ -160,7 +178,7 @@ set_menu_bar_lines_1 (window, n)
     }
 }
 
-static void
+void
 set_menu_bar_lines (f, value, oldval)
      struct frame *f;
      Lisp_Object value, oldval;
@@ -186,6 +204,7 @@ set_menu_bar_lines (f, value, oldval)
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
       FRAME_MENU_BAR_LINES (f) = nlines;
       set_menu_bar_lines_1 (f->root_window, nlines - olines);
+      adjust_glyphs (f);
     }
 }
 \f
@@ -221,8 +240,8 @@ See also `frame-live-p'.")
       return Qt;
     case output_x_window:
       return Qx;
-    case output_win32:
-      return Qwin32;
+    case output_w32:
+      return Qw32;
     case output_msdos_raw:
       return Qpc;
     default:
@@ -263,10 +282,12 @@ make_frame (mini_p)
   f = (struct frame *)vec;
   XSETFRAME (frame, f);
 
-  f->cursor_x = 0;
-  f->cursor_y = 0;
-  f->current_glyphs = 0;
-  f->desired_glyphs = 0;
+  f->desired_matrix = 0;
+  f->current_matrix = 0;
+  f->desired_pool = 0;
+  f->current_pool = 0;
+  f->glyphs_initialized_p = 0;
+  f->decode_mode_spec_buffer = 0;
   f->visible = 0;
   f->async_visible = 0;
   f->output_data.nothing = 0;
@@ -281,20 +302,27 @@ make_frame (mini_p)
   f->focus_frame = Qnil;
   f->explicit_name = 0;
   f->can_have_scroll_bars = 0;
-  f->has_vertical_scroll_bars = 0;
+  f->vertical_scroll_bar_type = vertical_scroll_bar_none;
   f->param_alist = Qnil;
   f->scroll_bars = Qnil;
   f->condemned_scroll_bars = Qnil;
   f->face_alist = Qnil;
+  f->face_cache = NULL;
   f->menu_bar_items = Qnil;
   f->menu_bar_vector = Qnil;
   f->menu_bar_items_used = 0;
   f->buffer_predicate = Qnil;
+  f->buffer_list = Qnil;
 #ifdef MULTI_KBOARD
   f->kboard = initial_kboard;
 #endif
   f->namebuf = 0;
   f->title = Qnil;
+  f->menu_bar_window = Qnil;
+  f->toolbar_window = Qnil;
+  f->desired_toolbar_items = f->current_toolbar_items = Qnil;
+  f->desired_toolbar_string = f->current_toolbar_string = Qnil;
+  f->n_desired_toolbar_items = f->n_current_toolbar_items = 0;
 
   root_window = make_window ();
   if (mini_p)
@@ -319,7 +347,7 @@ make_frame (mini_p)
      just so that there is "something there."
      Correct size will be set up later with change_frame_size.  */
 
-  f->width = 10;
+  SET_FRAME_WIDTH (f, 10);
   f->height = 10;
 
   XSETFASTINT (XWINDOW (root_window)->width, 10);
@@ -341,17 +369,26 @@ make_frame (mini_p)
     /* If buf is a 'hidden' buffer (i.e. one whose name starts with
        a space), try to find another one.  */
     if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
-      buf = Fother_buffer (buf, Qnil);
-    Fset_window_buffer (root_window, buf);
+      buf = Fother_buffer (buf, Qnil, Qnil);
+
+    /* Use set_window_buffer, not Fset_window_buffer, and don't let
+       hooks be run by it.  The reason is that the whole frame/window
+       arrangement is not yet fully intialized at this point.  Windows
+       don't have the right size, glyph matrices aren't initialized
+       etc.  Running Lisp functions at this point surely ends in a
+       SEGV.  */
+    set_window_buffer (root_window, buf, 0);
+    f->buffer_list = Fcons (buf, Qnil);
   }
 
   if (mini_p)
     {
       XWINDOW (mini_window)->buffer = Qt;
-      Fset_window_buffer (mini_window,
-                         (NILP (Vminibuffer_list)
-                          ? get_minibuffer (0)
-                          : Fcar (Vminibuffer_list)));
+      set_window_buffer (mini_window,
+                        (NILP (Vminibuffer_list)
+                         ? get_minibuffer (0)
+                         : Fcar (Vminibuffer_list)),
+                        0);
     }
 
   f->root_window = root_window;
@@ -360,9 +397,14 @@ make_frame (mini_p)
      a newly-created, never-selected window.  */
   XSETFASTINT (XWINDOW (f->selected_window)->use_time, ++window_select_count);
 
+#ifdef HAVE_WINDOW_SYSTEM
+  f->fontset_data = alloc_fontset_data ();
+#endif
+
   return f;
 }
 \f
+#ifdef HAVE_WINDOW_SYSTEM
 /* Make a frame using a separate minibuffer window on another frame.
    MINI_WINDOW is the minibuffer window to use.  nil means use the
    default (the global minibuffer).  */
@@ -456,6 +498,7 @@ make_minibuffer_frame ()
                       : Fcar (Vminibuffer_list)));
   return f;
 }
+#endif /* HAVE_WINDOW_SYSTEM */
 \f
 /* Construct a frame that refers to the terminal (stdin and stdout).  */
 
@@ -488,24 +531,19 @@ make_terminal_frame ()
   Vframe_list = Fcons (frame, Vframe_list);
 
   terminal_frame_count++;
-  if (terminal_frame_count == 1)
-    {
-      f->name = build_string ("Emacs");
-    }
-  else
-    {
-      sprintf (name, "Emacs-%d", terminal_frame_count);
-      f->name = build_string (name);
-    }
+  sprintf (name, "F%d", terminal_frame_count);
+  f->name = build_string (name);
 
   f->visible = 1;              /* FRAME_SET_VISIBLE wd set frame_garbaged. */
   f->async_visible = 1;                /* Don't let visible be cleared later. */
 #ifdef MSDOS
   f->output_data.x = &the_only_x_display;
   f->output_method = output_msdos_raw;
-  init_frame_faces (f);
+  if (!noninteractive)
+    init_frame_faces (f);
 #else /* not MSDOS */
   f->output_data.nothing = 1;  /* Nonzero means frame isn't deleted.  */
+  init_frame_faces (f);
 #endif
   return f;
 }
@@ -534,9 +572,10 @@ Note that changing the size of one terminal frame automatically affects all.")
   f = make_terminal_frame ();
   change_frame_size (f, FRAME_HEIGHT (selected_frame),
                     FRAME_WIDTH (selected_frame), 0, 0);
-  remake_frame_glyphs (f);
+  adjust_glyphs (f);
   calculate_costs (f);
   XSETFRAME (frame, f);
+  Fmodify_frame_parameters (frame, Vdefault_frame_alist);
   Fmodify_frame_parameters (frame, parms);
   f->face_alist = selected_frame->face_alist;
   return frame;
@@ -1063,6 +1102,13 @@ but if the second optional argument FORCE is non-nil, you may do so.")
   if (NILP (force) && !other_visible_frames (f))
     error ("Attempt to delete the sole visible or iconified frame");
 
+#if 0
+  /* This is a nice idea, but x_connection_closed needs to be able
+     to delete the last frame, if it is gone.  */
+  if (NILP (XCONS (Vframe_list)->cdr))
+    error ("Attempt to delete the only frame");
+#endif
+
   /* Does this frame have a minibuffer, and is it the surrogate
      minibuffer for any other frame?  */
   if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
@@ -1126,6 +1172,12 @@ but if the second optional argument FORCE is non-nil, you may do so.")
     x_clear_frame_selections (f);
 #endif
 
+  /* Free glyphs. 
+     This function must be called before the window tree of the 
+     frame is deleted because windows contain dynamically allocated
+     memory. */
+  free_glyphs (f);
+
   /* 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));
@@ -1134,22 +1186,29 @@ but if the second optional argument FORCE is non-nil, you may do so.")
   Vframe_list = Fdelq (frame, Vframe_list);
   FRAME_SET_VISIBLE (f, 0);
 
+  if (echo_area_glyphs == FRAME_MESSAGE_BUF (f))
+    {
+      echo_area_glyphs = 0;
+      previous_echo_glyphs = 0;
+    }
+
   if (f->namebuf)
-    free (f->namebuf);
-  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));
+    xfree (f->namebuf);
   if (FRAME_INSERT_COST (f))
-    free (FRAME_INSERT_COST (f));
+    xfree (FRAME_INSERT_COST (f));
   if (FRAME_DELETEN_COST (f))
-    free (FRAME_DELETEN_COST (f));
+    xfree (FRAME_DELETEN_COST (f));
   if (FRAME_INSERTN_COST (f))
-    free (FRAME_INSERTN_COST (f));
+    xfree (FRAME_INSERTN_COST (f));
   if (FRAME_DELETE_COST (f))
-    free (FRAME_DELETE_COST (f));
+    xfree (FRAME_DELETE_COST (f));
+  if (FRAME_MESSAGE_BUF (f))
+    xfree (FRAME_MESSAGE_BUF (f));
+
+#ifdef HAVE_WINDOW_SYSTEM
+  /* Free all fontset data.  */
+  free_fontset_data (FRAME_FONTSET_DATA (f));
+#endif
 
   /* 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
@@ -1245,6 +1304,9 @@ but if the second optional argument FORCE is non-nil, you may do so.")
        FRAME_KBOARD (f)->Vdefault_minibuffer_frame = Qnil;
     }
 
+  /* Cause frame titles to update--necessary if we now have just one frame.  */
+  update_mode_lines = 1;
+
   return Qnil;
 }
 \f
@@ -1272,7 +1334,7 @@ and nil for X and Y.")
 #ifdef HAVE_MOUSE
   /* It's okay for the hook to refrain from storing anything.  */
   if (mouse_position_hook)
-    (*mouse_position_hook) (&f, 0,
+    (*mouse_position_hook) (&f, -1,
                            &lispy_dummy, &party_dummy,
                            &x, &y,
                            &long_dummy);
@@ -1312,7 +1374,7 @@ and nil for X and Y.")
 #ifdef HAVE_MOUSE
   /* It's okay for the hook to refrain from storing anything.  */
   if (mouse_position_hook)
-    (*mouse_position_hook) (&f, 0,
+    (*mouse_position_hook) (&f, -1,
                            &lispy_dummy, &party_dummy,
                            &x, &y,
                            &long_dummy);
@@ -1323,7 +1385,11 @@ and nil for X and Y.")
 
 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
   "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
-Note, this is a no-op for an X frame that is not visible.\n\
+Coordinates are relative to the frame, not a window,\n\
+so the coordinates of the top left character in the frame\n\
+may be nonzero due to left-hand scroll bars or the menu bar.\n\
+\n\
+This function is a no-op for an X frame that is not visible.\n\
 If you have just created a frame, you must wait for it to become visible\n\
 before calling this function on it, like this.\n\
   (while (not (frame-visible-p frame)) (sleep-for .5))")
@@ -1338,7 +1404,7 @@ before calling this function on it, like this.\n\
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (XFRAME (frame)))
     /* Warping the mouse will cause  enternotify and focus events. */
-    x_set_mouse_position (XFRAME (frame), x, y);
+    x_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
 #else
 #if defined (MSDOS) && defined (HAVE_MOUSE)
   if (FRAME_MSDOS_P (XFRAME (frame)))
@@ -1370,7 +1436,7 @@ before calling this function on it, like this.\n\
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (XFRAME (frame)))
     /* Warping the mouse will cause  enternotify and focus events. */
-    x_set_mouse_pixel_position (XFRAME (frame), x, y);
+    x_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
 #else
 #if defined (MSDOS) && defined (HAVE_MOUSE)
   if (FRAME_MSDOS_P (XFRAME (frame)))
@@ -1384,6 +1450,8 @@ before calling this function on it, like this.\n\
   return Qnil;
 }
 \f
+static void make_frame_visible_1 P_ ((Lisp_Object));
+
 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
        0, 1, "",
   "Make the frame FRAME visible (assuming it is an X-window).\n\
@@ -1405,12 +1473,37 @@ If omitted, FRAME defaults to the currently selected frame.")
     }
 #endif
 
+  make_frame_visible_1 (XFRAME (frame)->root_window);
+
   /* Make menu bar update for the Buffers and Frams menus.  */
   windows_or_buffers_changed++;
 
   return frame;
 }
 
+/* Update the display_time slot of the buffers shown in WINDOW
+   and all its descendents.  */
+
+static void
+make_frame_visible_1 (window)
+     Lisp_Object window;
+{
+  struct window *w;
+
+  for (;!NILP (window); window = w->next)
+    {
+      w = XWINDOW (window);
+
+      if (!NILP (w->buffer))
+       XBUFFER (w->buffer)->display_time = Fcurrent_time ();
+
+      if (!NILP (w->vchild))
+       make_frame_visible_1 (w->vchild);
+      if (!NILP (w->hchild))
+       make_frame_visible_1 (w->hchild);
+    }
+}
+
 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
        0, 2, "",
   "Make the frame FRAME invisible (assuming it is an X-window).\n\
@@ -1617,13 +1710,6 @@ The redirection lasts until `redirect-frame-focus' is called to change it.")
 
   XFRAME (frame)->focus_frame = focus_frame;
 
-  /* I think this should be done with a hook.  */
-#ifdef HAVE_WINDOW_SYSTEM
-  if (!NILP (focus_frame) && ! EQ (focus_frame, frame)
-      && (FRAME_WINDOW_P (XFRAME (focus_frame))))
-    Ffocus_frame (focus_frame);
-#endif
-
   if (frame_rehighlight_hook)
     (*frame_rehighlight_hook) (XFRAME (frame));
   
@@ -1663,9 +1749,59 @@ get_frame_param (frame, prop)
 /* Return the buffer-predicate of the selected frame.  */
 
 Lisp_Object
-frame_buffer_predicate ()
+frame_buffer_predicate (frame)
+     Lisp_Object frame;
+{
+  return XFRAME (frame)->buffer_predicate;
+}
+
+/* Return the buffer-list of the selected frame.  */
+
+Lisp_Object
+frame_buffer_list (frame)
+     Lisp_Object frame;
+{
+  return XFRAME (frame)->buffer_list;
+}
+
+/* Set the buffer-list of the selected frame.  */
+
+void
+set_frame_buffer_list (frame, list)
+     Lisp_Object frame, list;
 {
-  return selected_frame->buffer_predicate;
+  XFRAME (frame)->buffer_list = list;
+}
+
+/* Discard BUFFER from the buffer-list of each frame.  */
+
+void
+frames_discard_buffer (buffer)
+     Lisp_Object buffer;
+{
+  Lisp_Object frame, tail;
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      XFRAME (frame)->buffer_list
+       = Fdelq (buffer, XFRAME (frame)->buffer_list);
+    }
+}
+
+/* Move BUFFER to the end of the buffer-list of each frame.  */
+
+void
+frames_bury_buffer (buffer)
+     Lisp_Object buffer;
+{
+  Lisp_Object frame, tail;
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      XFRAME (frame)->buffer_list
+       = nconc2 (Fdelq (buffer, XFRAME (frame)->buffer_list),
+                 Fcons (buffer, Qnil));
+    }
 }
 
 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
@@ -1685,6 +1821,65 @@ store_in_alist (alistptr, prop, val)
     Fsetcdr (tem, val);
 }
 
+static int
+frame_name_fnn_p (str, len)
+     char *str;
+     int len;
+{
+  if (len > 1 && str[0] == 'F')
+    {
+      char *end_ptr;
+      long num = strtol (str + 1, &end_ptr, 10);
+
+      if (end_ptr == str + len)
+       return 1;
+    }
+  return 0;
+}
+
+/* Set the name of the terminal frame.  Also used by MSDOS frames.
+   Modeled after x_set_name which is used for WINDOW frames.  */
+
+void
+set_term_frame_name (f, name)
+     struct frame *f;
+     Lisp_Object name;
+{
+  f->explicit_name = ! NILP (name);
+
+  /* If NAME is nil, set the name to F<num>.  */
+  if (NILP (name))
+    {
+      char namebuf[20];
+
+      /* Check for no change needed in this very common case
+        before we do any consing.  */
+      if (frame_name_fnn_p (XSTRING (f->name)->data,
+                           STRING_BYTES (XSTRING (f->name))))
+       return;
+
+      terminal_frame_count++;
+      sprintf (namebuf, "F%d", terminal_frame_count);
+      name = build_string (namebuf);
+    }
+  else
+    {
+      CHECK_STRING (name, 0);
+
+      /* Don't change the name if it's already NAME.  */
+      if (! NILP (Fstring_equal (name, f->name)))
+       return;
+
+      /* Don't allow the user to set the frame name to F<num>, so it
+        doesn't clash with the names we generate for terminal frames.  */
+      if (frame_name_fnn_p (XSTRING (name)->data, STRING_BYTES (XSTRING (name))))
+       error ("Frame names of the form F<num> are usurped by Emacs");
+    }
+
+  f->name = name;
+  update_mode_lines = 1;
+}
+
 void
 store_frame_param (f, prop, val)
      struct frame *f;
@@ -1692,6 +1887,12 @@ store_frame_param (f, prop, val)
 {
   register Lisp_Object tem;
 
+  if (EQ (prop, Qbuffer_list))
+    {
+      f->buffer_list = val;
+      return;
+    }
+
   tem = Fassq (prop, f->param_alist);
   if (EQ (tem, Qnil))
     f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
@@ -1702,16 +1903,21 @@ store_frame_param (f, prop, val)
     f->buffer_predicate = val;
 
   if (! FRAME_WINDOW_P (f))
-    if (EQ (prop, Qmenu_bar_lines))
-      set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
+    {
+      if (EQ (prop, Qmenu_bar_lines))
+       set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
+      else if (EQ (prop, Qname))
+       set_term_frame_name (f, val);
+    }
 
   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");
+      if (FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f)
+         && !EQ (val, f->minibuffer_window))
+       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;
@@ -1745,18 +1951,15 @@ If FRAME is omitted, return information on the currently selected frame.")
 #ifdef MSDOS
   if (FRAME_MSDOS_P (f))
     {
-      static char *colornames[16] = 
-       {
-         "black", "blue", "green", "cyan", "red", "magenta", "brown",
-         "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
-         "lightred", "lightmagenta", "yellow", "white"
-       };
+      int fg = FRAME_FOREGROUND_PIXEL (f);
+      int bg = FRAME_BACKGROUND_PIXEL (f);
+
       store_in_alist (&alist, intern ("foreground-color"),
-                     build_string (colornames[FRAME_FOREGROUND_PIXEL (f)]));
+                     build_string (msdos_stdcolor_name (fg)));
       store_in_alist (&alist, intern ("background-color"),
-                     build_string (colornames[FRAME_BACKGROUND_PIXEL (f)]));
+                     build_string (msdos_stdcolor_name (bg)));
     }
-  store_in_alist (&alist, intern ("font"), build_string ("default"));
+  store_in_alist (&alist, intern ("font"), build_string ("ms-dos"));
 #endif
   store_in_alist (&alist, Qname, f->name);
   height = (FRAME_NEW_HEIGHT (f) ? FRAME_NEW_HEIGHT (f) : FRAME_HEIGHT (f));
@@ -1769,6 +1972,8 @@ If FRAME is omitted, return information on the currently selected frame.")
                   : FRAME_MINIBUF_ONLY_P (f) ? Qonly
                   : FRAME_MINIBUF_WINDOW (f)));
   store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
+  store_in_alist (&alist, Qbuffer_list,
+                 frame_buffer_list (Fselected_frame ()));
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
@@ -1790,7 +1995,9 @@ DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
   "Modify the parameters of frame FRAME according to ALIST.\n\
 ALIST is an alist of parameters to change and their new values.\n\
 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
-The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
+The meaningful PARMs depend on the kind of frame.\n\
+Undefined PARMs are ignored, but stored in the frame's parameter list\n\
+so that `frame-parameters' will return them.")
   (frame, alist)
      Lisp_Object frame, alist;
 {
@@ -1816,13 +2023,35 @@ The meaningful PARMs depend on the kind of frame; undefined PARMs are ignored.")
     IT_set_frame_parameters (f, alist);
   else
 #endif
-    for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
-      {
-       elt = Fcar (tail);
-       prop = Fcar (elt);
-       val = Fcdr (elt);
-       store_frame_param (f, prop, val);
-      }
+    {
+      int length = XINT (Flength (alist));
+      int i;
+      Lisp_Object *parms
+       = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
+      Lisp_Object *values
+       = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
+
+      /* Extract parm names and values into those vectors.  */
+
+      i = 0;
+      for (tail = alist; CONSP (tail); tail = Fcdr (tail))
+       {
+         Lisp_Object elt, prop, val;
+
+         elt = Fcar (tail);
+         parms[i] = Fcar (elt);
+         values[i] = Fcdr (elt);
+         i++;
+       }
+
+      /* Now process them in reverse of specified order.  */
+      for (i--; i >= 0; i--)
+       {
+         prop = parms[i];
+         val = values[i];
+         store_frame_param (f, prop, val);
+       }
+    }
 
   return Qnil;
 }
@@ -1885,6 +2114,8 @@ For a terminal screen, the value is always 1.")
 DEFUN ("frame-pixel-height", Fframe_pixel_height, 
        Sframe_pixel_height, 0, 1, 0,
   "Return a FRAME's height in pixels.\n\
+This counts only the height available for text lines,\n\
+not menu bars on window-system Emacs frames.\n\
 For a terminal frame, the result really gives the height in characters.\n\
 If FRAME is omitted, the selected frame is used.")
   (frame)
@@ -1958,6 +2189,7 @@ but that the idea of the actual height of the frame should not be changed.")
     {
       if (XINT (lines) != f->height)
        x_set_window_size (f, 1, f->width, XINT (lines));
+      do_pending_window_change ();
     }
   else
 #endif
@@ -1988,6 +2220,7 @@ but that the idea of the actual width of the frame should not be changed.")
     {
       if (XINT (cols) != f->width)
        x_set_window_size (f, 1, XINT (cols), f->height);
+      do_pending_window_change ();
     }
   else
 #endif
@@ -2015,6 +2248,7 @@ DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
       if (XINT (rows) != f->height || XINT (cols) != f->width
          || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
        x_set_window_size (f, 1, XINT (cols), XINT (rows));
+      do_pending_window_change ();
     }
   else
 #endif
@@ -2050,6 +2284,7 @@ the rightmost or bottommost possible position (that stays within the screen).")
 }
 
 \f
+void
 syms_of_frame ()
 {
   syms_of_frame_1 ();
@@ -2122,6 +2357,7 @@ displayed.");
   defsubr (&Sset_frame_position);
 }
 
+void
 keys_of_frame ()
 {
   initial_define_lispy_key (global_map, "switch-frame", "handle-switch-frame");