Make "xfree (NULL)" a no-op; remove useless if-before-xfree.
[bpt/emacs.git] / src / frame.c
index 091abfd..84a4e54 100644 (file)
@@ -1,13 +1,13 @@
 /* Generic frame functions.
    Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 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,15 +15,13 @@ 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 "lisp.h"
-#include "charset.h"
+#include "character.h"
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
@@ -38,14 +36,15 @@ Boston, MA 02110-1301, USA.  */
 #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,6 +62,10 @@ 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
 
 Lisp_Object Qframep, Qframe_live_p;
@@ -72,6 +75,7 @@ Lisp_Object Qx, Qw32, Qmac, Qpc;
 Lisp_Object Qvisible;
 Lisp_Object Qdisplay_type;
 Lisp_Object Qbackground_mode;
+Lisp_Object Qnoelisp;
 
 Lisp_Object Qx_frame_parameter;
 Lisp_Object Qx_resource_name;
@@ -103,18 +107,17 @@ Lisp_Object Qouter_window_id;
 #endif
 Lisp_Object Qparent_id;
 Lisp_Object Qtitle, Qname;
+Lisp_Object Qexplicit_name;
 Lisp_Object Qunsplittable;
 Lisp_Object Qmenu_bar_lines, Qtool_bar_lines;
 Lisp_Object Qleft_fringe, Qright_fringe;
 Lisp_Object Qbuffer_predicate, Qbuffer_list, Qburied_buffer_list;
 Lisp_Object Qtty_color_mode;
 Lisp_Object Qtty, Qtty_type;
-Lisp_Object Qwindow_system;
-Lisp_Object Qenvironment;
-Lisp_Object Qterm_environment_variable;
-Lisp_Object Qdisplay_environment_variable;
 
 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;
@@ -124,7 +127,9 @@ 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
 static void
 set_menu_bar_lines_1 (window, n)
@@ -261,7 +266,7 @@ FRAME defaults to the currently selected frame.  */)
     return Qnil;
   else
     return type;
-}      
+}
 
 struct frame *
 make_frame (mini_p)
@@ -327,6 +332,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)
@@ -514,16 +521,7 @@ make_initial_frame (void)
   struct terminal *terminal;
   Lisp_Object frame;
 
-#ifdef MULTI_KBOARD
-  /* Create the initial keyboard. */
-  if (!initial_kboard)
-    {
-      initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
-      init_kboard (initial_kboard);
-      initial_kboard->next_kboard = all_kboards;
-      all_kboards = initial_kboard;
-    }
-#endif
+  eassert (initial_kboard);
 
   /* The first call must initialize Vframe_list.  */
   if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
@@ -546,10 +544,10 @@ make_initial_frame (void)
   f->terminal = terminal;
   f->terminal->reference_count++;
   f->output_data.nothing = 0;
-  
+
   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;
 
@@ -564,8 +562,8 @@ make_terminal_frame (struct terminal *terminal)
   Lisp_Object frame;
   char name[20];
 
-  if (terminal->deleted)
-    error ("Terminal is being deleted, can't create new frames on it");
+  if (!terminal->name)
+    error ("Terminal is not live, can't create new frames on it");
 
   f = make_frame (1);
 
@@ -602,42 +600,31 @@ make_terminal_frame (struct terminal *terminal)
     }
   else
     f->output_method = output_termcap;
-#else
-#ifdef WINDOWSNT
-  f->output_method = output_termcap;
-  f->terminal = terminal;
-  f->terminal->reference_count++;
-  create_w32cons_output (f);
-#else
-#ifdef MAC_OS8
-  make_mac_terminal_frame (f);
 #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 (FRAME_TTY (f)->top_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
   FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR;
   FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR;
 #endif
-#endif /* MAC_OS8 */
-#endif /* WINDOWSNT */
 #endif /* MSDOS */
 
   if (!noninteractive)
@@ -704,7 +691,7 @@ affects all frames on the same terminal device.  */)
     abort ();
 #else /* not MSDOS */
 
-#if 0 /* #ifdef MAC_OS */
+#if 0
   /* This can happen for multi-tty when using both terminal frames and
      Carbon frames. */
   if (sf->output_method != output_mac)
@@ -716,7 +703,7 @@ affects all frames on the same terminal device.  */)
 #endif
 #endif
 #endif /* not MSDOS */
-  
+
   {
     Lisp_Object terminal;
 
@@ -727,9 +714,9 @@ affects all frames on the same terminal device.  */)
         t = get_terminal (terminal, 1);
       }
   }
-  
+
   if (!t)
-    { 
+    {
       char *name = 0, *type = 0;
       Lisp_Object tty, tty_type;
 
@@ -743,7 +730,7 @@ affects all frames on the same terminal device.  */)
           strncpy (name, SDATA (tty), SBYTES (tty));
           name[SBYTES (tty)] = 0;
         }
-      
+
       tty_type = get_future_frame_param
         (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
                             ? FRAME_TTY (XFRAME (selected_frame))->type
@@ -765,13 +752,12 @@ affects all frames on the same terminal device.  */)
     get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
     change_frame_size (f, height, width, 0, 0, 0);
   }
-  
+
   adjust_glyphs (f);
   calculate_costs (f);
   XSETFRAME (frame, f);
   Fmodify_frame_parameters (frame, Vdefault_frame_alist);
   Fmodify_frame_parameters (frame, parms);
-  Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qnil), Qnil));
   Fmodify_frame_parameters (frame, Fcons (Fcons (Qtty_type,
                                                  build_string (t->display_info.tty->type)),
                                           Qnil));
@@ -781,7 +767,7 @@ affects all frames on the same terminal device.  */)
                                             Qnil));
   else
     Fmodify_frame_parameters (frame, Fcons (Fcons (Qtty, Qnil), Qnil));
-  
+
   /* Make the frame face alist be frame-specific, so that each
      frame could change its face definitions independently.  */
   f->face_alist = Fcopy_alist (sf->face_alist);
@@ -879,11 +865,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)))
     {
-      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;
     }
@@ -894,23 +880,6 @@ do_switch_frame (frame, track, for_deletion)
 
   Fselect_window (XFRAME (frame)->selected_window, Qnil);
 
-#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 */
-
   /* We want to make sure that the next event generates a frame-switch
      event to the appropriate frame.  This seems kludgy to me, but
      before you take it out, make sure that evaluating something like
@@ -1344,6 +1313,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.
@@ -1353,7 +1324,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;
 {
@@ -1377,13 +1350,7 @@ The functions are run with one arg, the frame to be deleted.  */)
   if (! FRAME_LIVE_P (f))
     return Qnil;
 
-  if (NILP (force) && !other_visible_frames (f)
-#ifdef MAC_OS8
-      /* Terminal frame deleted before any other visible frames are
-        created.  */
-      && strcmp (SDATA (f->name), "F1") != 0
-#endif
-     )
+  if (NILP (force) && !other_visible_frames (f))
     error ("Attempt to delete the sole visible or iconified frame");
 
 #if 0
@@ -1410,31 +1377,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.  */
@@ -1476,24 +1448,6 @@ The functions are run with one arg, the frame to be deleted.  */)
   if (EQ (f->minibuffer_window, echo_area_window))
     echo_area_window = sf->minibuffer_window;
 
-  /* Don't allow other frames to refer to a deleted frame in their
-     'environment parameter.  */
-  {
-    Lisp_Object tail, frame1;
-    Lisp_Object env = get_frame_param (XFRAME (frame), Qenvironment);
-    FOR_EACH_FRAME (tail, frame1)
-      {
-        if (EQ (frame, frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
-          continue;
-        if (EQ (frame, get_frame_param (XFRAME (frame1), Qenvironment)))
-          {
-            store_frame_param (XFRAME (frame1), Qenvironment, env);
-            if (!FRAMEP (env))
-              env = frame1;
-          }
-      }
-  }
-  
   /* Clear any X selections for this frame.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (f))
@@ -1510,6 +1464,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));
@@ -1518,20 +1477,13 @@ 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));
+  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
@@ -1545,7 +1497,7 @@ The functions are run with one arg, the frame to be deleted.  */)
 
   {
     struct terminal *terminal = FRAME_TERMINAL (f);
-    f->output_data.nothing = 0; 
+    f->output_data.nothing = 0;
     f->terminal = 0;             /* Now the frame is dead. */
 
     /* If needed, delete the terminal that this frame was on.
@@ -1553,11 +1505,11 @@ 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
@@ -2052,7 +2004,7 @@ doesn't support multiple overlapping frames, this function does nothing.  */)
   CHECK_LIVE_FRAME (frame);
 
   f = XFRAME (frame);
-  
+
   /* Do like the documentation says. */
   Fmake_frame_visible (frame);
 
@@ -2072,14 +2024,14 @@ doesn't support multiple overlapping frames, this function does nothing.  */)
      Lisp_Object frame;
 {
   struct frame *f;
-  
+
   if (NILP (frame))
     frame = selected_frame;
 
   CHECK_LIVE_FRAME (frame);
 
   f = XFRAME (frame);
-  
+
   if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
     (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
 
@@ -2116,7 +2068,7 @@ The redirection lasts until `redirect-frame-focus' is called to change it.  */)
      Lisp_Object frame, focus_frame;
 {
   struct frame *f;
-  
+
   /* Note that we don't check for a live frame here.  It's reasonable
      to redirect the focus of a frame you're about to delete, if you
      know what other frame should receive those keystrokes.  */
@@ -2126,7 +2078,7 @@ The redirection lasts until `redirect-frame-focus' is called to change it.  */)
     CHECK_LIVE_FRAME (focus_frame);
 
   f = XFRAME (frame);
-  
+
   f->focus_frame = focus_frame;
 
   if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
@@ -2229,7 +2181,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')
     {
@@ -2314,8 +2266,7 @@ store_frame_param (f, prop, val)
     {
       Lisp_Object valcontents;
       valcontents = SYMBOL_VALUE (prop);
-      if ((BUFFER_LOCAL_VALUEP (valcontents)
-          || SOME_BUFFER_LOCAL_VALUEP (valcontents))
+      if ((BUFFER_LOCAL_VALUEP (valcontents))
          && XBUFFER_LOCAL_VALUE (valcontents)->check_frame
          && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame
          && XFRAME (XBUFFER_LOCAL_VALUE (valcontents)->frame) == f)
@@ -2323,11 +2274,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.  */
@@ -2400,7 +2353,7 @@ If FRAME is omitted, return information on the currently selected frame.  */)
         unspecified and reversed, take the frame's background pixel
         for foreground and vice versa.  */
       elt = Fassq (Qforeground_color, alist);
-      if (!NILP (elt) && CONSP (elt) && STRINGP (XCDR (elt)))
+      if (CONSP (elt) && STRINGP (XCDR (elt)))
        {
          if (strncmp (SDATA (XCDR (elt)),
                       unspecified_bg,
@@ -2414,7 +2367,7 @@ If FRAME is omitted, return information on the currently selected frame.  */)
       else
        store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
       elt = Fassq (Qbackground_color, alist);
-      if (!NILP (elt) && CONSP (elt) && STRINGP (XCDR (elt)))
+      if (CONSP (elt) && STRINGP (XCDR (elt)))
        {
          if (strncmp (SDATA (XCDR (elt)),
                       unspecified_fg,
@@ -2589,11 +2542,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++;
@@ -2613,44 +2566,8 @@ enabled such bindings for that variable with `make-variable-frame-local'.  */)
            call1 (Qframe_set_background_mode, frame);
        }
     }
+  return Qnil;
 }
-
-DEFUN ("frame-with-environment", Fframe_with_environment, Sframe_with_environment, 0, 1, 0,
-       doc: /* Return the frame that has the environment variable list for FRAME.
-
-The frame-local environment variable list is normally shared between
-frames that were created in the same Emacsclient session.  The
-environment list is stored in a single frame's 'environment parameter;
-the other frames' 'environment parameter is set to this frame.  This
-function follows the chain of 'environment references to reach the
-frame that stores the actual local environment list, and returns that
-frame.  */)
-     (frame)
-     Lisp_Object frame;
-{
-  Lisp_Object hare, tortoise;
-
-  if (NILP (frame))
-    frame = selected_frame;
-  CHECK_FRAME (frame);
-
-  hare = tortoise = get_frame_param (XFRAME (frame), Qenvironment);
-  while (!NILP (hare) && FRAMEP (hare))
-    {
-      frame = hare;
-      hare = get_frame_param (XFRAME (hare), Qenvironment);
-      if (NILP (hare) || !FRAMEP (hare))
-        break;
-      frame = hare;
-      hare = get_frame_param (XFRAME (hare), Qenvironment);
-      tortoise = get_frame_param (XFRAME (tortoise), Qenvironment);
-      if (EQ (hare, tortoise))
-        error ("Cyclic frame-local environment indirection");
-    }
-
-  return frame;
-}
-
 \f
 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
        0, 1, 0,
@@ -2907,6 +2824,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
@@ -3005,11 +2924,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++;
@@ -3082,9 +3001,9 @@ x_set_frame_parameters (f, alist)
       prop = parms[i];
       val = values[i];
 
-      if (EQ (prop, Qwidth) && NUMBERP (val))
+      if (EQ (prop, Qwidth) && NATNUMP (val))
        width = XFASTINT (val);
-      else if (EQ (prop, Qheight) && NUMBERP (val))
+      else if (EQ (prop, Qheight) && NATNUMP (val))
        height = XFASTINT (val);
       else if (EQ (prop, Qtop))
        top = val;
@@ -3330,6 +3249,7 @@ x_report_frame_params (f, alistptr)
     tem = Qnil;
   else
     XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
+  store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
   store_in_alist (alistptr, Qparent_id, tem);
 }
 
@@ -3351,7 +3271,7 @@ x_set_fullscreen (f, new_value, old_value)
   else if (EQ (new_value, Qfullheight))
     f->want_fullscreen = FULLSCREEN_HEIGHT;
 
-  if (FRAME_TERMINAL (f)->fullscreen_hook != NULL) 
+  if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
     FRAME_TERMINAL (f)->fullscreen_hook (f);
 }
 
@@ -3415,48 +3335,59 @@ 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);
-
-  fontset_name = Fquery_fontset (arg, Qnil);
+  int fontset = -1;
+  Lisp_Object font_object;
 
-  BLOCK_INPUT;
-  result = (STRINGP (fontset_name)
-            ? x_new_fontset (f, SDATA (fontset_name))
-            : x_new_font (f, SDATA (arg)));
-  UNBLOCK_INPUT;
+  /* Set the frame parameter back to the old value because we mail
+     fail to use ARG as the new parameter value.  */
+  store_frame_param (f, Qfont, oldval);
 
-  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);
 
@@ -3473,6 +3404,60 @@ x_set_font (f, arg, oldval)
 }
 
 
+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 && *p1 != ',') p1++;
+         if (p0 < p1)
+           new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
+                              new_value);
+         if (*p1)
+           p1++;
+         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);
+      x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
+      ++face_change_count;
+      ++windows_or_buffers_changed;
+    }
+}
+
+
 void
 x_set_fringe_width (f, new_value, old_value)
      struct frame *f;
@@ -3650,6 +3635,61 @@ 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))
+        {
+          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];
+
+#ifdef HAVE_X_WINDOWS
+  BLOCK_INPUT;
+  x_set_frame_alpha (f);
+  UNBLOCK_INPUT;
+#endif
+
+  return;
+}
+
 \f
 /* Subroutines of creating an X frame.  */
 
@@ -4244,7 +4284,7 @@ x_figure_window_size (f, parms, toolbar_p)
       int width, height;
 
       /* It takes both for some WM:s to place it where we want */
-      window_prompting = USPosition | PPosition;
+      window_prompting |= USPosition | PPosition;
       x_fullscreen_adjust (f, &width, &height, &top, &left);
       FRAME_COLS (f) = width;
       FRAME_LINES (f) = height;
@@ -4291,6 +4331,8 @@ syms_of_frame ()
   staticpro (&Qframep);
   Qframe_live_p = intern ("frame-live-p");
   staticpro (&Qframe_live_p);
+  Qexplicit_name = intern ("explicit-name");
+  staticpro (&Qexplicit_name);
   Qheight = intern ("height");
   staticpro (&Qheight);
   Qicon = intern ("icon");
@@ -4345,21 +4387,14 @@ 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");
   staticpro (&Qtty);
   Qtty_type = intern ("tty-type");
   staticpro (&Qtty_type);
-  Qwindow_system = intern ("window-system");
-  staticpro (&Qwindow_system);
-  Qenvironment = intern ("environment");
-  staticpro (&Qenvironment);
-
-  Qterm_environment_variable = intern ("term-environment-variable");
-  staticpro (&Qterm_environment_variable);
-  Qdisplay_environment_variable = intern ("display-environment-variable");
-  staticpro (&Qdisplay_environment_variable);
 
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
@@ -4384,7 +4419,7 @@ syms_of_frame ()
   staticpro (&Qterminal);
   Qterminal_live_p = intern ("terminal-live-p");
   staticpro (&Qterminal_live_p);
-  
+
   {
     int i;
 
@@ -4424,6 +4459,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,
@@ -4482,13 +4524,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.
@@ -4505,6 +4547,21 @@ displayed.
 
 This variable is local to the current terminal and cannot be buffer-local.  */);
 
+  DEFVAR_BOOL ("focus-follows-mouse", &focus_follows_mouse,
+              doc: /* Non-nil if window system changes focus when you move the mouse.
+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)
+  focus_follows_mouse = 0;
+#else
+  focus_follows_mouse = 1;
+#endif
+#else
+  focus_follows_mouse = 0;
+#endif
+
   staticpro (&Vframe_list);
 
   defsubr (&Sactive_minibuffer_window);
@@ -4544,7 +4601,6 @@ This variable is local to the current terminal and cannot be buffer-local.  */);
   defsubr (&Sframe_parameters);
   defsubr (&Sframe_parameter);
   defsubr (&Smodify_frame_parameters);
-  defsubr (&Sframe_with_environment);
   defsubr (&Sframe_char_height);
   defsubr (&Sframe_char_width);
   defsubr (&Sframe_pixel_height);