*** empty log message ***
[bpt/emacs.git] / src / frame.c
index 77caef6..8af3e4b 100644 (file)
@@ -4,10 +4,10 @@
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,37 +15,37 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 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, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
 #include <stdio.h>
 
 #include <config.h>
 
 #include <stdio.h>
+#include <ctype.h>
 #include "lisp.h"
 #include "lisp.h"
-#include "charset.h"
+#include "character.h"
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
 #ifdef WINDOWSNT
 #include "w32term.h"
 #endif
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
 #ifdef WINDOWSNT
 #include "w32term.h"
 #endif
-#ifdef MAC_OS
-#include "macterm.h"
+#ifdef HAVE_NS
+#include "nsterm.h"
 #endif
 #include "buffer.h"
 /* These help us bind and responding to switch-frame events.  */
 #include "commands.h"
 #include "keyboard.h"
 #include "frame.h"
 #endif
 #include "buffer.h"
 /* These help us bind and responding to switch-frame events.  */
 #include "commands.h"
 #include "keyboard.h"
 #include "frame.h"
-#ifdef HAVE_WINDOW_SYSTEM
-#include "fontset.h"
-#endif
 #include "blockinput.h"
 #include "termchar.h"
 #include "termhooks.h"
 #include "dispextern.h"
 #include "window.h"
 #include "blockinput.h"
 #include "termchar.h"
 #include "termhooks.h"
 #include "dispextern.h"
 #include "window.h"
+#ifdef HAVE_WINDOW_SYSTEM
+#include "font.h"
+#include "fontset.h"
+#endif
 #ifdef MSDOS
 #include "msdos.h"
 #include "dosfns.h"
 #ifdef MSDOS
 #include "msdos.h"
 #include "dosfns.h"
@@ -63,15 +63,24 @@ Lisp_Object Vx_resource_name;
 
 Lisp_Object Vx_resource_class;
 
 
 Lisp_Object Vx_resource_class;
 
+/* Lower limit value of the frame opacity (alpha transparency).  */
+
+Lisp_Object Vframe_alpha_lower_limit;
+
+#endif
+
+#ifdef HAVE_NS
+Lisp_Object Qns_parse_geometry;
 #endif
 
 Lisp_Object Qframep, Qframe_live_p;
 Lisp_Object Qicon, Qmodeline;
 Lisp_Object Qonly;
 #endif
 
 Lisp_Object Qframep, Qframe_live_p;
 Lisp_Object Qicon, Qmodeline;
 Lisp_Object Qonly;
-Lisp_Object Qx, Qw32, Qmac, Qpc;
+Lisp_Object Qx, Qw32, Qmac, Qpc, Qns;
 Lisp_Object Qvisible;
 Lisp_Object Qdisplay_type;
 Lisp_Object Qbackground_mode;
 Lisp_Object Qvisible;
 Lisp_Object Qdisplay_type;
 Lisp_Object Qbackground_mode;
+Lisp_Object Qnoelisp;
 
 Lisp_Object Qx_frame_parameter;
 Lisp_Object Qx_resource_name;
 
 Lisp_Object Qx_frame_parameter;
 Lisp_Object Qx_resource_name;
@@ -112,8 +121,9 @@ Lisp_Object Qtty_color_mode;
 Lisp_Object Qtty, Qtty_type;
 
 Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
 Lisp_Object Qtty, Qtty_type;
 
 Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
+Lisp_Object Qfont_backend;
+Lisp_Object Qalpha;
 
 
-Lisp_Object Qinhibit_face_set_after_frame_default;
 Lisp_Object Qface_set_after_frame_default;
 
 Lisp_Object Vterminal_frame;
 Lisp_Object Qface_set_after_frame_default;
 
 Lisp_Object Vterminal_frame;
@@ -121,7 +131,7 @@ Lisp_Object Vdefault_frame_alist;
 Lisp_Object Vdefault_frame_scroll_bars;
 Lisp_Object Vmouse_position_function;
 Lisp_Object Vmouse_highlight;
 Lisp_Object Vdefault_frame_scroll_bars;
 Lisp_Object Vmouse_position_function;
 Lisp_Object Vmouse_highlight;
-Lisp_Object Vdelete_frame_functions;
+static Lisp_Object Vdelete_frame_functions, Qdelete_frame_functions;
 
 int focus_follows_mouse;
 \f
 
 int focus_follows_mouse;
 \f
@@ -197,7 +207,7 @@ DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
 Value is t for a termcap frame (a character-only terminal),
 `x' for an Emacs frame that is really an X window,
 `w32' for an Emacs frame that is a window on MS-Windows display,
 Value is t for a termcap frame (a character-only terminal),
 `x' for an Emacs frame that is really an X window,
 `w32' for an Emacs frame that is a window on MS-Windows display,
-`mac' for an Emacs frame on a Macintosh display,
+`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
 `pc' for a direct-write MS-DOS frame.
 See also `frame-live-p'.  */)
      (object)
 `pc' for a direct-write MS-DOS frame.
 See also `frame-live-p'.  */)
      (object)
@@ -218,6 +228,8 @@ See also `frame-live-p'.  */)
       return Qpc;
     case output_mac:
       return Qmac;
       return Qpc;
     case output_mac:
       return Qmac;
+    case output_ns:
+      return Qns;
     default:
       abort ();
     }
     default:
       abort ();
     }
@@ -326,6 +338,8 @@ make_frame (mini_p)
 #endif
   f->size_hint_flags = 0;
   f->win_gravity = 0;
 #endif
   f->size_hint_flags = 0;
   f->win_gravity = 0;
+  f->font_driver_list = NULL;
+  f->font_data_list = NULL;
 
   root_window = make_window ();
   if (mini_p)
 
   root_window = make_window ();
   if (mini_p)
@@ -423,11 +437,9 @@ make_frame_without_minibuffer (mini_window, kb, display)
   if (!NILP (mini_window))
     CHECK_LIVE_WINDOW (mini_window);
 
   if (!NILP (mini_window))
     CHECK_LIVE_WINDOW (mini_window);
 
-#ifdef MULTI_KBOARD
   if (!NILP (mini_window)
       && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
     error ("Frame and minibuffer must be on the same terminal");
   if (!NILP (mini_window)
       && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
     error ("Frame and minibuffer must be on the same terminal");
-#endif
 
   /* Make a frame containing just a root window.  */
   f = make_frame (0);
 
   /* Make a frame containing just a root window.  */
   f = make_frame (0);
@@ -543,6 +555,11 @@ make_initial_frame (void)
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
 
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
 
+#ifdef CANNOT_DUMP
+  if (!noninteractive)
+    init_frame_faces (f);
+#endif
+
   return f;
 }
 
   return f;
 }
 
@@ -568,49 +585,23 @@ make_terminal_frame (struct terminal *terminal)
 
   f->visible = 1;              /* FRAME_SET_VISIBLE wd set frame_garbaged. */
   f->async_visible = 1;                /* Don't let visible be cleared later. */
 
   f->visible = 1;              /* FRAME_SET_VISIBLE wd set frame_garbaged. */
   f->async_visible = 1;                /* Don't let visible be cleared later. */
+  f->terminal = terminal;
+  f->terminal->reference_count++;
 #ifdef MSDOS
 #ifdef MSDOS
-  f->output_data.x = &the_only_x_display;
+  f->output_data.tty->display_info = &the_only_display_info;
   if (!inhibit_window_system
       && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
          || XFRAME (selected_frame)->output_method == output_msdos_raw))
   if (!inhibit_window_system
       && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
          || XFRAME (selected_frame)->output_method == output_msdos_raw))
-    {
-      f->output_method = output_msdos_raw;
-      /* This initialization of foreground and background pixels is
-        only important for the initial frame created in temacs.  If
-        we don't do that, we get black background and foreground in
-        the dumped Emacs because the_only_x_display is a static
-        variable, hence it is born all-zeroes, and zero is the code
-        for the black color.  Other frames all inherit their pixels
-        from what's already in the_only_x_display.  */
-      if ((!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
-         && FRAME_BACKGROUND_PIXEL (f) == 0
-         && FRAME_FOREGROUND_PIXEL (f) == 0)
-       {
-         FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
-         FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
-       }
-    }
+    f->output_method = output_msdos_raw;
   else
     f->output_method = output_termcap;
 #else
   {
     f->output_method = output_termcap;
   else
     f->output_method = output_termcap;
 #else
   {
     f->output_method = output_termcap;
-    f->terminal = terminal;
-    f->terminal->reference_count++;
     create_tty_output (f);
 
     FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
     FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
     create_tty_output (f);
 
     FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
     FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
-
-    FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
-    FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
-
-    /* Set the top frame to the newly created frame. */
-    if (FRAMEP (FRAME_TTY (f)->top_frame)
-        && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
-      XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */
-
-    FRAME_TTY (f)->top_frame = frame;
   }
 
 #ifdef CANNOT_DUMP
   }
 
 #ifdef CANNOT_DUMP
@@ -619,6 +610,16 @@ make_terminal_frame (struct terminal *terminal)
 #endif
 #endif /* MSDOS */
 
 #endif
 #endif /* MSDOS */
 
+  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+
+  /* Set the top frame to the newly created frame. */
+  if (FRAMEP (FRAME_TTY (f)->top_frame)
+      && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
+    XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */
+
+  FRAME_TTY (f)->top_frame = frame;
+
   if (!noninteractive)
     init_frame_faces (f);
 
   if (!noninteractive)
     init_frame_faces (f);
 
@@ -683,17 +684,10 @@ affects all frames on the same terminal device.  */)
     abort ();
 #else /* not MSDOS */
 
     abort ();
 #else /* not MSDOS */
 
-#if 0
-  /* This can happen for multi-tty when using both terminal frames and
-     Carbon frames. */
-  if (sf->output_method != output_mac)
-    error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
-#else
 #if 0                           /* This should work now! */
   if (sf->output_method != output_termcap)
     error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
 #endif
 #if 0                           /* This should work now! */
   if (sf->output_method != output_termcap)
     error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
 #endif
-#endif
 #endif /* not MSDOS */
 
   {
 #endif /* not MSDOS */
 
   {
@@ -705,6 +699,13 @@ affects all frames on the same terminal device.  */)
         terminal = XCDR (terminal);
         t = get_terminal (terminal, 1);
       }
         terminal = XCDR (terminal);
         t = get_terminal (terminal, 1);
       }
+#ifdef MSDOS
+    if (t && t != the_only_display_info.terminal)
+      /* msdos.c assumes a single tty_display_info object.  */
+      error ("Multiple terminals are not supported on this platform");
+    if (!t)
+      t = the_only_display_info.terminal;
+#endif
   }
 
   if (!t)
   }
 
   if (!t)
@@ -783,11 +784,13 @@ affects all frames on the same terminal device.  */)
 
    FOR_DELETION non-zero means that the selected frame is being
    deleted, which includes the possibility that the frame's terminal
 
    FOR_DELETION non-zero means that the selected frame is being
    deleted, which includes the possibility that the frame's terminal
-   is dead.  */
+   is dead.
+
+   The value of NORECORD is passed as argument to Fselect_window.  */
 
 Lisp_Object
 
 Lisp_Object
-do_switch_frame (frame, track, for_deletion)
-     Lisp_Object frame;
+do_switch_frame (frame, track, for_deletion, norecord)
+     Lisp_Object frame, norecord;
      int track, for_deletion;
 {
   struct frame *sf = SELECTED_FRAME ();
      int track, for_deletion;
 {
   struct frame *sf = SELECTED_FRAME ();
@@ -857,11 +860,11 @@ do_switch_frame (frame, track, for_deletion)
   if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
     resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
 
   if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
     resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
 
-  if (FRAME_TERMCAP_P (XFRAME (selected_frame))
-      && FRAME_TERMCAP_P (XFRAME (frame))
-      && FRAME_TTY (XFRAME (selected_frame)) == FRAME_TTY (XFRAME (frame)))
+  if (FRAME_TERMCAP_P (XFRAME (frame)) || FRAME_MSDOS_P (XFRAME (frame)))
     {
     {
-      XFRAME (selected_frame)->async_visible = 2; /* obscured */
+      if (FRAMEP (FRAME_TTY (XFRAME (frame))->top_frame))
+       /* Mark previously displayed frame as now obscured.  */
+       XFRAME (FRAME_TTY (XFRAME (frame))->top_frame)->async_visible = 2;
       XFRAME (frame)->async_visible = 1;
       FRAME_TTY (XFRAME (frame))->top_frame = frame;
     }
       XFRAME (frame)->async_visible = 1;
       FRAME_TTY (XFRAME (frame))->top_frame = frame;
     }
@@ -870,24 +873,13 @@ do_switch_frame (frame, track, for_deletion)
   if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
     last_nonminibuf_frame = XFRAME (selected_frame);
 
   if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
     last_nonminibuf_frame = XFRAME (selected_frame);
 
-  Fselect_window (XFRAME (frame)->selected_window, Qnil);
+  Fselect_window (XFRAME (frame)->selected_window, norecord);
 
 
-#ifndef WINDOWSNT
-  /* Make sure to switch the tty color mode to that of the newly
-     selected frame.  */
-  sf = SELECTED_FRAME ();
-  if (FRAME_TERMCAP_P (sf))
-    {
-      Lisp_Object color_mode_spec, color_mode;
-
-      color_mode_spec = assq_no_quit (Qtty_color_mode, sf->param_alist);
-      if (CONSP (color_mode_spec))
-       color_mode = XCDR (color_mode_spec);
-      else
-       color_mode = make_number (0);
-      set_tty_color_mode (sf, color_mode);
-    }
-#endif /* !WINDOWSNT */
+#ifdef NS_IMPL_COCOA
+  /* term gets no other notification of this */
+  if (for_deletion)
+    Fraise_frame(Qnil);
+#endif
 
   /* We want to make sure that the next event generates a frame-switch
      event to the appropriate frame.  This seems kludgy to me, but
 
   /* We want to make sure that the next event generates a frame-switch
      event to the appropriate frame.  This seems kludgy to me, but
@@ -900,21 +892,25 @@ do_switch_frame (frame, track, for_deletion)
   return frame;
 }
 
   return frame;
 }
 
-DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 1, "e",
-       doc: /* Select the frame FRAME.
+DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
+       doc: /* Select FRAME.
 Subsequent editing commands apply to its selected window.
 Subsequent editing commands apply to its selected window.
+Optional argument NORECORD means to neither change the order of
+recently selected windows nor the buffer list.
+
 The selection of FRAME lasts until the next time the user does
 The selection of FRAME lasts until the next time the user does
-something to select a different frame, or until the next time this
-function is called.  If you are using a window system, the previously
-selected frame may be restored as the selected frame after return to
-the command loop, because it still may have the window system's input
-focus.  On a text-only terminal, the next redisplay will display FRAME.
+something to select a different frame, or until the next time
+this function is called.  If you are using a window system, the
+previously selected frame may be restored as the selected frame
+after return to the command loop, because it still may have the
+window system's input focus.  On a text-only terminal, the next
+redisplay will display FRAME.
 
 This function returns FRAME, or nil if FRAME has been deleted.  */)
 
 This function returns FRAME, or nil if FRAME has been deleted.  */)
-  (frame)
-    Lisp_Object frame;
+     (frame, norecord)
+     Lisp_Object frame, norecord;
 {
 {
-  return do_switch_frame (frame, 1, 0);
+  return do_switch_frame (frame, 1, 0, norecord);
 }
 
 
 }
 
 
@@ -933,7 +929,7 @@ to that frame.  */)
   /* Preserve prefix arg that the command loop just cleared.  */
   current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
   call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
   /* Preserve prefix arg that the command loop just cleared.  */
   current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
   call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
-  return do_switch_frame (event, 0, 0);
+  return do_switch_frame (event, 0, 0, Qnil);
 }
 
 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
 }
 
 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
@@ -1008,8 +1004,8 @@ If omitted, FRAME defaults to the currently selected frame.  */)
 
 DEFUN ("frame-selected-window", Fframe_selected_window,
        Sframe_selected_window, 0, 1, 0,
 
 DEFUN ("frame-selected-window", Fframe_selected_window,
        Sframe_selected_window, 0, 1, 0,
-       doc: /* Return the selected window of frame object FRAME.
-If omitted, FRAME defaults to the currently selected frame.  */)
+       doc: /* Return the selected window of FRAME.
+FRAME defaults to the currently selected frame.  */)
      (frame)
      Lisp_Object frame;
 {
      (frame)
      Lisp_Object frame;
 {
@@ -1027,13 +1023,15 @@ If omitted, FRAME defaults to the currently selected frame.  */)
 }
 
 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
 }
 
 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
-       Sset_frame_selected_window, 2, 2, 0,
-       doc: /* Set the selected window of frame object FRAME to WINDOW.
-Return WINDOW.
-If FRAME is nil, the selected frame is used.
-If FRAME is the selected frame, this makes WINDOW the selected window.  */)
-     (frame, window)
-     Lisp_Object frame, window;
+       Sset_frame_selected_window, 2, 3, 0,
+       doc: /* Set selected window of FRAME to WINDOW.
+If FRAME is nil, use the selected frame.  If FRAME is the
+selected frame, this makes WINDOW the selected window.
+Optional argument NORECORD non-nil means to neither change the
+order of recently selected windows nor the buffer list.
+Return WINDOW.  */)
+     (frame, window, norecord)
+     Lisp_Object frame, window, norecord;
 {
   if (NILP (frame))
     frame = selected_frame;
 {
   if (NILP (frame))
     frame = selected_frame;
@@ -1045,7 +1043,7 @@ If FRAME is the selected frame, this makes WINDOW the selected window.  */)
     error ("In `set-frame-selected-window', WINDOW is not on FRAME");
 
   if (EQ (frame, selected_frame))
     error ("In `set-frame-selected-window', WINDOW is not on FRAME");
 
   if (EQ (frame, selected_frame))
-    return Fselect_window (window, Qnil);
+    return Fselect_window (window, norecord);
 
   return XFRAME (frame)->selected_window = window;
 }
 
   return XFRAME (frame)->selected_window = window;
 }
@@ -1322,6 +1320,8 @@ delete_frame_handler (Lisp_Object arg)
   return Qnil;
 }
 
   return Qnil;
 }
 
+extern Lisp_Object Qrun_hook_with_args;
+
 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
        doc: /* Delete FRAME, permanently eliminating it from use.
 If omitted, FRAME defaults to the selected frame.
 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
        doc: /* Delete FRAME, permanently eliminating it from use.
 If omitted, FRAME defaults to the selected frame.
@@ -1331,7 +1331,9 @@ but if the second optional argument FORCE is non-nil, you may do so.
 
 This function runs `delete-frame-functions' before actually deleting the
 frame, unless the frame is a tooltip.
 
 This function runs `delete-frame-functions' before actually deleting the
 frame, unless the frame is a tooltip.
-The functions are run with one arg, the frame to be deleted.  */)
+The functions are run with one arg, the frame to be deleted.
+But FORCE inhibits this too.  */)
+/* FORCE is non-nil when handling a disconnected terminal.  */
      (frame, force)
      Lisp_Object frame, force;
 {
      (frame, force)
      Lisp_Object frame, force;
 {
@@ -1382,31 +1384,36 @@ The functions are run with one arg, the frame to be deleted.  */)
              && EQ (frame,
                     WINDOW_FRAME (XWINDOW
                                   (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
              && EQ (frame,
                     WINDOW_FRAME (XWINDOW
                                   (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
-           error ("Attempt to delete a surrogate minibuffer frame");
+           {
+             /* If we MUST delete this frame, delete the other first.  */
+             if (!NILP (force))
+               Fdelete_frame (this, force);
+             else
+               error ("Attempt to delete a surrogate minibuffer frame");
+           }
        }
     }
 
        }
     }
 
-  /* Run `delete-frame-functions' unless frame is a tooltip.  */
-  if (!NILP (Vrun_hooks)
-      && NILP (Fframe_parameter (frame, intern ("tooltip"))))
-    {
-      Lisp_Object args[2];
-      struct gcpro gcpro1, gcpro2;
-
-      /* Don't let a rogue function in `delete-frame-functions'
-        prevent the frame deletion. */
-      GCPRO2 (args[0], args[1]);
-      args[0] = intern ("delete-frame-functions");
-      args[1] = frame;
-      internal_condition_case_2 (Frun_hook_with_args, 2, args,
-                                Qt, delete_frame_handler);
-      UNGCPRO;
-    }
+  /* Run `delete-frame-functions'
+     unless FORCE is `noelisp' or frame is a tooltip.
+     FORCE is set to `noelisp' when handling a disconnect from the terminal,
+     so we don't dare call Lisp code.  */
+  if (NILP (Vrun_hooks) || !NILP (Fframe_parameter (frame, intern ("tooltip"))))
+    ;
+  if (EQ (force, Qnoelisp))
+    pending_funcalls
+      = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
+              pending_funcalls);
+  else
+    safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
 
   /* The hook may sometimes (indirectly) cause the frame to be deleted.  */
   if (! FRAME_LIVE_P (f))
     return Qnil;
 
 
   /* The hook may sometimes (indirectly) cause the frame to be deleted.  */
   if (! FRAME_LIVE_P (f))
     return Qnil;
 
+  /* At this point, we are committed to deleting the frame.
+     There is no more chance for errors to prevent it.  */
+
   minibuffer_selected = EQ (minibuf_window, selected_window);
 
   /* Don't let the frame remain selected.  */
   minibuffer_selected = EQ (minibuf_window, selected_window);
 
   /* Don't let the frame remain selected.  */
@@ -1427,7 +1434,7 @@ The functions are run with one arg, the frame to be deleted.  */)
            }
        }
 
            }
        }
 
-      do_switch_frame (frame1, 0, 1);
+      do_switch_frame (frame1, 0, 1, Qnil);
       sf = SELECTED_FRAME ();
     }
 
       sf = SELECTED_FRAME ();
     }
 
@@ -1453,10 +1460,6 @@ The functions are run with one arg, the frame to be deleted.  */)
   if (FRAME_X_P (f))
     x_clear_frame_selections (f);
 #endif
   if (FRAME_X_P (f))
     x_clear_frame_selections (f);
 #endif
-#ifdef MAC_OS
-  if (FRAME_MAC_P (f))
-    x_clear_frame_selections (f);
-#endif
 
   /* Free glyphs.
      This function must be called before the window tree of the
 
   /* Free glyphs.
      This function must be called before the window tree of the
@@ -1464,6 +1467,11 @@ The functions are run with one arg, the frame to be deleted.  */)
      memory. */
   free_glyphs (f);
 
      memory. */
   free_glyphs (f);
 
+#ifdef HAVE_WINDOW_SYSTEM
+  /* Give chance to each font driver to free a frame specific data.  */
+  font_update_drivers (f, Qnil);
+#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));
   /* 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));
@@ -1472,20 +1480,16 @@ The functions are run with one arg, the frame to be deleted.  */)
   Vframe_list = Fdelq (frame, Vframe_list);
   FRAME_SET_VISIBLE (f, 0);
 
   Vframe_list = Fdelq (frame, Vframe_list);
   FRAME_SET_VISIBLE (f, 0);
 
-  if (f->namebuf)
-    xfree (f->namebuf);
-  if (f->decode_mode_spec_buffer)
-    xfree (f->decode_mode_spec_buffer);
-  if (FRAME_INSERT_COST (f))
-    xfree (FRAME_INSERT_COST (f));
-  if (FRAME_DELETEN_COST (f))
-    xfree (FRAME_DELETEN_COST (f));
-  if (FRAME_INSERTN_COST (f))
-    xfree (FRAME_INSERTN_COST (f));
-  if (FRAME_DELETE_COST (f))
-    xfree (FRAME_DELETE_COST (f));
-  if (FRAME_MESSAGE_BUF (f))
-    xfree (FRAME_MESSAGE_BUF (f));
+  f->menu_bar_vector = Qnil;
+
+  free_font_driver_list (f);
+  xfree (f->namebuf);
+  xfree (f->decode_mode_spec_buffer);
+  xfree (FRAME_INSERT_COST (f));
+  xfree (FRAME_DELETEN_COST (f));
+  xfree (FRAME_INSERTN_COST (f));
+  xfree (FRAME_DELETE_COST (f));
+  xfree (FRAME_MESSAGE_BUF (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 terminal
 
   /* 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 terminal
@@ -1507,16 +1511,14 @@ The functions are run with one arg, the frame to be deleted.  */)
     terminal->reference_count--;
     if (terminal->reference_count == 0)
       {
     terminal->reference_count--;
     if (terminal->reference_count == 0)
       {
+       Lisp_Object tmp;
+       XSETTERMINAL (tmp, terminal);
+
         kb = NULL;
         kb = NULL;
-        if (terminal->delete_terminal_hook)
-          (*terminal->delete_terminal_hook) (terminal);
-        else
-          delete_terminal (terminal);
+       Fdelete_terminal (tmp, NILP (force) ? Qt : force);
       }
       }
-#ifdef MULTI_KBOARD
     else
       kb = terminal->kboard;
     else
       kb = terminal->kboard;
-#endif
   }
 
   /* If we've deleted the last_nonminibuf_frame, then try to find
   }
 
   /* If we've deleted the last_nonminibuf_frame, then try to find
@@ -1748,13 +1750,13 @@ before calling this function on it, like this.
 #if defined (MSDOS) && defined (HAVE_MOUSE)
   if (FRAME_MSDOS_P (XFRAME (frame)))
     {
 #if defined (MSDOS) && defined (HAVE_MOUSE)
   if (FRAME_MSDOS_P (XFRAME (frame)))
     {
-      Fselect_frame (frame);
+      Fselect_frame (frame, Qnil);
       mouse_moveto (XINT (x), XINT (y));
     }
 #else
 #ifdef HAVE_GPM
     {
       mouse_moveto (XINT (x), XINT (y));
     }
 #else
 #ifdef HAVE_GPM
     {
-      Fselect_frame (frame);
+      Fselect_frame (frame, Qnil);
       term_mouse_moveto (XINT (x), XINT (y));
     }
 #endif
       term_mouse_moveto (XINT (x), XINT (y));
     }
 #endif
@@ -1790,13 +1792,13 @@ before calling this function on it, like this.
 #if defined (MSDOS) && defined (HAVE_MOUSE)
   if (FRAME_MSDOS_P (XFRAME (frame)))
     {
 #if defined (MSDOS) && defined (HAVE_MOUSE)
   if (FRAME_MSDOS_P (XFRAME (frame)))
     {
-      Fselect_frame (frame);
+      Fselect_frame (frame, Qnil);
       mouse_moveto (XINT (x), XINT (y));
     }
 #else
 #ifdef HAVE_GPM
     {
       mouse_moveto (XINT (x), XINT (y));
     }
 #else
 #ifdef HAVE_GPM
     {
-      Fselect_frame (frame);
+      Fselect_frame (frame, Qnil);
       term_mouse_moveto (XINT (x), XINT (y));
     }
 #endif
       term_mouse_moveto (XINT (x), XINT (y));
     }
 #endif
@@ -1880,7 +1882,7 @@ but if the second optional argument FORCE is non-nil, you may do so.  */)
 #if 0 /* This isn't logically necessary, and it can do GC.  */
   /* Don't let the frame remain selected.  */
   if (EQ (frame, selected_frame))
 #if 0 /* This isn't logically necessary, and it can do GC.  */
   /* Don't let the frame remain selected.  */
   if (EQ (frame, selected_frame))
-    do_switch_frame (next_frame (frame, Qt), 0, 0)
+    do_switch_frame (next_frame (frame, Qt), 0, 0, Qnil)
 #endif
 
   /* Don't allow minibuf_window to remain on a deleted frame.  */
 #endif
 
   /* Don't allow minibuf_window to remain on a deleted frame.  */
@@ -1995,7 +1997,7 @@ DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
 If FRAME is invisible or iconified, make it visible.
 If you don't specify a frame, the selected frame is used.
 If Emacs is displaying on an ordinary terminal or some other device which
 If FRAME is invisible or iconified, make it visible.
 If you don't specify a frame, the selected frame is used.
 If Emacs is displaying on an ordinary terminal or some other device which
-doesn't support multiple overlapping frames, this function does nothing.  */)
+doesn't support multiple overlapping frames, this function selects FRAME.  */)
      (frame)
      Lisp_Object frame;
 {
      (frame)
      Lisp_Object frame;
 {
@@ -2007,8 +2009,12 @@ doesn't support multiple overlapping frames, this function does nothing.  */)
 
   f = XFRAME (frame);
 
 
   f = XFRAME (frame);
 
-  /* Do like the documentation says. */
-  Fmake_frame_visible (frame);
+  if (FRAME_TERMCAP_P (f))
+    /* On a text-only terminal select FRAME.  */
+    Fselect_frame (frame, Qnil);
+  else
+    /* Do like the documentation says. */
+    Fmake_frame_visible (frame);
 
   if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
     (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
 
   if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
     (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
@@ -2183,7 +2189,7 @@ store_in_alist (alistptr, prop, val)
 static int
 frame_name_fnn_p (str, len)
      char *str;
 static int
 frame_name_fnn_p (str, len)
      char *str;
-     int len;
+     EMACS_INT len;
 {
   if (len > 1 && str[0] == 'F')
     {
 {
   if (len > 1 && str[0] == 'F')
     {
@@ -2276,11 +2282,13 @@ store_frame_param (f, prop, val)
     }
 
 #ifndef WINDOWSNT
     }
 
 #ifndef WINDOWSNT
-  /* The tty color mode needs to be set before the frame's parameter
-     alist is updated with the new value, because set_tty_color_mode
-     wants to look at the old mode.  */
-  if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode))
-    set_tty_color_mode (f, val);
+  /* The tty color needed to be set before the frame's parameter
+     alist was updated with the new value.  This is not true any more,
+     but we still do this test early on.  */
+  if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
+      && f == FRAME_TTY (f)->previous_frame)
+    /* Force redisplay of this tty.  */
+    FRAME_TTY (f)->previous_frame = NULL;
 #endif
 
   /* Update the frame parameter alist.  */
 #endif
 
   /* Update the frame parameter alist.  */
@@ -2507,7 +2515,9 @@ so that `frame-parameters' will return them.
 
 The value of frame parameter FOO can also be accessed
 as a frame-local binding for the variable FOO, if you have
 
 The value of frame parameter FOO can also be accessed
 as a frame-local binding for the variable FOO, if you have
-enabled such bindings for that variable with `make-variable-frame-local'.  */)
+enabled such bindings for that variable with `make-variable-frame-local'.
+Note that this functionality is obsolete as of Emacs 22.2, and its
+use is not recommended.  Explicitly check for a frame-parameter instead.  */)
      (frame, alist)
      Lisp_Object frame, alist;
 {
      (frame, alist)
      Lisp_Object frame, alist;
 {
@@ -2542,11 +2552,11 @@ enabled such bindings for that variable with `make-variable-frame-local'.  */)
       /* Extract parm names and values into those vectors.  */
 
       i = 0;
       /* Extract parm names and values into those vectors.  */
 
       i = 0;
-      for (tail = alist; CONSP (tail); tail = Fcdr (tail))
+      for (tail = alist; CONSP (tail); tail = XCDR (tail))
        {
          Lisp_Object elt;
 
        {
          Lisp_Object elt;
 
-         elt = Fcar (tail);
+         elt = XCAR (tail);
          parms[i] = Fcar (elt);
          values[i] = Fcdr (elt);
          i++;
          parms[i] = Fcar (elt);
          values[i] = Fcdr (elt);
          i++;
@@ -2824,6 +2834,8 @@ static struct frame_parm_table frame_parms[] =
   {"right-fringe",             &Qright_fringe},
   {"wait-for-wm",              &Qwait_for_wm},
   {"fullscreen",                &Qfullscreen},
   {"right-fringe",             &Qright_fringe},
   {"wait-for-wm",              &Qwait_for_wm},
   {"fullscreen",                &Qfullscreen},
+  {"font-backend",             &Qfont_backend},
+  {"alpha",                    &Qalpha}
 };
 
 #ifdef HAVE_WINDOW_SYSTEM
 };
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -2847,6 +2859,7 @@ x_fullscreen_adjust (f, width, height, top_pos, left_pos)
 {
   int newwidth = FRAME_COLS (f);
   int newheight = FRAME_LINES (f);
 {
   int newwidth = FRAME_COLS (f);
   int newheight = FRAME_LINES (f);
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
   *top_pos = f->top_pos;
   *left_pos = f->left_pos;
 
   *top_pos = f->top_pos;
   *left_pos = f->left_pos;
@@ -2855,7 +2868,7 @@ x_fullscreen_adjust (f, width, height, top_pos, left_pos)
     {
       int ph;
 
     {
       int ph;
 
-      ph = FRAME_X_DISPLAY_INFO (f)->height;
+      ph = x_display_pixel_height (dpyinfo);
       newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
       ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
       newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
       newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
       ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
       newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
@@ -2866,7 +2879,7 @@ x_fullscreen_adjust (f, width, height, top_pos, left_pos)
     {
       int pw;
 
     {
       int pw;
 
-      pw = FRAME_X_DISPLAY_INFO (f)->width;
+      pw = x_display_pixel_width (dpyinfo);
       newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
       pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
       newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
       newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
       pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
       newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
@@ -2922,11 +2935,11 @@ x_set_frame_parameters (f, alist)
   /* Extract parm names and values into those vectors.  */
 
   i = 0;
   /* Extract parm names and values into those vectors.  */
 
   i = 0;
-  for (tail = alist; CONSP (tail); tail = Fcdr (tail))
+  for (tail = alist; CONSP (tail); tail = XCDR (tail))
     {
       Lisp_Object elt;
 
     {
       Lisp_Object elt;
 
-      elt = Fcar (tail);
+      elt = XCAR (tail);
       parms[i] = Fcar (elt);
       values[i] = Fcdr (elt);
       i++;
       parms[i] = Fcar (elt);
       values[i] = Fcdr (elt);
       i++;
@@ -2964,20 +2977,11 @@ x_set_frame_parameters (f, alist)
           || EQ (prop, Qfullscreen))
        {
          register Lisp_Object param_index, old_value;
           || EQ (prop, Qfullscreen))
        {
          register Lisp_Object param_index, old_value;
-         int count = SPECPDL_INDEX ();
 
          old_value = get_frame_param (f, prop);
          fullscreen_is_being_set |= EQ (prop, Qfullscreen);
 
          old_value = get_frame_param (f, prop);
          fullscreen_is_being_set |= EQ (prop, Qfullscreen);
-
          if (NILP (Fequal (val, old_value)))
            {
          if (NILP (Fequal (val, old_value)))
            {
-             /* For :font attributes, the frame_parm_handler
-                x_set_font calls `face-set-after-frame-default'.
-                Unless we bind inhibit-face-set-after-frame-default
-                here, this would reset the :font attribute that we
-                just applied to the default value for new faces.  */
-             specbind (Qinhibit_face_set_after_frame_default, Qt);
-
              store_frame_param (f, prop, val);
 
              param_index = Fget (prop, Qx_frame_parameter);
              store_frame_param (f, prop, val);
 
              param_index = Fget (prop, Qx_frame_parameter);
@@ -2986,7 +2990,6 @@ x_set_frame_parameters (f, alist)
                      < sizeof (frame_parms)/sizeof (frame_parms[0]))
                   && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
                 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
                      < sizeof (frame_parms)/sizeof (frame_parms[0]))
                   && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
                 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
-             unbind_to (count, Qnil);
            }
        }
     }
            }
        }
     }
@@ -3333,60 +3336,125 @@ x_set_font (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  Lisp_Object result;
-  Lisp_Object fontset_name;
   Lisp_Object frame;
   Lisp_Object frame;
-  int old_fontset = FRAME_FONTSET(f);
-
-  CHECK_STRING (arg);
+  int fontset = -1;
+  Lisp_Object font_object;
 
 
-  fontset_name = Fquery_fontset (arg, Qnil);
+  /* Set the frame parameter back to the old value because we may
+     fail to use ARG as the new parameter value.  */
+  store_frame_param (f, Qfont, oldval);
 
 
-  BLOCK_INPUT;
-  result = (STRINGP (fontset_name)
-            ? x_new_fontset (f, SDATA (fontset_name))
-            : x_new_font (f, SDATA (arg)));
-  UNBLOCK_INPUT;
-
-  if (EQ (result, Qnil))
-    error ("Font `%s' is not defined", SDATA (arg));
-  else if (EQ (result, Qt))
-    error ("The characters of the given font have varying widths");
-  else if (STRINGP (result))
+  /* ARG is a fontset name, a font name, or a font object.
+     In the last case, this function never fail.  */
+  if (STRINGP (arg))
     {
     {
-      set_default_ascii_font (result);
-      if (STRINGP (fontset_name))
+      fontset = fs_query_fontset (arg, 0);
+      if (fontset < 0)
        {
        {
-         /* Fontset names are built from ASCII font names, so the
-            names may be equal despite there was a change.  */
-         if (old_fontset == FRAME_FONTSET (f))
-           return;
+         font_object = font_open_by_name (f, SDATA (arg));
+         if (NILP (font_object))
+           error ("Font `%s' is not defined", SDATA (arg));
+         arg = AREF (font_object, FONT_NAME_INDEX);
        }
        }
-      else if (!NILP (Fequal (result, oldval)))
-        return;
-
-      /* Recalculate toolbar height.  */
-      f->n_tool_bar_rows = 0;
-      /* Ensure we redraw it.  */
-      clear_current_matrices (f);
+      else if (fontset > 0)
+       {
+         Lisp_Object ascii_font = fontset_ascii (fontset);
 
 
-      store_frame_param (f, Qfont, result);
-      recompute_basic_faces (f);
+         font_object = font_open_by_name (f, SDATA (ascii_font));
+         if (NILP (font_object))
+           error ("Font `%s' is not defined", SDATA (arg));
+         arg = fontset_name (fontset);
+       }
+      else
+       error ("The default fontset can't be used for a frame font");
+    }
+  else if (FONT_OBJECT_P (arg))
+    {
+      font_object = arg;
+      /* This is store the XLFD font name in the frame parameter for
+        backward compatiblity.  We should store the font-object
+        itself in the future.  */
+      arg = AREF (font_object, FONT_NAME_INDEX);
     }
   else
     }
   else
-    abort ();
+    signal_error ("Invalid font", arg);
+
+  if (! NILP (Fequal (font_object, oldval)))
+    return;
+  x_new_font (f, font_object, fontset);
+  store_frame_param (f, Qfont, arg);
+  /* Recalculate toolbar height.  */
+  f->n_tool_bar_rows = 0;
+  /* Ensure we redraw it.  */
+  clear_current_matrices (f);
+
+  recompute_basic_faces (f);
 
   do_pending_window_change (0);
 
 
   do_pending_window_change (0);
 
-  /* Don't call `face-set-after-frame-default' when faces haven't been
-     initialized yet.  This is the case when called from
-     Fx_create_frame.  In that case, the X widget or window doesn't
-     exist either, and we can end up in x_report_frame_params with a
-     null widget which gives a segfault.  */
-  if (FRAME_FACE_CACHE (f))
+  /* We used to call face-set-after-frame-default here, but it leads to
+     recursive calls (since that function can set the `default' face's
+     font which in turns changes the frame's `font' parameter).
+     Also I don't know what this call is meant to do, but it seems the
+     wrong way to do it anyway (it does a lot more work than what seems
+     reasonable in response to a change to `font').  */
+}
+
+
+void
+x_set_font_backend (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  if (! NILP (new_value)
+      && !CONSP (new_value))
+    {
+      char *p0, *p1;
+
+      CHECK_STRING (new_value);
+      p0 = p1 = SDATA (new_value);
+      new_value = Qnil;
+      while (*p0)
+       {
+         while (*p1 && ! isspace (*p1) && *p1 != ',') p1++;
+         if (p0 < p1)
+           new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
+                              new_value);
+         if (*p1)
+           {
+             int c;
+
+             while ((c = *++p1) && isspace (c));
+           }
+         p0 = p1;
+       }
+      new_value = Fnreverse (new_value);
+    }
+
+  if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
+    return;
+
+  if (FRAME_FONT (f))
+    free_all_realized_faces (Qnil);
+
+  new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
+  if (NILP (new_value))
+    {
+      if (NILP (old_value))
+       error ("No font backend available");
+      font_update_drivers (f, old_value);
+      error ("None of specified font backends are available");
+    }
+  store_frame_param (f, Qfont_backend, new_value);
+
+  if (FRAME_FONT (f))
     {
     {
+      Lisp_Object frame;
+
       XSETFRAME (frame, f);
       XSETFRAME (frame, f);
-      call1 (Qface_set_after_frame_default, frame);
+      x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
+      ++face_change_count;
+      ++windows_or_buffers_changed;
     }
 }
 
     }
 }
 
@@ -3568,6 +3636,60 @@ x_icon_type (f)
     return Qnil;
 }
 
     return Qnil;
 }
 
+void
+x_set_alpha (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  double alpha = 1.0;
+  double newval[2];
+  int i, ialpha;
+  Lisp_Object item;
+
+  for (i = 0; i < 2; i++)
+    {
+      newval[i] = 1.0;
+      if (CONSP (arg))
+        {
+          item = CAR (arg);
+          arg  = CDR (arg);
+        }
+      else
+        item = arg;
+
+      if (NILP (item))
+       alpha = - 1.0;
+      else if (FLOATP (item))
+       {
+         alpha = XFLOAT_DATA (item);
+         if (alpha < 0.0 || 1.0 < alpha)
+           args_out_of_range (make_float (0.0), make_float (1.0));
+       }
+      else if (INTEGERP (item))
+       {
+         ialpha = XINT (item);
+         if (ialpha < 0 || 100 < ialpha)
+           args_out_of_range (make_number (0), make_number (100));
+         else
+           alpha = ialpha / 100.0;
+       }
+      else
+       wrong_type_argument (Qnumberp, item);
+      newval[i] = alpha;
+    }
+
+  for (i = 0; i < 2; i++)
+    f->alpha[i] = newval[i];
+
+#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
+  BLOCK_INPUT;
+  x_set_frame_alpha (f);
+  UNBLOCK_INPUT;
+#endif
+
+  return;
+}
+
 \f
 /* Subroutines of creating an X frame.  */
 
 \f
 /* Subroutines of creating an X frame.  */
 
@@ -3836,6 +3958,9 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
            case RES_TYPE_BOOLEAN:
              tem = Fdowncase (tem);
              if (!strcmp (SDATA (tem), "on")
            case RES_TYPE_BOOLEAN:
              tem = Fdowncase (tem);
              if (!strcmp (SDATA (tem), "on")
+#ifdef HAVE_NS
+                  || !strcmp(SDATA(tem), "yes")
+#endif
                  || !strcmp (SDATA (tem), "true"))
                return Qt;
              else
                  || !strcmp (SDATA (tem), "true"))
                return Qt;
              else
@@ -3851,9 +3976,15 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
                Lisp_Object lower;
                lower = Fdowncase (tem);
                if (!strcmp (SDATA (lower), "on")
                Lisp_Object lower;
                lower = Fdowncase (tem);
                if (!strcmp (SDATA (lower), "on")
+#ifdef HAVE_NS
+                    || !strcmp(SDATA(lower), "yes")
+#endif
                    || !strcmp (SDATA (lower), "true"))
                  return Qt;
                else if (!strcmp (SDATA (lower), "off")
                    || !strcmp (SDATA (lower), "true"))
                  return Qt;
                else if (!strcmp (SDATA (lower), "off")
+#ifdef HAVE_NS
+                      || !strcmp(SDATA(lower), "no")
+#endif
                      || !strcmp (SDATA (lower), "false"))
                  return Qnil;
                else
                      || !strcmp (SDATA (lower), "false"))
                  return Qnil;
                else
@@ -3931,6 +4062,25 @@ x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
 
 
 \f
 
 
 \f
+#ifdef HAVE_NS
+
+/* We used to define x-parse-geometry directly in ns-win.el, but that
+   confused make-docfile: the documentation string in ns-win.el was
+   used for x-parse-geometry even in non-NS builds..  */
+
+DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
+       doc: /* Parse a Nextstep-style geometry string STRING.
+Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
+The properties returned may include `top', `left', `height', and `width'.
+This works by calling `ns-parse-geometry'.  */)
+     (string)
+     Lisp_Object string;
+{
+  call1 (Qns_parse_geometry, string);
+}
+
+#else /* !HAVE_NS */
+
 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
        doc: /* Parse an X-style geometry string STRING.
 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
        doc: /* Parse an X-style geometry string STRING.
 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
@@ -3949,12 +4099,6 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.  */)
 
   geometry = XParseGeometry ((char *) SDATA (string),
                             &x, &y, &width, &height);
 
   geometry = XParseGeometry ((char *) SDATA (string),
                             &x, &y, &width, &height);
-
-#if 0
-  if (!!(geometry & XValue) != !!(geometry & YValue))
-    error ("Must specify both x and y position, or neither");
-#endif
-
   result = Qnil;
   if (geometry & XValue)
     {
   result = Qnil;
   if (geometry & XValue)
     {
@@ -3989,6 +4133,8 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.  */)
 
   return result;
 }
 
   return result;
 }
+#endif /* HAVE_NS */
+
 
 /* Calculate the desired size and position of frame F.
    Return the flags saying which aspects were specified.
 
 /* Calculate the desired size and position of frame F.
    Return the flags saying which aspects were specified.
@@ -4253,6 +4399,8 @@ syms_of_frame ()
   staticpro (&Qpc);
   Qmac = intern ("mac");
   staticpro (&Qmac);
   staticpro (&Qpc);
   Qmac = intern ("mac");
   staticpro (&Qmac);
+  Qns = intern ("ns");
+  staticpro (&Qns);
   Qvisible = intern ("visible");
   staticpro (&Qvisible);
   Qbuffer_predicate = intern ("buffer-predicate");
   Qvisible = intern ("visible");
   staticpro (&Qvisible);
   Qbuffer_predicate = intern ("buffer-predicate");
@@ -4265,6 +4413,8 @@ syms_of_frame ()
   staticpro (&Qdisplay_type);
   Qbackground_mode = intern ("background-mode");
   staticpro (&Qbackground_mode);
   staticpro (&Qdisplay_type);
   Qbackground_mode = intern ("background-mode");
   staticpro (&Qbackground_mode);
+  Qnoelisp = intern ("noelisp");
+  staticpro (&Qnoelisp);
   Qtty_color_mode = intern ("tty-color-mode");
   staticpro (&Qtty_color_mode);
   Qtty = intern ("tty");
   Qtty_color_mode = intern ("tty-color-mode");
   staticpro (&Qtty_color_mode);
   Qtty = intern ("tty");
@@ -4275,10 +4425,6 @@ syms_of_frame ()
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
 
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
 
-  Qinhibit_face_set_after_frame_default
-    = intern ("inhibit-face-set-after-frame-default");
-  staticpro (&Qinhibit_face_set_after_frame_default);
-
   Qfullwidth = intern ("fullwidth");
   staticpro (&Qfullwidth);
   Qfullheight = intern ("fullheight");
   Qfullwidth = intern ("fullwidth");
   staticpro (&Qfullwidth);
   Qfullheight = intern ("fullheight");
@@ -4296,6 +4442,11 @@ syms_of_frame ()
   Qterminal_live_p = intern ("terminal-live-p");
   staticpro (&Qterminal_live_p);
 
   Qterminal_live_p = intern ("terminal-live-p");
   staticpro (&Qterminal_live_p);
 
+#ifdef HAVE_NS
+  Qns_parse_geometry = intern ("ns-parse-geometry");
+  staticpro (&Qns_parse_geometry);
+#endif
+
   {
     int i;
 
   {
     int i;
 
@@ -4335,6 +4486,13 @@ Setting this variable permanently is not a reasonable thing to do,
 but binding this variable locally around a call to `x-get-resource'
 is a reasonable practice.  See also the variable `x-resource-name'.  */);
   Vx_resource_class = build_string (EMACS_CLASS);
 but binding this variable locally around a call to `x-get-resource'
 is a reasonable practice.  See also the variable `x-resource-name'.  */);
   Vx_resource_class = build_string (EMACS_CLASS);
+
+  DEFVAR_LISP ("frame-alpha-lower-limit", &Vframe_alpha_lower_limit,
+    doc: /* The lower limit of the frame opacity (alpha transparency).
+The value should range from 0 (invisible) to 100 (completely opaque).
+You can also use a floating number between 0.0 and 1.0.
+The default is 20.  */);
+  Vframe_alpha_lower_limit = make_number (20);
 #endif
 
   DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
 #endif
 
   DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
@@ -4355,8 +4513,8 @@ Setting this variable does not affect existing frames, only new ones.  */);
   DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
               doc: /* Default position of scroll bars on this window-system.  */);
 #ifdef HAVE_WINDOW_SYSTEM
   DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
               doc: /* Default position of scroll bars on this window-system.  */);
 #ifdef HAVE_WINDOW_SYSTEM
-#if defined(HAVE_NTGUI) || defined(MAC_OS)
-  /* MS-Windows has scroll bars on the right by default.  */
+#if defined(HAVE_NTGUI) || defined(NS_IMPL_COCOA)
+  /* MS-Windows and Mac OS X have scroll bars on the right by default.  */
   Vdefault_frame_scroll_bars = Qright;
 #else
   Vdefault_frame_scroll_bars = Qleft;
   Vdefault_frame_scroll_bars = Qright;
 #else
   Vdefault_frame_scroll_bars = Qleft;
@@ -4393,13 +4551,13 @@ when the mouse is over clickable text.  */);
 The functions are run with one arg, the frame to be deleted.
 See `delete-frame'.
 
 The functions are run with one arg, the frame to be deleted.
 See `delete-frame'.
 
-Note that functions in this list may be called twice on the same
-frame.  In the second invocation, the frame is already deleted, and
-the function should do nothing.  (You can use `frame-live-p' to check
-for this.)  This wrinkle happens when an earlier function in
-`delete-frame-functions' (indirectly) calls `delete-frame'
-recursively.  */);
+Note that functions in this list may be called just before the frame is
+actually deleted, or some time later (or even both when an earlier function
+in `delete-frame-functions' (indirectly) calls `delete-frame'
+recursively).  */);
   Vdelete_frame_functions = Qnil;
   Vdelete_frame_functions = Qnil;
+  Qdelete_frame_functions = intern ("delete-frame-functions");
+  staticpro (&Qdelete_frame_functions);
 
   DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
                 doc: /* Minibufferless frames use this frame's minibuffer.
 
   DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
                 doc: /* Minibufferless frames use this frame's minibuffer.
@@ -4422,7 +4580,7 @@ You should set this variable to tell Emacs how your window manager
 handles focus, since there is no way in general for Emacs to find out
 automatically.  */);
 #ifdef HAVE_WINDOW_SYSTEM
 handles focus, since there is no way in general for Emacs to find out
 automatically.  */);
 #ifdef HAVE_WINDOW_SYSTEM
-#if defined(HAVE_NTGUI) || defined(MAC_OS)
+#if defined(HAVE_NTGUI) || defined(HAVE_NS)
   focus_follows_mouse = 0;
 #else
   focus_follows_mouse = 1;
   focus_follows_mouse = 0;
 #else
   focus_follows_mouse = 1;