*** 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.
 
-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
-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
@@ -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
-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 <ctype.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 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"
-#ifdef HAVE_WINDOW_SYSTEM
-#include "fontset.h"
-#endif
 #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"
@@ -63,15 +63,24 @@ Lisp_Object Vx_resource_name;
 
 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;
-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 Qnoelisp;
 
 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 Qfont_backend;
+Lisp_Object Qalpha;
 
-Lisp_Object Qinhibit_face_set_after_frame_default;
 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 Vdelete_frame_functions;
+static Lisp_Object Vdelete_frame_functions, Qdelete_frame_functions;
 
 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,
-`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)
@@ -218,6 +228,8 @@ See also `frame-live-p'.  */)
       return Qpc;
     case output_mac:
       return Qmac;
+    case output_ns:
+      return Qns;
     default:
       abort ();
     }
@@ -326,6 +338,8 @@ make_frame (mini_p)
 #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)
@@ -423,11 +437,9 @@ make_frame_without_minibuffer (mini_window, kb, display)
   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");
-#endif
 
   /* 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;
 
+#ifdef CANNOT_DUMP
+  if (!noninteractive)
+    init_frame_faces (f);
+#endif
+
   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->terminal = terminal;
+  f->terminal->reference_count++;
 #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))
-    {
-      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;
-    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;
-
-    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
@@ -619,6 +610,16 @@ make_terminal_frame (struct terminal *terminal)
 #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);
 
@@ -683,17 +684,10 @@ affects all frames on the same terminal device.  */)
     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
-#endif
 #endif /* not MSDOS */
 
   {
@@ -705,6 +699,13 @@ affects all frames on the same terminal device.  */)
         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)
@@ -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
-   is dead.  */
+   is dead.
+
+   The value of NORECORD is passed as argument to Fselect_window.  */
 
 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 ();
@@ -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 (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;
     }
@@ -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);
 
-  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
@@ -900,21 +892,25 @@ do_switch_frame (frame, track, for_deletion)
   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.
+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
-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.  */)
-  (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);
-  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,
@@ -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,
-       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;
 {
@@ -1027,13 +1023,15 @@ If omitted, FRAME defaults to the currently selected frame.  */)
 }
 
 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;
@@ -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))
-    return Fselect_window (window, Qnil);
+    return Fselect_window (window, norecord);
 
   return XFRAME (frame)->selected_window = window;
 }
@@ -1322,6 +1320,8 @@ delete_frame_handler (Lisp_Object arg)
   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.
@@ -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.
-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;
 {
@@ -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))))))
-           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;
 
+  /* 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.  */
@@ -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 ();
     }
 
@@ -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
-#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
@@ -1464,6 +1467,11 @@ The functions are run with one arg, the frame to be deleted.  */)
      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));
@@ -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);
 
-  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
@@ -1507,16 +1511,14 @@ The functions are run with one arg, the frame to be deleted.  */)
     terminal->reference_count--;
     if (terminal->reference_count == 0)
       {
+       Lisp_Object tmp;
+       XSETTERMINAL (tmp, terminal);
+
         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;
-#endif
   }
 
   /* 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)))
     {
-      Fselect_frame (frame);
+      Fselect_frame (frame, Qnil);
       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
@@ -1790,13 +1792,13 @@ before calling this function on it, like this.
 #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
     {
-      Fselect_frame (frame);
+      Fselect_frame (frame, Qnil);
       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))
-    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.  */
@@ -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
-doesn't support multiple overlapping frames, this function does nothing.  */)
+doesn't support multiple overlapping frames, this function selects FRAME.  */)
      (frame)
      Lisp_Object frame;
 {
@@ -2007,8 +2009,12 @@ doesn't support multiple overlapping frames, this function does nothing.  */)
 
   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);
@@ -2183,7 +2189,7 @@ store_in_alist (alistptr, prop, val)
 static int
 frame_name_fnn_p (str, len)
      char *str;
-     int len;
+     EMACS_INT len;
 {
   if (len > 1 && str[0] == 'F')
     {
@@ -2276,11 +2282,13 @@ store_frame_param (f, prop, val)
     }
 
 #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.  */
@@ -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
-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;
 {
@@ -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;
-      for (tail = alist; CONSP (tail); tail = Fcdr (tail))
+      for (tail = alist; CONSP (tail); tail = XCDR (tail))
        {
          Lisp_Object elt;
 
-         elt = Fcar (tail);
+         elt = XCAR (tail);
          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},
+  {"font-backend",             &Qfont_backend},
+  {"alpha",                    &Qalpha}
 };
 
 #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);
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
   *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;
 
-      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);
@@ -2866,7 +2879,7 @@ x_fullscreen_adjust (f, width, height, top_pos, left_pos)
     {
       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);
@@ -2922,11 +2935,11 @@ x_set_frame_parameters (f, alist)
   /* 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;
 
-      elt = Fcar (tail);
+      elt = XCAR (tail);
       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;
-         int count = SPECPDL_INDEX ();
 
          old_value = get_frame_param (f, prop);
          fullscreen_is_being_set |= EQ (prop, Qfullscreen);
-
          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);
@@ -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);
-             unbind_to (count, Qnil);
            }
        }
     }
@@ -3333,60 +3336,125 @@ x_set_font (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  Lisp_Object result;
-  Lisp_Object fontset_name;
   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
-    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);
 
-  /* 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);
-      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;
 }
 
+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.  */
 
@@ -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")
+#ifdef HAVE_NS
+                  || !strcmp(SDATA(tem), "yes")
+#endif
                  || !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")
+#ifdef HAVE_NS
+                    || !strcmp(SDATA(lower), "yes")
+#endif
                    || !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
@@ -3931,6 +4062,25 @@ x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
 
 
 \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) ... ).
@@ -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);
-
-#if 0
-  if (!!(geometry & XValue) != !!(geometry & YValue))
-    error ("Must specify both x and y position, or neither");
-#endif
-
   result = Qnil;
   if (geometry & XValue)
     {
@@ -3989,6 +4133,8 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.  */)
 
   return result;
 }
+#endif /* HAVE_NS */
+
 
 /* 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);
+  Qns = intern ("ns");
+  staticpro (&Qns);
   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);
+  Qnoelisp = intern ("noelisp");
+  staticpro (&Qnoelisp);
   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);
 
-  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");
@@ -4296,6 +4442,11 @@ syms_of_frame ()
   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;
 
@@ -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);
+
+  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,
@@ -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
-#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;
@@ -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'.
 
-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;
+  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.
@@ -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
-#if defined(HAVE_NTGUI) || defined(MAC_OS)
+#if defined(HAVE_NTGUI) || defined(HAVE_NS)
   focus_follows_mouse = 0;
 #else
   focus_follows_mouse = 1;