Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
[bpt/emacs.git] / src / xfaces.c
index 902d30c..d4d68eb 100644 (file)
@@ -1,6 +1,6 @@
 /* xfaces.c -- "Face" primitives.
    Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -27,34 +27,36 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
    1. Font family name.
 
-   2. Relative proportionate width, aka character set width or set
+   2. Font foundary name.
+
+   3. Relative proportionate width, aka character set width or set
    width (swidth), e.g. `semi-compressed'.
 
-   3. Font height in 1/10pt.
+   4. Font height in 1/10pt.
 
-   4. Font weight, e.g. `bold'.
+   5. Font weight, e.g. `bold'.
 
-   5. Font slant, e.g. `italic'.
+   6. Font slant, e.g. `italic'.
 
-   6. Foreground color.
+   7. Foreground color.
 
-   7. Background color.
+   8. Background color.
 
-   8. Whether or not characters should be underlined, and in what color.
+   9. Whether or not characters should be underlined, and in what color.
 
-   9. Whether or not characters should be displayed in inverse video.
+   10. Whether or not characters should be displayed in inverse video.
 
-   10. A background stipple, a bitmap.
+   11. A background stipple, a bitmap.
 
-   11. Whether or not characters should be overlined, and in what color.
+   12. Whether or not characters should be overlined, and in what color.
 
-   12. Whether or not characters should be strike-through, and in what
+   13. Whether or not characters should be strike-through, and in what
    color.
 
-   13. Whether or not a box should be drawn around characters, the box
+   14. Whether or not a box should be drawn around characters, the box
    type, and, for simple boxes, in what color.
 
-   14. Font-spec, or nil.  This is a special attribute.
+   15. Font-spec, or nil.  This is a special attribute.
 
    A font-spec is a collection of font attributes (specs).
 
@@ -202,6 +204,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdio.h>              /* This needs to be before termchar.h */
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "character.h"
@@ -232,15 +235,18 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define x_display_info w32_display_info
 #define FRAME_X_FONT_TABLE FRAME_W32_FONT_TABLE
 #define check_x check_w32
-#define x_list_fonts w32_list_fonts
 #define GCGraphicsExposures 0
 #endif /* WINDOWSNT */
 
-#ifdef MAC_OS
-#include "macterm.h"
-#define x_display_info mac_display_info
-#define check_x check_mac
-#endif /* MAC_OS */
+#ifdef HAVE_NS
+#include "nsterm.h"
+#undef FRAME_X_DISPLAY_INFO
+#define FRAME_X_DISPLAY_INFO FRAME_NS_DISPLAY_INFO
+#define x_display_info ns_display_info
+#define FRAME_X_FONT_TABLE FRAME_NS_FONT_TABLE
+#define check_x check_ns
+#define GCGraphicsExposures 0
+#endif /* HAVE_NS */
 
 #include "buffer.h"
 #include "dispextern.h"
@@ -249,8 +255,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "intervals.h"
 #include "termchar.h"
 
-#ifdef HAVE_WINDOW_SYSTEM
 #include "font.h"
+#ifdef HAVE_WINDOW_SYSTEM
 #include "fontset.h"
 #endif /* HAVE_WINDOW_SYSTEM */
 
@@ -422,6 +428,23 @@ Lisp_Object Qbitmap_spec_p;
 
 Lisp_Object Vface_new_frame_defaults;
 
+/* Alist of face remappings.  Each element is of the form:
+   (FACE REPLACEMENT...) which causes display of the face FACE to use
+   REPLACEMENT... instead.  REPLACEMENT... is interpreted the same way
+   the value of a `face' text property is: it may be (1) A face name,
+   (2) A list of face names, (3) A property-list of face attribute/value
+   pairs, or (4) A list of face names intermixed with lists containing
+   face attribute/value pairs.
+
+   Multiple entries in REPLACEMENT... are merged together to form the final
+   result, with faces or attributes earlier in the list taking precedence
+   over those that are later.
+
+   Face-name remapping cycles are suppressed; recursive references use
+   the underlying face instead of the remapped face.  */
+
+Lisp_Object Vface_remapping_alist;
+
 /* The next ID to assign to Lisp faces.  */
 
 static int next_lface_id;
@@ -484,85 +507,59 @@ int menu_face_changed_default;
 \f
 /* Function prototypes.  */
 
-struct font_name;
 struct table_entry;
 struct named_merge_point;
 
-static void map_tty_color P_ ((struct frame *, struct face *,
-                              enum lface_attribute_index, int *));
-static Lisp_Object resolve_face_name P_ ((Lisp_Object, int));
-static int may_use_scalable_font_p P_ ((const char *));
-static void set_font_frame_param P_ ((Lisp_Object, Lisp_Object));
-static int better_font_p P_ ((int *, struct font_name *, struct font_name *,
-                             int, int));
-static int x_face_list_fonts P_ ((struct frame *, char *,
-                                 struct font_name **, int, int));
-static int get_lface_attributes P_ ((struct frame *, Lisp_Object, Lisp_Object *, int));
-static int load_pixmap P_ ((struct frame *, Lisp_Object, unsigned *, unsigned *));
-static unsigned char *xstrlwr P_ ((unsigned char *));
-static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int));
-static void load_face_font P_ ((struct frame *, struct face *));
-static void load_face_colors P_ ((struct frame *, struct face *, Lisp_Object *));
-static void free_face_colors P_ ((struct frame *, struct face *));
-static int face_color_gray_p P_ ((struct frame *, char *));
-static char *build_font_name P_ ((struct font_name *));
-static void free_font_names P_ ((struct font_name *, int));
-static int sorted_font_list P_ ((struct frame *, char *,
-                                int (*cmpfn) P_ ((const void *, const void *)),
-                                struct font_name **));
-static int font_list_1 P_ ((struct frame *, Lisp_Object, Lisp_Object,
-                           Lisp_Object, struct font_name **));
-static int font_list P_ ((struct frame *, Lisp_Object, Lisp_Object,
-                         Lisp_Object, struct font_name **));
-static int try_font_list P_ ((struct frame *, Lisp_Object,
-                             Lisp_Object, Lisp_Object, struct font_name **));
-static int try_alternative_families P_ ((struct frame *f, Lisp_Object,
-                                        Lisp_Object, struct font_name **));
-static int cmp_font_names P_ ((const void *, const void *));
-static struct face *realize_face P_ ((struct face_cache *, Lisp_Object *,
-                                     int));
-static struct face *realize_non_ascii_face P_ ((struct frame *, Lisp_Object,
-                                               struct face *));
-static struct face *realize_x_face P_ ((struct face_cache *, Lisp_Object *));
-static struct face *realize_tty_face P_ ((struct face_cache *, Lisp_Object *));
-static int realize_basic_faces P_ ((struct frame *));
-static int realize_default_face P_ ((struct frame *));
-static void realize_named_face P_ ((struct frame *, Lisp_Object, int));
-static int lface_fully_specified_p P_ ((Lisp_Object *));
-static int lface_equal_p P_ ((Lisp_Object *, Lisp_Object *));
-static unsigned hash_string_case_insensitive P_ ((Lisp_Object));
-static unsigned lface_hash P_ ((Lisp_Object *));
-static int lface_same_font_attributes_p P_ ((Lisp_Object *, Lisp_Object *));
-static struct face_cache *make_face_cache P_ ((struct frame *));
-static void clear_face_gcs P_ ((struct face_cache *));
-static void free_face_cache P_ ((struct face_cache *));
-static int face_fontset P_ ((Lisp_Object *));
-static void merge_face_vectors P_ ((struct frame *, Lisp_Object *, Lisp_Object*,
-                                   struct named_merge_point *));
-static int merge_face_ref P_ ((struct frame *, Lisp_Object, Lisp_Object *,
-                              int, struct named_merge_point *));
-static int set_lface_from_font P_ ((struct frame *, Lisp_Object, Lisp_Object,
-                                   int));
-static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
-static struct face *make_realized_face P_ ((Lisp_Object *));
-static char *best_matching_font P_ ((struct frame *, Lisp_Object *,
-                                    struct font_name *, int, int, int *));
-static void cache_face P_ ((struct face_cache *, struct face *, unsigned));
-static void uncache_face P_ ((struct face_cache *, struct face *));
+static void map_tty_color (struct frame *, struct face *,
+                           enum lface_attribute_index, int *);
+static Lisp_Object resolve_face_name (Lisp_Object, int);
+static int may_use_scalable_font_p (const char *);
+static void set_font_frame_param (Lisp_Object, Lisp_Object);
+static int get_lface_attributes (struct frame *, Lisp_Object, Lisp_Object *,
+                                 int, struct named_merge_point *);
+static int load_pixmap (struct frame *, Lisp_Object, unsigned *, unsigned *);
+static struct frame *frame_or_selected_frame (Lisp_Object, int);
+static void load_face_colors (struct frame *, struct face *, Lisp_Object *);
+static void free_face_colors (struct frame *, struct face *);
+static int face_color_gray_p (struct frame *, char *);
+static struct face *realize_face (struct face_cache *, Lisp_Object *,
+                                  int);
+static struct face *realize_non_ascii_face (struct frame *, Lisp_Object,
+                                            struct face *);
+static struct face *realize_x_face (struct face_cache *, Lisp_Object *);
+static struct face *realize_tty_face (struct face_cache *, Lisp_Object *);
+static int realize_basic_faces (struct frame *);
+static int realize_default_face (struct frame *);
+static void realize_named_face (struct frame *, Lisp_Object, int);
+static int lface_fully_specified_p (Lisp_Object *);
+static int lface_equal_p (Lisp_Object *, Lisp_Object *);
+static unsigned hash_string_case_insensitive (Lisp_Object);
+static unsigned lface_hash (Lisp_Object *);
+static int lface_same_font_attributes_p (Lisp_Object *, Lisp_Object *);
+static struct face_cache *make_face_cache (struct frame *);
+static void clear_face_gcs (struct face_cache *);
+static void free_face_cache (struct face_cache *);
+static int face_fontset (Lisp_Object *);
+static void merge_face_vectors (struct frame *, Lisp_Object *, Lisp_Object*,
+                                struct named_merge_point *);
+static int merge_face_ref (struct frame *, Lisp_Object, Lisp_Object *,
+                           int, struct named_merge_point *);
+static int set_lface_from_font (struct frame *, Lisp_Object, Lisp_Object,
+                                int);
+static Lisp_Object lface_from_face_name (struct frame *, Lisp_Object, int);
+static struct face *make_realized_face (Lisp_Object *);
+static void cache_face (struct face_cache *, struct face *, unsigned);
+static void uncache_face (struct face_cache *, struct face *);
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-static GC x_create_gc P_ ((struct frame *, unsigned long, XGCValues *));
-static void x_free_gc P_ ((struct frame *, GC));
-
-#ifdef WINDOWSNT
-extern Lisp_Object w32_list_fonts P_ ((struct frame *, Lisp_Object, int, int));
-#endif /* WINDOWSNT */
+static GC x_create_gc (struct frame *, unsigned long, XGCValues *);
+static void x_free_gc (struct frame *, GC);
 
 #ifdef USE_X_TOOLKIT
-static void x_update_menu_appearance P_ ((struct frame *));
+static void x_update_menu_appearance (struct frame *);
 
-extern void free_frame_menubar P_ ((struct frame *));
+extern void free_frame_menubar (struct frame *);
 #endif /* USE_X_TOOLKIT */
 
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -659,10 +656,7 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
    is called.  */
 
 void
-x_free_colors (f, pixels, npixels)
-     struct frame *f;
-     unsigned long *pixels;
-     int npixels;
+x_free_colors (struct frame *f, long unsigned int *pixels, int npixels)
 {
   int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
 
@@ -684,12 +678,7 @@ x_free_colors (f, pixels, npixels)
    is called.  */
 
 void
-x_free_dpy_colors (dpy, screen, cmap, pixels, npixels)
-     Display *dpy;
-     Screen *screen;
-     Colormap cmap;
-     unsigned long *pixels;
-     int npixels;
+x_free_dpy_colors (Display *dpy, Screen *screen, Colormap cmap, long unsigned int *pixels, int npixels)
 {
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   int class = dpyinfo->visual->class;
@@ -710,10 +699,7 @@ x_free_dpy_colors (dpy, screen, cmap, pixels, npixels)
    are given by XGCV and MASK.  */
 
 static INLINE GC
-x_create_gc (f, mask, xgcv)
-     struct frame *f;
-     unsigned long mask;
-     XGCValues *xgcv;
+x_create_gc (struct frame *f, long unsigned int mask, XGCValues *xgcv)
 {
   GC gc;
   BLOCK_INPUT;
@@ -727,9 +713,7 @@ x_create_gc (f, mask, xgcv)
 /* Free GC which was used on frame F.  */
 
 static INLINE void
-x_free_gc (f, gc)
-     struct frame *f;
-     GC gc;
+x_free_gc (struct frame *f, GC gc)
 {
   eassert (interrupt_input_blocked);
   IF_DEBUG (xassert (--ngcs >= 0));
@@ -769,8 +753,8 @@ x_free_gc (f, gc)
 
 #endif  /* WINDOWSNT */
 
-#ifdef MAC_OS
-/* Mac OS emulation of GCs */
+#ifdef HAVE_NS
+/* NS emulation of GCs */
 
 static INLINE GC
 x_create_gc (f, mask, xgcv)
@@ -778,11 +762,9 @@ x_create_gc (f, mask, xgcv)
      unsigned long mask;
      XGCValues *xgcv;
 {
-  GC gc;
-  BLOCK_INPUT;
-  gc = XCreateGC (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), mask, xgcv);
-  UNBLOCK_INPUT;
-  IF_DEBUG (++ngcs);
+  GC gc = xmalloc (sizeof (*gc));
+  if (gc)
+    memcpy (gc, xgcv, sizeof (XGCValues));
   return gc;
 }
 
@@ -791,19 +773,15 @@ x_free_gc (f, gc)
      struct frame *f;
      GC gc;
 {
-  eassert (interrupt_input_blocked);
-  IF_DEBUG (xassert (--ngcs >= 0));
-  XFreeGC (FRAME_MAC_DISPLAY (f), gc);
+  xfree (gc);
 }
+#endif  /* HAVE_NS */
 
-#endif  /* MAC_OS */
-
-/* Like stricmp.  Used to compare parts of font names which are in
-   ISO8859-1.  */
+/* Like strcasecmp/stricmp.  Used to compare parts of font names which
+   are in ISO8859-1.  */
 
 int
-xstricmp (s1, s2)
-     const unsigned char *s1, *s2;
+xstrcasecmp (const unsigned char *s1, const unsigned char *s2)
 {
   while (*s1 && *s2)
     {
@@ -820,24 +798,6 @@ xstricmp (s1, s2)
 }
 
 
-/* Like strlwr, which might not always be available.  */
-
-static unsigned char *
-xstrlwr (s)
-     unsigned char *s;
-{
-  unsigned char *p = s;
-
-  for (p = s; *p; ++p)
-    /* On Mac OS X 10.3, tolower also converts non-ASCII characters
-       for some locales.  */
-    if (isascii (*p))
-      *p = tolower (*p);
-
-  return s;
-}
-
-
 /* If FRAME is nil, return a pointer to the selected frame.
    Otherwise, check that FRAME is a live frame, and return a pointer
    to it.  NPARAM is the parameter number of FRAME, for
@@ -845,9 +805,7 @@ xstrlwr (s)
    Lisp function definitions.  */
 
 static INLINE struct frame *
-frame_or_selected_frame (frame, nparam)
-     Lisp_Object frame;
-     int nparam;
+frame_or_selected_frame (Lisp_Object frame, int nparam)
 {
   if (NILP (frame))
     frame = selected_frame;
@@ -864,8 +822,7 @@ frame_or_selected_frame (frame, nparam)
 /* Initialize face cache and basic faces for frame F.  */
 
 void
-init_frame_faces (f)
-     struct frame *f;
+init_frame_faces (struct frame *f)
 {
   /* Make a face cache, if F doesn't have one.  */
   if (FRAME_FACE_CACHE (f) == NULL)
@@ -875,8 +832,10 @@ init_frame_faces (f)
   /* Make the image cache.  */
   if (FRAME_WINDOW_P (f))
     {
+      /* We initialize the image cache when creating the first frame
+        on a terminal, and not during terminal creation.  This way,
+        `x-open-connection' on a tty won't create an image cache.  */
       if (FRAME_IMAGE_CACHE (f) == NULL)
-       /* Is that ever possible??  --Stef  */
        FRAME_IMAGE_CACHE (f) = make_image_cache ();
       ++FRAME_IMAGE_CACHE (f)->refcount;
     }
@@ -890,19 +849,18 @@ init_frame_faces (f)
 #ifdef WINDOWSNT
   if (!FRAME_WINDOW_P (f) || FRAME_W32_WINDOW (f))
 #endif
-#ifdef MAC_OS
-  if (!FRAME_MAC_P (f) || FRAME_MAC_WINDOW (f))
+#ifdef HAVE_NS
+  if (!FRAME_NS_P (f) || FRAME_NS_WINDOW (f))
 #endif
     if (!realize_basic_faces (f))
-      abort ();
+        abort ();
 }
 
 
-/* Free face cache of frame F.  Called from Fdelete_frame.  */
+/* Free face cache of frame F.  Called from delete_frame.  */
 
 void
-free_frame_faces (f)
-     struct frame *f;
+free_frame_faces (struct frame *f)
 {
   struct face_cache *face_cache = FRAME_FACE_CACHE (f);
 
@@ -933,8 +891,7 @@ free_frame_faces (f)
    of named faces. */
 
 void
-recompute_basic_faces (f)
-     struct frame *f;
+recompute_basic_faces (struct frame *f)
 {
   if (FRAME_FACE_CACHE (f))
     {
@@ -949,8 +906,7 @@ recompute_basic_faces (f)
    try to free unused fonts, too.  */
 
 void
-clear_face_cache (clear_fonts_p)
-     int clear_fonts_p;
+clear_face_cache (int clear_fonts_p)
 {
 #ifdef HAVE_WINDOW_SYSTEM
   Lisp_Object tail, frame;
@@ -959,14 +915,11 @@ clear_face_cache (clear_fonts_p)
   if (clear_fonts_p
       || ++clear_font_table_count == CLEAR_FONT_TABLE_COUNT)
     {
-      struct x_display_info *dpyinfo;
-
 #if 0
       /* Not yet implemented.  */
       clear_font_cache (frame);
 #endif
 
-
       /* From time to time see if we can unload some fonts.  This also
         frees all realized faces on all frames.  Fonts needed by
         faces will be loaded again when faces are realized again.  */
@@ -1072,10 +1025,7 @@ the pixmap.  Bits are stored row by row, each row occupies
    if these pointers are not null.  */
 
 static int
-load_pixmap (f, name, w_ptr, h_ptr)
-     FRAME_PTR f;
-     Lisp_Object name;
-     unsigned int *w_ptr, *h_ptr;
+load_pixmap (FRAME_PTR f, Lisp_Object name, unsigned int *w_ptr, unsigned int *h_ptr)
 {
   int bitmap_id;
 
@@ -1144,9 +1094,7 @@ load_pixmap (f, name, w_ptr, h_ptr)
    Return 0 if there's a problem with RGB_LIST, otherwise return 1.  */
 
 static int
-parse_rgb_list (rgb_list, color)
-     Lisp_Object rgb_list;
-     XColor *color;
+parse_rgb_list (Lisp_Object rgb_list, XColor *color)
 {
 #define PARSE_RGB_LIST_FIELD(field)                                    \
   if (CONSP (rgb_list) && INTEGERP (XCAR (rgb_list)))                  \
@@ -1171,10 +1119,7 @@ parse_rgb_list (rgb_list, color)
    returned in it.  */
 
 static int
-tty_lookup_color (f, color, tty_color, std_color)
-     struct frame *f;
-     Lisp_Object color;
-     XColor *tty_color, *std_color;
+tty_lookup_color (struct frame *f, Lisp_Object color, XColor *tty_color, XColor *std_color)
 {
   Lisp_Object frame, color_desc;
 
@@ -1234,11 +1179,7 @@ tty_lookup_color (f, color, tty_color, std_color)
 /* A version of defined_color for non-X frames.  */
 
 int
-tty_defined_color (f, color_name, color_def, alloc)
-     struct frame *f;
-     char *color_name;
-     XColor *color_def;
-     int alloc;
+tty_defined_color (struct frame *f, char *color_name, XColor *color_def, int alloc)
 {
   int status = 1;
 
@@ -1273,11 +1214,7 @@ tty_defined_color (f, color_name, color_def, alloc)
    This does the right thing for any type of frame.  */
 
 int
-defined_color (f, color_name, color_def, alloc)
-     struct frame *f;
-     char *color_name;
-     XColor *color_def;
-     int alloc;
+defined_color (struct frame *f, char *color_name, XColor *color_def, int alloc)
 {
   if (!FRAME_WINDOW_P (f))
     return tty_defined_color (f, color_name, color_def, alloc);
@@ -1289,9 +1226,9 @@ defined_color (f, color_name, color_def, alloc)
   else if (FRAME_W32_P (f))
     return w32_defined_color (f, color_name, color_def, alloc);
 #endif
-#ifdef MAC_OS
-  else if (FRAME_MAC_P (f))
-    return mac_defined_color (f, color_name, color_def, alloc);
+#ifdef HAVE_NS
+  else if (FRAME_NS_P (f))
+    return ns_defined_color (f, color_name, color_def, alloc, 1);
 #endif
   else
     abort ();
@@ -1302,9 +1239,7 @@ defined_color (f, color_name, color_def, alloc)
    Lisp string.  */
 
 Lisp_Object
-tty_color_name (f, idx)
-     struct frame *f;
-     int idx;
+tty_color_name (struct frame *f, int idx)
 {
   if (idx >= 0 && !NILP (Ffboundp (Qtty_color_by_index)))
     {
@@ -1339,9 +1274,7 @@ tty_color_name (f, idx)
    The criterion implemented here is not a terribly sophisticated one.  */
 
 static int
-face_color_gray_p (f, color_name)
-     struct frame *f;
-     char *color_name;
+face_color_gray_p (struct frame *f, char *color_name)
 {
   XColor color;
   int gray_p;
@@ -1368,10 +1301,7 @@ face_color_gray_p (f, color_name)
    color.  */
 
 static int
-face_color_supported_p (f, color_name, background_p)
-     struct frame *f;
-     char *color_name;
-     int background_p;
+face_color_supported_p (struct frame *f, char *color_name, int background_p)
 {
   Lisp_Object frame;
   XColor not_used;
@@ -1381,8 +1311,8 @@ face_color_supported_p (f, color_name, background_p)
 #ifdef HAVE_WINDOW_SYSTEM
     FRAME_WINDOW_P (f)
     ? (!NILP (Fxw_display_color_p (frame))
-       || xstricmp (color_name, "black") == 0
-       || xstricmp (color_name, "white") == 0
+       || xstrcasecmp (color_name, "black") == 0
+       || xstrcasecmp (color_name, "white") == 0
        || (background_p
           && face_color_gray_p (f, color_name))
        || (!NILP (Fx_display_grayscale_p (frame))
@@ -1446,11 +1376,7 @@ COLOR must be a valid color name.  */)
    these colors.  */
 
 unsigned long
-load_color (f, face, name, target_index)
-     struct frame *f;
-     struct face *face;
-     Lisp_Object name;
-     enum lface_attribute_index target_index;
+load_color (struct frame *f, struct face *face, Lisp_Object name, enum lface_attribute_index target_index)
 {
   XColor color;
 
@@ -1521,10 +1447,7 @@ load_color (f, face, name, target_index)
    try to emulate gray colors with a stipple from Vface_default_stipple.  */
 
 static void
-load_face_colors (f, face, attrs)
-     struct frame *f;
-     struct face *face;
-     Lisp_Object *attrs;
+load_face_colors (struct frame *f, struct face *face, Lisp_Object *attrs)
 {
   Lisp_Object fg, bg;
 
@@ -1560,9 +1483,7 @@ load_face_colors (f, face, attrs)
 /* Free color PIXEL on frame F.  */
 
 void
-unload_color (f, pixel)
-     struct frame *f;
-     unsigned long pixel;
+unload_color (struct frame *f, long unsigned int pixel)
 {
 #ifdef HAVE_X_WINDOWS
   if (pixel != -1)
@@ -1578,10 +1499,9 @@ unload_color (f, pixel)
 /* Free colors allocated for FACE.  */
 
 static void
-free_face_colors (f, face)
-     struct frame *f;
-     struct face *face;
+free_face_colors (struct frame *f, struct face *face)
 {
+/* PENDING(NS): need to do something here? */
 #ifdef HAVE_X_WINDOWS
   if (face->colors_copied_bitwise_p)
     return;
@@ -1707,124 +1627,24 @@ enum xlfd_swidth
   XLFD_SWIDTH_ULTRA_EXPANDED   /* 90: UltraExpanded... */
 };
 
-/* Structure used for tables mapping XLFD weight, slant, and width
-   names to numeric and symbolic values.  */
-
-struct table_entry
-{
-  char *name;
-  int numeric;
-  Lisp_Object *symbol;
-};
-
-/* Table of XLFD slant names and their numeric and symbolic
-   representations.  This table must be sorted by slant names in
-   ascending order.  */
-
-static struct table_entry slant_table[] =
-{
-  {"i",                        XLFD_SLANT_ITALIC,              &Qitalic},
-  {"o",                        XLFD_SLANT_OBLIQUE,             &Qoblique},
-  {"ot",               XLFD_SLANT_OTHER,               &Qitalic},
-  {"r",                        XLFD_SLANT_ROMAN,               &Qnormal},
-  {"ri",               XLFD_SLANT_REVERSE_ITALIC,      &Qreverse_italic},
-  {"ro",               XLFD_SLANT_REVERSE_OBLIQUE,     &Qreverse_oblique}
-};
-
-/* Table of XLFD weight names.  This table must be sorted by weight
-   names in ascending order.  */
-
-static struct table_entry weight_table[] =
-{
-  {"black",            XLFD_WEIGHT_ULTRA_BOLD,         &Qultra_bold},
-  {"bold",             XLFD_WEIGHT_BOLD,               &Qbold},
-  {"book",             XLFD_WEIGHT_SEMI_LIGHT,         &Qsemi_light},
-  {"demi",             XLFD_WEIGHT_SEMI_BOLD,          &Qsemi_bold},
-  {"demibold",         XLFD_WEIGHT_SEMI_BOLD,          &Qsemi_bold},
-  {"extralight",       XLFD_WEIGHT_EXTRA_LIGHT,        &Qextra_light},
-  {"extrabold",                XLFD_WEIGHT_EXTRA_BOLD,         &Qextra_bold},
-  {"heavy",            XLFD_WEIGHT_EXTRA_BOLD,         &Qextra_bold},
-  {"light",            XLFD_WEIGHT_LIGHT,              &Qlight},
-  {"medium",           XLFD_WEIGHT_MEDIUM,             &Qnormal},
-  {"normal",           XLFD_WEIGHT_MEDIUM,             &Qnormal},
-  {"regular",          XLFD_WEIGHT_MEDIUM,             &Qnormal},
-  {"semibold",         XLFD_WEIGHT_SEMI_BOLD,          &Qsemi_bold},
-  {"semilight",                XLFD_WEIGHT_SEMI_LIGHT,         &Qsemi_light},
-  {"ultralight",       XLFD_WEIGHT_ULTRA_LIGHT,        &Qultra_light},
-  {"ultrabold",                XLFD_WEIGHT_ULTRA_BOLD,         &Qultra_bold}
-};
-
-/* Table of XLFD width names.  This table must be sorted by width
-   names in ascending order.  */
-
-static struct table_entry swidth_table[] =
-{
-  {"compressed",       XLFD_SWIDTH_CONDENSED,          &Qcondensed},
-  {"condensed",                XLFD_SWIDTH_CONDENSED,          &Qcondensed},
-  {"demiexpanded",     XLFD_SWIDTH_SEMI_EXPANDED,      &Qsemi_expanded},
-  {"expanded",         XLFD_SWIDTH_EXPANDED,           &Qexpanded},
-  {"extracondensed",   XLFD_SWIDTH_EXTRA_CONDENSED,    &Qextra_condensed},
-  {"extraexpanded",    XLFD_SWIDTH_EXTRA_EXPANDED,     &Qextra_expanded},
-  {"medium",           XLFD_SWIDTH_MEDIUM,             &Qnormal},
-  {"narrow",           XLFD_SWIDTH_CONDENSED,          &Qcondensed},
-  {"normal",           XLFD_SWIDTH_MEDIUM,             &Qnormal},
-  {"regular",          XLFD_SWIDTH_MEDIUM,             &Qnormal},
-  {"semicondensed",    XLFD_SWIDTH_SEMI_CONDENSED,     &Qsemi_condensed},
-  {"semiexpanded",     XLFD_SWIDTH_SEMI_EXPANDED,      &Qsemi_expanded},
-  {"ultracondensed",   XLFD_SWIDTH_ULTRA_CONDENSED,    &Qultra_condensed},
-  {"ultraexpanded",    XLFD_SWIDTH_ULTRA_EXPANDED,     &Qultra_expanded},
-  {"wide",             XLFD_SWIDTH_EXTRA_EXPANDED,     &Qextra_expanded}
-};
-
-/* The frame in effect when sorting font names.  Set temporarily in
-   sort_fonts so that it is available in font comparison functions.  */
-
-static struct frame *font_frame;
-
 /* Order by which font selection chooses fonts.  The default values
    mean `first, find a best match for the font width, then for the
    font height, then for weight, then for slant.'  This variable can be
    set via set-face-font-sort-order.  */
 
-#ifdef MAC_OS
-static int font_sort_order[4] = {
-  XLFD_SWIDTH, XLFD_POINT_SIZE, XLFD_WEIGHT, XLFD_SLANT
-};
-#else
 static int font_sort_order[4];
-#endif
-
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-/* Return a rescaling ratio of a font of NAME.  */
-
-static double
-font_rescale_ratio (name)
-     char *name;
-{
-  Lisp_Object tail, elt;
-
-  for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail))
-    {
-      elt = XCAR (tail);
-      if (STRINGP (XCAR (elt)) && FLOATP (XCDR (elt))
-         && fast_c_string_match_ignore_case (XCAR (elt), name) >= 0)
-       return XFLOAT_DATA (XCDR (elt));
-    }
-  return 1.0;
-}
-
 static enum font_property_index font_props_for_sorting[FONT_SIZE_INDEX];
 
 static int
-compare_fonts_by_sort_order (v1, v2)
-     const void *v1, *v2;
+compare_fonts_by_sort_order (const void *v1, const void *v2)
 {
   Lisp_Object font1 = *(Lisp_Object *) v1;
   Lisp_Object font2 = *(Lisp_Object *) v2;
   int i;
-  
+
   for (i = 0; i < FONT_SIZE_INDEX; i++)
     {
       enum font_property_index idx = font_props_for_sorting[i];
@@ -1870,43 +1690,52 @@ the face font sort order.  */)
      (family, frame)
      Lisp_Object family, frame;
 {
-  struct frame *f = check_x_frame (frame);
-  Lisp_Object font_spec = Qnil, vec;
-  int i, nfonts;
+  Lisp_Object font_spec, list, *drivers, vec;
+  int i, nfonts, ndrivers;
   Lisp_Object result;
 
+  if (NILP (frame))
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame);
+
+  font_spec = Ffont_spec (0, NULL);
   if (!NILP (family))
     {
       CHECK_STRING (family);
-      font_spec = Ffont_spec (0, NULL);
-      Ffont_put (font_spec, QCfamily, family);
+      font_parse_family_registry (family, Qnil, font_spec);
     }
-  vec = font_list_entities (frame, font_spec);
-  nfonts = ASIZE (vec);
-  if (nfonts == 0)
+
+  list = font_list_entities (frame, font_spec);
+  if (NILP (list))
     return Qnil;
-  if (nfonts > 1)
-    {
-      for (i = 0; i < 4; i++)
-       switch (font_sort_order[i])
-         {
-         case XLFD_SWIDTH:
-           font_props_for_sorting[i] = FONT_WIDTH_INDEX; break;
-         case XLFD_POINT_SIZE:
-           font_props_for_sorting[i] = FONT_SIZE_INDEX; break;
-         case XLFD_WEIGHT:
-           font_props_for_sorting[i] = FONT_WEIGHT_INDEX; break;
-         default:
-           font_props_for_sorting[i] = FONT_SLANT_INDEX; break;
-         }
-      font_props_for_sorting[i++] = FONT_FAMILY_INDEX;
-      font_props_for_sorting[i++] = FONT_FOUNDRY_INDEX;
-      font_props_for_sorting[i++] = FONT_ADSTYLE_INDEX;
-      font_props_for_sorting[i++] = FONT_REGISTRY_INDEX;
 
-      qsort (XVECTOR (vec)->contents, nfonts, sizeof (Lisp_Object),
-            compare_fonts_by_sort_order);
-    }
+  /* Sort the font entities.  */
+  for (i = 0; i < 4; i++)
+    switch (font_sort_order[i])
+      {
+      case XLFD_SWIDTH:
+       font_props_for_sorting[i] = FONT_WIDTH_INDEX; break;
+      case XLFD_POINT_SIZE:
+       font_props_for_sorting[i] = FONT_SIZE_INDEX; break;
+      case XLFD_WEIGHT:
+       font_props_for_sorting[i] = FONT_WEIGHT_INDEX; break;
+      default:
+       font_props_for_sorting[i] = FONT_SLANT_INDEX; break;
+      }
+  font_props_for_sorting[i++] = FONT_FAMILY_INDEX;
+  font_props_for_sorting[i++] = FONT_FOUNDRY_INDEX;
+  font_props_for_sorting[i++] = FONT_ADSTYLE_INDEX;
+  font_props_for_sorting[i++] = FONT_REGISTRY_INDEX;
+
+  ndrivers = XINT (Flength (list));
+  drivers  = alloca (sizeof (Lisp_Object) * ndrivers);
+  for (i = 0; i < ndrivers; i++, list = XCDR (list))
+    drivers[i] = XCAR (list);
+  vec = Fvconcat (ndrivers, drivers);
+  nfonts = ASIZE (vec);
+
+  qsort (XVECTOR (vec)->contents, nfonts, sizeof (Lisp_Object),
+        compare_fonts_by_sort_order);
 
   result = Qnil;
   for (i = nfonts - 1; i >= 0; --i)
@@ -1919,13 +1748,13 @@ the face font sort order.  */)
       ASET (v, 0, AREF (font, FONT_FAMILY_INDEX));
       ASET (v, 1, FONT_WIDTH_SYMBOLIC (font));
       point = PIXEL_TO_POINT (XINT (AREF (font, FONT_SIZE_INDEX)) * 10,
-                             f->resy);
+                             XFRAME (frame)->resy);
       ASET (v, 2, make_number (point));
       ASET (v, 3, FONT_WEIGHT_SYMBOLIC (font));
       ASET (v, 4, FONT_SLANT_SYMBOLIC (font));
       spacing = Ffont_get (font, QCspacing);
       ASET (v, 5, (NILP (spacing) || EQ (spacing, Qp)) ? Qnil : Qt);
-      ASET (v, 6, AREF (font, FONT_NAME_INDEX));
+      ASET (v, 6, Ffont_xlfd_name (font, Qnil));
       ASET (v, 7, AREF (font, FONT_REGISTRY_INDEX));
 
       result = Fcons (v, result);
@@ -1934,33 +1763,20 @@ the face font sort order.  */)
   return result;
 }
 
-
-DEFUN ("x-font-family-list", Fx_font_family_list, Sx_font_family_list,
-       0, 1, 0,
-       doc: /* Return a list of available font families on FRAME.
-If FRAME is omitted or nil, use the selected frame.
-Value is a list of conses (FAMILY . FIXED-P) where FAMILY
-is a font family, and FIXED-P is non-nil if fonts of that family
-are fixed-pitch.  */)
-     (frame)
-     Lisp_Object frame;
-{
-  return Ffont_family_list (frame);
-}
-
-
 DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 5, 0,
        doc: /* Return a list of the names of available fonts matching PATTERN.
 If optional arguments FACE and FRAME are specified, return only fonts
 the same size as FACE on FRAME.
-PATTERN is a string, perhaps with wildcard characters;
+
+PATTERN should be a string containing a font name in the XLFD,
+Fontconfig, or GTK format.  A font name given in the XLFD format may
+contain wildcard characters:
   the * character matches any substring, and
   the ? character matches any single character.
   PATTERN is case-insensitive.
-FACE is a face name--a symbol.
 
 The return value is a list of strings, suitable as arguments to
-set-face-font.
+`set-face-font'.
 
 Fonts Emacs can't use may or may not be excluded
 even if they match PATTERN and FACE.
@@ -2026,15 +1842,35 @@ the WIDTH times as wide as FACE on FRAME.  */)
 
   {
     Lisp_Object font_spec;
-    Lisp_Object args[2];
+    Lisp_Object args[2], tail;
 
     font_spec = font_spec_from_name (pattern);
+    if (!FONTP (font_spec))
+      signal_error ("Invalid font name", pattern);
+
     if (size)
       {
        Ffont_put (font_spec, QCsize, make_number (size));
        Ffont_put (font_spec, QCavgwidth, make_number (avgwidth));
       }
-    args[0] = Flist_fonts (font_spec, frame, maximum, Qnil);
+    args[0] = Flist_fonts (font_spec, frame, maximum, font_spec);
+    for (tail = args[0]; CONSP (tail); tail = XCDR (tail))
+      {
+       Lisp_Object font_entity;
+
+       font_entity = XCAR (tail);
+       if ((NILP (AREF (font_entity, FONT_SIZE_INDEX))
+            || XINT (AREF (font_entity, FONT_SIZE_INDEX)) == 0)
+           && ! NILP (AREF (font_spec, FONT_SIZE_INDEX)))
+         {
+           /* This is a scalable font.  For backward compatibility,
+              we set the specified size. */
+           font_entity = Fcopy_font_spec (font_entity);
+           ASET (font_entity, FONT_SIZE_INDEX,
+                 AREF (font_spec, FONT_SIZE_INDEX));
+         }
+       XSETCAR (tail, Ffont_xlfd_name (font_entity, Qnil));
+      }
     if (NILP (frame))
       /* We don't have to check fontsets.  */
       return args[0];
@@ -2045,7 +1881,6 @@ the WIDTH times as wide as FACE on FRAME.  */)
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
-
 \f
 /***********************************************************************
                              Lisp Faces
@@ -2054,6 +1889,7 @@ the WIDTH times as wide as FACE on FRAME.  */)
 /* Access face attributes of face LFACE, a Lisp vector.  */
 
 #define LFACE_FAMILY(LFACE)        AREF ((LFACE), LFACE_FAMILY_INDEX)
+#define LFACE_FOUNDRY(LFACE)       AREF ((LFACE), LFACE_FOUNDRY_INDEX)
 #define LFACE_HEIGHT(LFACE)        AREF ((LFACE), LFACE_HEIGHT_INDEX)
 #define LFACE_WEIGHT(LFACE)        AREF ((LFACE), LFACE_WEIGHT_INDEX)
 #define LFACE_SLANT(LFACE)         AREF ((LFACE), LFACE_SLANT_INDEX)
@@ -2090,6 +1926,9 @@ check_lface_attrs (attrs)
   xassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
           || IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX])
           || STRINGP (attrs[LFACE_FAMILY_INDEX]));
+  xassert (UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
+          || IGNORE_DEFFACE_P (attrs[LFACE_FOUNDRY_INDEX])
+          || STRINGP (attrs[LFACE_FOUNDRY_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
           || IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX])
           || SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
@@ -2174,6 +2013,12 @@ check_lface (lface)
 \f
 /* Face-merge cycle checking.  */
 
+enum named_merge_point_kind
+{
+  NAMED_MERGE_POINT_NORMAL,
+  NAMED_MERGE_POINT_REMAP
+};
+
 /* A `named merge point' is simply a point during face-merging where we
    look up a face by name.  We keep a stack of which named lookups we're
    currently processing so that we can easily detect cycles, using a
@@ -2183,27 +2028,40 @@ check_lface (lface)
 struct named_merge_point
 {
   Lisp_Object face_name;
+  enum named_merge_point_kind named_merge_point_kind;
   struct named_merge_point *prev;
 };
 
 
 /* If a face merging cycle is detected for FACE_NAME, return 0,
    otherwise add NEW_NAMED_MERGE_POINT, which is initialized using
-   FACE_NAME, as the head of the linked list pointed to by
-   NAMED_MERGE_POINTS, and return 1.  */
+   FACE_NAME and NAMED_MERGE_POINT_KIND, as the head of the linked list
+   pointed to by NAMED_MERGE_POINTS, and return 1.  */
 
 static INLINE int
 push_named_merge_point (struct named_merge_point *new_named_merge_point,
                        Lisp_Object face_name,
+                       enum named_merge_point_kind named_merge_point_kind,
                        struct named_merge_point **named_merge_points)
 {
   struct named_merge_point *prev;
 
   for (prev = *named_merge_points; prev; prev = prev->prev)
     if (EQ (face_name, prev->face_name))
-      return 0;
+      {
+       if (prev->named_merge_point_kind == named_merge_point_kind)
+         /* A cycle, so fail.  */
+         return 0;
+       else if (prev->named_merge_point_kind == NAMED_MERGE_POINT_REMAP)
+         /* A remap `hides ' any previous normal merge points
+            (because the remap means that it's actually different face),
+            so as we know the current merge point must be normal, we
+            can just assume it's OK.  */
+         break;
+      }
 
   new_named_merge_point->face_name = face_name;
+  new_named_merge_point->named_merge_point_kind = named_merge_point_kind;
   new_named_merge_point->prev = *named_merge_points;
 
   *named_merge_points = new_named_merge_point;
@@ -2237,9 +2095,7 @@ resolve_face_name_error (ignore)
    Return default face in case of errors.  */
 
 static Lisp_Object
-resolve_face_name (face_name, signal_p)
-     Lisp_Object face_name;
-     int signal_p;
+resolve_face_name (Lisp_Object face_name, int signal_p)
 {
   Lisp_Object orig_face;
   Lisp_Object tortoise, hare;
@@ -2281,22 +2137,14 @@ resolve_face_name (face_name, signal_p)
 /* Return the face definition of FACE_NAME on frame F.  F null means
    return the definition for new frames.  FACE_NAME may be a string or
    a symbol (apparently Emacs 20.2 allowed strings as face names in
-   face text properties; Ediff uses that).  If FACE_NAME is an alias
-   for another face, return that face's definition.  If SIGNAL_P is
-   non-zero, signal an error if FACE_NAME is not a valid face name.
-   If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
-   name.  */
-
+   face text properties; Ediff uses that).  If SIGNAL_P is non-zero,
+   signal an error if FACE_NAME is not a valid face name.  If SIGNAL_P
+   is zero, value is nil if FACE_NAME is not a valid face name.  */
 static INLINE Lisp_Object
-lface_from_face_name (f, face_name, signal_p)
-     struct frame *f;
-     Lisp_Object face_name;
-     int signal_p;
+lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name, int signal_p)
 {
   Lisp_Object lface;
 
-  face_name = resolve_face_name (face_name, signal_p);
-
   if (f)
     lface = assq_no_quit (face_name, f->face_alist);
   else
@@ -2308,9 +2156,25 @@ lface_from_face_name (f, face_name, signal_p)
     signal_error ("Invalid face", face_name);
 
   check_lface (lface);
+
   return lface;
 }
 
+/* Return the face definition of FACE_NAME on frame F.  F null means
+   return the definition for new frames.  FACE_NAME may be a string or
+   a symbol (apparently Emacs 20.2 allowed strings as face names in
+   face text properties; Ediff uses that).  If FACE_NAME is an alias
+   for another face, return that face's definition.  If SIGNAL_P is
+   non-zero, signal an error if FACE_NAME is not a valid face name.
+   If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
+   name.  */
+static INLINE Lisp_Object
+lface_from_face_name (struct frame *f, Lisp_Object face_name, int signal_p)
+{
+  face_name = resolve_face_name (face_name, signal_p);
+  return lface_from_face_name_no_resolve (f, face_name, signal_p);
+}
+
 
 /* Get face attributes of face FACE_NAME from frame-local faces on
    frame F.  Store the resulting attributes in ATTRS which must point
@@ -2319,26 +2183,56 @@ lface_from_face_name (f, face_name, signal_p)
    Otherwise, value is zero if FACE_NAME is not a face.  */
 
 static INLINE int
-get_lface_attributes (f, face_name, attrs, signal_p)
-     struct frame *f;
-     Lisp_Object face_name;
-     Lisp_Object *attrs;
-     int signal_p;
+get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name, Lisp_Object *attrs, int signal_p)
 {
   Lisp_Object lface;
-  int success_p;
 
-  lface = lface_from_face_name (f, face_name, signal_p);
-  if (!NILP (lface))
+  lface = lface_from_face_name_no_resolve (f, face_name, signal_p);
+
+  if (! NILP (lface))
+    memcpy (attrs, XVECTOR (lface)->contents,
+           LFACE_VECTOR_SIZE * sizeof *attrs);
+
+  return !NILP (lface);
+}
+
+/* Get face attributes of face FACE_NAME from frame-local faces on frame
+   F.  Store the resulting attributes in ATTRS which must point to a
+   vector of Lisp_Objects of size LFACE_VECTOR_SIZE.  If FACE_NAME is an
+   alias for another face, use that face's definition.  If SIGNAL_P is
+   non-zero, signal an error if FACE_NAME does not name a face.
+   Otherwise, value is zero if FACE_NAME is not a face.  */
+
+static INLINE int
+get_lface_attributes (struct frame *f, Lisp_Object face_name, Lisp_Object *attrs, int signal_p, struct named_merge_point *named_merge_points)
+{
+  Lisp_Object face_remapping;
+
+  face_name = resolve_face_name (face_name, signal_p);
+
+  /* See if SYMBOL has been remapped to some other face (usually this
+     is done buffer-locally).  */
+  face_remapping = assq_no_quit (face_name, Vface_remapping_alist);
+  if (CONSP (face_remapping))
     {
-      bcopy (XVECTOR (lface)->contents, attrs,
-            LFACE_VECTOR_SIZE * sizeof *attrs);
-      success_p = 1;
+      struct named_merge_point named_merge_point;
+
+      if (push_named_merge_point (&named_merge_point,
+                                 face_name, NAMED_MERGE_POINT_REMAP,
+                                 &named_merge_points))
+       {
+         int i;
+
+         for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
+           attrs[i] = Qunspecified;
+
+         return merge_face_ref (f, XCDR (face_remapping), attrs,
+                                signal_p, named_merge_points);
+       }
     }
-  else
-    success_p = 0;
 
-  return success_p;
+  /* Default case, no remapping.  */
+  return get_lface_attributes_no_remap (f, face_name, attrs, signal_p);
 }
 
 
@@ -2346,20 +2240,13 @@ get_lface_attributes (f, face_name, attrs, signal_p)
    specified, i.e. are non-nil.  */
 
 static int
-lface_fully_specified_p (attrs)
-     Lisp_Object *attrs;
+lface_fully_specified_p (Lisp_Object *attrs)
 {
   int i;
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX)
-      if ((UNSPECIFIEDP (attrs[i]) || IGNORE_DEFFACE_P (attrs[i]))
-#ifdef MAC_OS
-        /* MAC_TODO: No stipple support on Mac OS yet, this index is
-           always unspecified.  */
-          && i != LFACE_STIPPLE_INDEX
-#endif
-          )
+      if ((UNSPECIFIEDP (attrs[i]) || IGNORE_DEFFACE_P (attrs[i])))
         break;
 
   return i == LFACE_VECTOR_SIZE;
@@ -2373,10 +2260,7 @@ lface_fully_specified_p (attrs)
    of FORCE_P.  */
 
 static int
-set_lface_from_font (f, lface, font_object, force_p)
-     struct frame *f;
-     Lisp_Object lface, font_object;
-     int force_p;
+set_lface_from_font (struct frame *f, Lisp_Object lface, Lisp_Object font_object, int force_p)
 {
   Lisp_Object val;
   struct font *font = XFONT_OBJECT (font_object);
@@ -2387,25 +2271,16 @@ set_lface_from_font (f, lface, font_object, force_p)
 
   if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
     {
-      Lisp_Object foundry = AREF (font_object, FONT_FOUNDRY_INDEX);
       Lisp_Object family = AREF (font_object, FONT_FAMILY_INDEX);
 
-      if (! NILP (foundry))
-       {
-         if (! NILP (family))
-           val = concat3 (SYMBOL_NAME (foundry), build_string ("-"),
-                          SYMBOL_NAME (family));
-         else
-           val = concat2 (SYMBOL_NAME (foundry), build_string ("-*"));
-       }
-      else
-       {
-         if (! NILP (family))
-           val = SYMBOL_NAME (family);
-         else
-           val = build_string ("*");
-       }
-      LFACE_FAMILY (lface) = val;
+      LFACE_FAMILY (lface) = SYMBOL_NAME (family);
+    }
+
+  if (force_p || UNSPECIFIEDP (LFACE_FOUNDRY (lface)))
+    {
+      Lisp_Object foundry = AREF (font_object, FONT_FOUNDRY_INDEX);
+
+      LFACE_FOUNDRY (lface) = SYMBOL_NAME (foundry);
     }
 
   if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
@@ -2443,13 +2318,10 @@ set_lface_from_font (f, lface, font_object, force_p)
    merged height.  If FROM is an invalid height, then INVALID is
    returned instead.  FROM and TO may be either absolute face heights or
    `relative' heights; the returned value is always an absolute height
-   unless both FROM and TO are relative.  GCPRO is a lisp value that
-   will be protected from garbage-collection if this function makes a
-   call into lisp.  */
+   unless both FROM and TO are relative.  */
 
 Lisp_Object
-merge_face_heights (from, to, invalid)
-     Lisp_Object from, to, invalid;
+merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
 {
   Lisp_Object result = invalid;
 
@@ -2494,14 +2366,11 @@ merge_face_heights (from, to, invalid)
    specified attribute of FROM overrides the corresponding attribute of
    TO; relative attributes in FROM are merged with the absolute value in
    TO and replace it.  NAMED_MERGE_POINTS is used internally to detect
-   loops in face inheritance; it should be 0 when called from other
-   places.  */
+   loops in face inheritance/remapping; it should be 0 when called from
+   other places.  */
 
 static INLINE void
-merge_face_vectors (f, from, to, named_merge_points)
-     struct frame *f;
-     Lisp_Object *from, *to;
-     struct named_merge_point *named_merge_points;
+merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to, struct named_merge_point *named_merge_points)
 {
   int i;
 
@@ -2521,6 +2390,16 @@ merge_face_vectors (f, from, to, named_merge_points)
        to[i] = Fmerge_font_spec (from[i], to[i]);
       else
        to[i] = Fcopy_font_spec (from[i]);
+      if (! NILP (AREF (to[i], FONT_FOUNDRY_INDEX)))
+       to[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (to[i], FONT_FOUNDRY_INDEX));
+      if (! NILP (AREF (to[i], FONT_FAMILY_INDEX)))
+       to[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (to[i], FONT_FAMILY_INDEX));
+      if (! NILP (AREF (to[i], FONT_WEIGHT_INDEX)))
+       to[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (to[i]);
+      if (! NILP (AREF (to[i], FONT_SLANT_INDEX)))
+       to[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (to[i]);
+      if (! NILP (AREF (to[i], FONT_WIDTH_INDEX)))
+       to[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (to[i]);
       ASET (to[i], FONT_SIZE_INDEX, Qnil);
     }
 
@@ -2532,12 +2411,14 @@ merge_face_vectors (f, from, to, named_merge_points)
            to[i] = merge_face_heights (from[i], to[i], to[i]);
            font_clear_prop (to, FONT_SIZE_INDEX);
          }
-       else if (i != LFACE_FONT_INDEX)
+       else if (i != LFACE_FONT_INDEX
+                && ! EQ (to[i], from[i]))
          {
            to[i] = from[i];
            if (i >= LFACE_FAMILY_INDEX && i <=LFACE_SLANT_INDEX)
              font_clear_prop (to,
                               (i == LFACE_FAMILY_INDEX ? FONT_FAMILY_INDEX
+                               : i == LFACE_FOUNDRY_INDEX ? FONT_FOUNDRY_INDEX
                                : i == LFACE_SWIDTH_INDEX ? FONT_WIDTH_INDEX
                                : i == LFACE_HEIGHT_INDEX ? FONT_SIZE_INDEX
                                : i == LFACE_WEIGHT_INDEX ? FONT_WEIGHT_INDEX
@@ -2545,11 +2426,6 @@ merge_face_vectors (f, from, to, named_merge_points)
          }
       }
 
-  /* If `font' attribute is specified, reflect the font properties in
-     it to the other attributes.  */
-  if (0 && !UNSPECIFIEDP (to[LFACE_FONT_INDEX]))
-    font_update_lface (f, to);
-
   /* TO is always an absolute face, which should inherit from nothing.
      We blindly copy the :inherit attribute above and fix it up here.  */
   to[LFACE_INHERIT_INDEX] = Qnil;
@@ -2561,20 +2437,17 @@ merge_face_vectors (f, from, to, named_merge_points)
    merging succeeded.  */
 
 static int
-merge_named_face (f, face_name, to, named_merge_points)
-     struct frame *f;
-     Lisp_Object face_name;
-     Lisp_Object *to;
-     struct named_merge_point *named_merge_points;
+merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to, struct named_merge_point *named_merge_points)
 {
   struct named_merge_point named_merge_point;
 
   if (push_named_merge_point (&named_merge_point,
-                             face_name, &named_merge_points))
+                             face_name, NAMED_MERGE_POINT_NORMAL,
+                             &named_merge_points))
     {
       struct gcpro gcpro1;
       Lisp_Object from[LFACE_VECTOR_SIZE];
-      int ok = get_lface_attributes (f, face_name, from, 0);
+      int ok = get_lface_attributes (f, face_name, from, 0, named_merge_points);
 
       if (ok)
        {
@@ -2614,12 +2487,7 @@ merge_named_face (f, face_name, to, named_merge_points)
    specifications.  */
 
 static int
-merge_face_ref (f, face_ref, to, err_msgs, named_merge_points)
-     struct frame *f;
-     Lisp_Object face_ref;
-     Lisp_Object *to;
-     int err_msgs;
-     struct named_merge_point *named_merge_points;
+merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to, int err_msgs, struct named_merge_point *named_merge_points)
 {
   int ok = 1;                  /* Succeed without an error? */
 
@@ -2672,6 +2540,16 @@ merge_face_ref (f, face_ref, to, err_msgs, named_merge_points)
                  else
                    err = 1;
                }
+             else if (EQ (keyword, QCfoundry))
+               {
+                 if (STRINGP (value))
+                   {
+                     to[LFACE_FOUNDRY_INDEX] = value;
+                     font_clear_prop (to, FONT_FOUNDRY_INDEX);
+                   }
+                 else
+                   err = 1;
+               }
              else if (EQ (keyword, QCheight))
                {
                  Lisp_Object new_height =
@@ -2768,7 +2646,7 @@ merge_face_ref (f, face_ref, to, err_msgs, named_merge_points)
                }
              else if (EQ (keyword, QCstipple))
                {
-#ifdef HAVE_X_WINDOWS
+#if defined(HAVE_X_WINDOWS) || defined(HAVE_NS)
                  Lisp_Object pixmap_p = Fbitmap_spec_p (value);
                  if (!NILP (pixmap_p))
                    to[LFACE_STIPPLE_INDEX] = value;
@@ -2924,6 +2802,7 @@ Value is a vector of face attributes.  */)
 DEFUN ("internal-lisp-face-p", Finternal_lisp_face_p,
        Sinternal_lisp_face_p, 1, 2, 0,
        doc: /* Return non-nil if FACE names a face.
+FACE should be a symbol or string.
 If optional second argument FRAME is non-nil, check for the
 existence of a frame-local face with name FACE on that frame.
 Otherwise check for the existence of a global face.  */)
@@ -2952,7 +2831,7 @@ DEFUN ("internal-copy-lisp-face", Finternal_copy_lisp_face,
 If FRAME is t, copy the global face definition of FROM.
 Otherwise, copy the frame-local definition of FROM on FRAME.
 If NEW-FRAME is a frame, copy that data into the frame-local
-definition of TO on NEW-FRAME.  If NEW-FRAME is nil.
+definition of TO on NEW-FRAME.  If NEW-FRAME is nil,
 FRAME controls where the data is copied to.
 
 The value is TO.  */)
@@ -2982,8 +2861,8 @@ The value is TO.  */)
       copy = Finternal_make_lisp_face (to, new_frame);
     }
 
-  bcopy (XVECTOR (lface)->contents, XVECTOR (copy)->contents,
-        LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
+  memcpy (XVECTOR (copy)->contents, XVECTOR (lface)->contents,
+         LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
 
   /* Changing a named face means that all realized faces depending on
      that face are invalid.  Since we cannot tell which realized faces
@@ -3072,21 +2951,38 @@ FRAME 0 means change the face on all frames, and change the default
       LFACE_FAMILY (lface) = value;
       prop_index = FONT_FAMILY_INDEX;
     }
+  else if (EQ (attr, QCfoundry))
+    {
+      if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+       {
+         CHECK_STRING (value);
+         if (SCHARS (value) == 0)
+           signal_error ("Invalid face foundry", value);
+       }
+      old_value = LFACE_FOUNDRY (lface);
+      LFACE_FOUNDRY (lface) = value;
+      prop_index = FONT_FOUNDRY_INDEX;
+    }
   else if (EQ (attr, QCheight))
     {
       if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
        {
-         Lisp_Object test;
-
-         test = (EQ (face, Qdefault)
-                 ? value
-                 /* The default face must have an absolute size,
-                    otherwise, we do a test merge with a random
-                    height to see if VALUE's ok. */
-                 : merge_face_heights (value, make_number (10), Qnil));
-
-         if (!INTEGERP (test) || XINT (test) <= 0)
-           signal_error ("Invalid face height", value);
+         if (EQ (face, Qdefault))
+           {
+             /* The default face must have an absolute size.  */
+             if (!INTEGERP (value) || XINT (value) <= 0)
+               signal_error ("Invalid default face height", value);
+           }
+         else
+           {
+             /* For non-default faces, do a test merge with a random
+                height to see if VALUE's ok. */
+             Lisp_Object test = merge_face_heights (value,
+                                                    make_number (10),
+                                                    Qnil);
+             if (!INTEGERP (test) || XINT (test) <= 0)
+               signal_error ("Invalid face height", value);
+           }
        }
 
       old_value = LFACE_HEIGHT (lface);
@@ -3236,6 +3132,9 @@ FRAME 0 means change the face on all frames, and change the default
     }
   else if (EQ (attr, QCforeground))
     {
+      /* Compatibility with 20.x.  */
+      if (NILP (value))
+       value = Qunspecified;
       if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
        {
          /* Don't check for valid color names here because it depends
@@ -3250,6 +3149,9 @@ FRAME 0 means change the face on all frames, and change the default
     }
   else if (EQ (attr, QCbackground))
     {
+      /* Compatibility with 20.x.  */
+      if (NILP (value))
+       value = Qunspecified;
       if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
        {
          /* Don't check for valid color names here because it depends
@@ -3264,14 +3166,14 @@ FRAME 0 means change the face on all frames, and change the default
     }
   else if (EQ (attr, QCstipple))
     {
-#ifdef HAVE_X_WINDOWS
+#if defined(HAVE_X_WINDOWS) || defined(HAVE_NS)
       if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
          && !NILP (value)
          && NILP (Fbitmap_spec_p (value)))
        signal_error ("Invalid stipple attribute", value);
       old_value = LFACE_STIPPLE (lface);
       LFACE_STIPPLE (lface) = value;
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_X_WINDOWS || HAVE_NS */
     }
   else if (EQ (attr, QCwidth))
     {
@@ -3299,12 +3201,14 @@ FRAME 0 means change the face on all frames, and change the default
                {
                  if (STRINGP (value))
                    {
-                     int fontset = fs_query_fontset (value, 0);
+                     Lisp_Object name = value;
+                     int fontset = fs_query_fontset (name, 0);
 
                      if (fontset >= 0)
-                       value = fontset_ascii (fontset);
-                     else
-                       value = font_spec_from_name (value);
+                       name = fontset_ascii (fontset);
+                     value = font_spec_from_name (name);
+                     if (!FONTP (value))
+                       signal_error ("Invalid font name", name);
                    }
                  else
                    signal_error ("Invalid font or font-spec", value);
@@ -3376,12 +3280,15 @@ FRAME 0 means change the face on all frames, and change the default
     signal_error ("Invalid face attribute name", attr);
 
   if (prop_index)
-    /* If a font-related attribute other than QCfont and QCfontset is
-       specified, and if the original QCfont attribute has a font
-       (font-spec or font-object), set the corresponding property in
-       the font to nil so that the font selector doesn't think that
-       the attribute is mandatory.  */
-    font_clear_prop (XVECTOR (lface)->contents, prop_index);
+    {
+      /* If a font-related attribute other than QCfont and QCfontset
+        is specified, and if the original QCfont attribute has a font
+        (font-spec or font-object), set the corresponding property in
+        the font to nil so that the font selector doesn't think that
+        the attribute is mandatory.  Also, clear the average
+        width.  */
+      font_clear_prop (XVECTOR (lface)->contents, prop_index);
+    }
 
   /* Changing a named face means that all realized faces depending on
      that face are invalid.  Since we cannot tell which realized faces
@@ -3494,41 +3401,11 @@ FRAME 0 means change the face on all frames, and change the default
 }
 
 
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* Set the `font' frame parameter of FRAME determined from the
-   font-object set in `default' face attributes LFACE.  */
-
-static void
-set_font_frame_param (frame, lface)
-     Lisp_Object frame, lface;
-{
-  struct frame *f = XFRAME (frame);
-
-  if (FRAME_WINDOW_P (f))
-    {
-      Lisp_Object font = LFACE_FONT (lface);
-
-      if (FONT_SPEC_P (font))
-       {
-         font = font_load_for_lface (f, XVECTOR (lface)->contents, font);
-         if (NILP (font))
-           return;
-         LFACE_FONT (lface) = font;
-       }
-      f->default_face_done_p = 0;
-      Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font), Qnil));
-    }
-}
-
-
 /* Update the corresponding face when frame parameter PARAM on frame F
    has been assigned the value NEW_VALUE.  */
 
 void
-update_face_from_frame_parameter (f, param, new_value)
-     struct frame *f;
-     Lisp_Object param, new_value;
+update_face_from_frame_parameter (struct frame *f, Lisp_Object param, Lisp_Object new_value)
 {
   Lisp_Object face = Qnil;
   Lisp_Object lface;
@@ -3553,7 +3430,7 @@ update_face_from_frame_parameter (f, param, new_value)
 
       /* Changing the background color might change the background
         mode, so that we have to load new defface specs.
-        Call frame-set-background-mode to do that.  */
+        Call frame-update-face-colors to do that.  */
       XSETFRAME (frame, f);
       call1 (Qframe_set_background_mode, frame);
 
@@ -3563,6 +3440,7 @@ update_face_from_frame_parameter (f, param, new_value)
                                  ? new_value : Qunspecified);
       realize_basic_faces (f);
     }
+#ifdef HAVE_WINDOW_SYSTEM
   else if (EQ (param, Qborder_color))
     {
       face = Qborder;
@@ -3584,6 +3462,7 @@ update_face_from_frame_parameter (f, param, new_value)
       LFACE_BACKGROUND (lface) = (STRINGP (new_value)
                                  ? new_value : Qunspecified);
     }
+#endif
 
   /* Changing a named face means that all realized faces depending on
      that face are invalid.  Since we cannot tell which realized faces
@@ -3599,6 +3478,36 @@ update_face_from_frame_parameter (f, param, new_value)
 }
 
 
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* Set the `font' frame parameter of FRAME determined from the
+   font-object set in `default' face attributes LFACE.  */
+
+static void
+set_font_frame_param (Lisp_Object frame, Lisp_Object lface)
+{
+  struct frame *f = XFRAME (frame);
+  Lisp_Object font;
+
+  if (FRAME_WINDOW_P (f)
+      /* Don't do anything if the font is `unspecified'.  This can
+        happen during frame creation.  */
+      && (font = LFACE_FONT (lface),
+         ! UNSPECIFIEDP (font)))
+    {
+      if (FONT_SPEC_P (font))
+       {
+         font = font_load_for_lface (f, XVECTOR (lface)->contents, font);
+         if (NILP (font))
+           return;
+         LFACE_FONT (lface) = font;
+       }
+      f->default_face_done_p = 0;
+      Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font), Qnil));
+    }
+}
+
+
 /* Get the value of X resource RESOURCE, class CLASS for the display
    of frame FRAME.  This is here because ordinary `x-get-resource'
    doesn't take a frame argument.  */
@@ -3626,21 +3535,19 @@ DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
    error; if SIGNAL_P is zero, return 0.  */
 
 static Lisp_Object
-face_boolean_x_resource_value (value, signal_p)
-     Lisp_Object value;
-     int signal_p;
+face_boolean_x_resource_value (Lisp_Object value, int signal_p)
 {
   Lisp_Object result = make_number (0);
 
   xassert (STRINGP (value));
 
-  if (xstricmp (SDATA (value), "on") == 0
-      || xstricmp (SDATA (value), "true") == 0)
+  if (xstrcasecmp (SDATA (value), "on") == 0
+      || xstrcasecmp (SDATA (value), "true") == 0)
     result = Qt;
-  else if (xstricmp (SDATA (value), "off") == 0
-          || xstricmp (SDATA (value), "false") == 0)
+  else if (xstrcasecmp (SDATA (value), "off") == 0
+          || xstrcasecmp (SDATA (value), "false") == 0)
     result = Qnil;
-  else if (xstricmp (SDATA (value), "unspecified") == 0)
+  else if (xstrcasecmp (SDATA (value), "unspecified") == 0)
     result = Qunspecified;
   else if (signal_p)
     signal_error ("Invalid face attribute value from X resource", value);
@@ -3660,7 +3567,7 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
   CHECK_SYMBOL (attr);
   CHECK_STRING (value);
 
-  if (xstricmp (SDATA (value), "unspecified") == 0)
+  if (xstrcasecmp (SDATA (value), "unspecified") == 0)
     value = Qunspecified;
   else if (EQ (attr, QCheight))
     {
@@ -3750,13 +3657,18 @@ x_update_menu_appearance (f)
        }
 
       if (face->font
+         /* On Solaris 5.8, it's been reported that the `menu' face
+            can be unspecified here, during startup.  Why this
+            happens remains unknown.  -- cyd  */
+         && FONTP (LFACE_FONT (lface))
          && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
+             || !UNSPECIFIEDP (LFACE_FOUNDRY (lface))
              || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
              || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
              || !UNSPECIFIEDP (LFACE_SLANT (lface))
              || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
        {
-         Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface));
+         Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface), Qnil);
 #ifdef USE_MOTIF
          const char *suffix = "List";
          Bool motif = True;
@@ -3774,7 +3686,7 @@ x_update_menu_appearance (f)
            {
 #if defined HAVE_X_I18N
              extern char *xic_create_fontsetname
-               P_ ((char *base_fontname, Bool motif));
+                (char *base_fontname, Bool motif);
              char *fontsetname = xic_create_fontsetname (SDATA (xlfd), motif);
 #else
              char *fontsetname = (char *) SDATA (xlfd);
@@ -3867,6 +3779,8 @@ frames).  If FRAME is omitted or nil, use the selected frame.  */)
 
   if (EQ (keyword, QCfamily))
     value = LFACE_FAMILY (lface);
+  else if (EQ (keyword, QCfoundry))
+    value = LFACE_FOUNDRY (lface);
   else if (EQ (keyword, QCheight))
     value = LFACE_HEIGHT (lface);
   else if (EQ (keyword, QCweight))
@@ -3942,10 +3856,11 @@ Default face attributes override any local face attributes.  */)
 {
   int i;
   Lisp_Object global_lface, local_lface, *gvec, *lvec;
+  struct frame *f = XFRAME (frame);
 
   CHECK_LIVE_FRAME (frame);
   global_lface = lface_from_face_name (NULL, face, 1);
-  local_lface = lface_from_face_name (XFRAME (frame), face, 0);
+  local_lface = lface_from_face_name (f, face, 0);
   if (NILP (local_lface))
     local_lface = Finternal_make_lisp_face (face, frame);
 
@@ -3957,13 +3872,44 @@ Default face attributes override any local face attributes.  */)
   lvec = XVECTOR (local_lface)->contents;
   gvec = XVECTOR (global_lface)->contents;
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-    if (! UNSPECIFIEDP (gvec[i]))
-      {
-       if (IGNORE_DEFFACE_P (gvec[i]))
-         lvec[i] = Qunspecified;
-       else
-         lvec[i] = gvec[i];
-      }
+    if (IGNORE_DEFFACE_P (gvec[i]))
+      lvec[i] = Qunspecified;
+    else if (! UNSPECIFIEDP (gvec[i]))
+      lvec[i] = gvec[i];
+
+  /* If the default face was changed, update the face cache and the
+     `font' frame parameter.  */
+  if (EQ (face, Qdefault))
+    {
+      struct face_cache *c = FRAME_FACE_CACHE (f);
+      struct face *newface, *oldface = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+      Lisp_Object attrs[LFACE_VECTOR_SIZE];
+
+      /* This can be NULL (e.g., in batch mode).  */
+      if (oldface)
+       {
+         /* Ensure that the face vector is fully specified by merging
+            the previously-cached vector.  */
+         memcpy (attrs, oldface->lface, sizeof attrs);
+         merge_face_vectors (f, lvec, attrs, 0);
+         memcpy (lvec, attrs, sizeof attrs);
+         newface = realize_face (c, lvec, DEFAULT_FACE_ID);
+
+         if ((! UNSPECIFIEDP (gvec[LFACE_FAMILY_INDEX])
+              || ! UNSPECIFIEDP (gvec[LFACE_FOUNDRY_INDEX])
+              || ! UNSPECIFIEDP (gvec[LFACE_HEIGHT_INDEX])
+              || ! UNSPECIFIEDP (gvec[LFACE_WEIGHT_INDEX])
+              || ! UNSPECIFIEDP (gvec[LFACE_SLANT_INDEX])
+              || ! UNSPECIFIEDP (gvec[LFACE_SWIDTH_INDEX])
+              || ! UNSPECIFIEDP (gvec[LFACE_FONT_INDEX]))
+             && newface->font)
+           {
+             Lisp_Object name = newface->font->props[FONT_NAME_INDEX];
+             Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, name),
+                                                     Qnil));
+           }
+       }
+    }
 
   return Qnil;
 }
@@ -4017,10 +3963,15 @@ return the font name used for CHARACTER.  */)
          face_id = FACE_FOR_CHAR (f, face, XINT (character), -1, Qnil);
          face = FACE_FROM_ID (f, face_id);
        }
-#endif
       return (face->font
              ? face->font->props[FONT_NAME_INDEX]
              : Qnil);
+#else  /* !HAVE_WINDOW_SYSTEM */
+      return build_string (FRAME_MSDOS_P (f)
+                          ? "ms-dos"
+                          : FRAME_W32_P (f) ? "w32term"
+                          :"tty");
+#endif
     }
 }
 
@@ -4030,8 +3981,7 @@ return the font name used for CHARACTER.  */)
    is called quite often.  */
 
 static INLINE int
-face_attr_equal_p (v1, v2)
-     Lisp_Object v1, v2;
+face_attr_equal_p (Lisp_Object v1, Lisp_Object v2)
 {
   /* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
      and the other is specified.  */
@@ -4047,9 +3997,9 @@ face_attr_equal_p (v1, v2)
       if (SBYTES (v1) != SBYTES (v2))
        return 0;
 
-      return bcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
+      return memcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
 
-    case Lisp_Int:
+    case_Lisp_Int:
     case Lisp_Symbol:
       return 0;
 
@@ -4064,8 +4014,7 @@ face_attr_equal_p (v1, v2)
    is called quite often.  */
 
 static INLINE int
-lface_equal_p (v1, v2)
-     Lisp_Object *v1, *v2;
+lface_equal_p (Lisp_Object *v1, Lisp_Object *v2)
 {
   int i, equal_p = 1;
 
@@ -4153,8 +4102,7 @@ For internal use only.  */)
    below in computing a hash value for a Lisp face.  */
 
 static INLINE unsigned
-hash_string_case_insensitive (string)
-     Lisp_Object string;
+hash_string_case_insensitive (Lisp_Object string)
 {
   const unsigned char *s;
   unsigned hash = 0;
@@ -4168,10 +4116,10 @@ hash_string_case_insensitive (string)
 /* Return a hash code for face attribute vector V.  */
 
 static INLINE unsigned
-lface_hash (v)
-     Lisp_Object *v;
+lface_hash (Lisp_Object *v)
 {
   return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
+         ^ hash_string_case_insensitive (v[LFACE_FOUNDRY_INDEX])
          ^ hash_string_case_insensitive (v[LFACE_FOREGROUND_INDEX])
          ^ hash_string_case_insensitive (v[LFACE_BACKGROUND_INDEX])
          ^ XHASH (v[LFACE_WEIGHT_INDEX])
@@ -4187,13 +4135,14 @@ lface_hash (v)
    LFACE1 and LFACE2 must be fully-specified.  */
 
 static INLINE int
-lface_same_font_attributes_p (lface1, lface2)
-     Lisp_Object *lface1, *lface2;
+lface_same_font_attributes_p (Lisp_Object *lface1, Lisp_Object *lface2)
 {
   xassert (lface_fully_specified_p (lface1)
           && lface_fully_specified_p (lface2));
-  return (xstricmp (SDATA (lface1[LFACE_FAMILY_INDEX]),
-                   SDATA (lface2[LFACE_FAMILY_INDEX])) == 0
+  return (xstrcasecmp (SDATA (lface1[LFACE_FAMILY_INDEX]),
+                       SDATA (lface2[LFACE_FAMILY_INDEX])) == 0
+         && xstrcasecmp (SDATA (lface1[LFACE_FOUNDRY_INDEX]),
+                         SDATA (lface2[LFACE_FOUNDRY_INDEX])) == 0
          && EQ (lface1[LFACE_HEIGHT_INDEX], lface2[LFACE_HEIGHT_INDEX])
          && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
          && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
@@ -4202,8 +4151,8 @@ lface_same_font_attributes_p (lface1, lface2)
          && (EQ (lface1[LFACE_FONTSET_INDEX], lface2[LFACE_FONTSET_INDEX])
              || (STRINGP (lface1[LFACE_FONTSET_INDEX])
                  && STRINGP (lface2[LFACE_FONTSET_INDEX])
-                 && ! xstricmp (SDATA (lface1[LFACE_FONTSET_INDEX]),
-                                SDATA (lface2[LFACE_FONTSET_INDEX]))))
+                 && ! xstrcasecmp (SDATA (lface1[LFACE_FONTSET_INDEX]),
+                                    SDATA (lface2[LFACE_FONTSET_INDEX]))))
          );
 }
 
@@ -4217,13 +4166,12 @@ lface_same_font_attributes_p (lface1, lface2)
    vector ATTR.  */
 
 static struct face *
-make_realized_face (attr)
-     Lisp_Object *attr;
+make_realized_face (Lisp_Object *attr)
 {
   struct face *face = (struct face *) xmalloc (sizeof *face);
-  bzero (face, sizeof *face);
+  memset (face, 0, sizeof *face);
   face->ascii_face = face;
-  bcopy (attr, face->lface, sizeof face->lface);
+  memcpy (face->lface, attr, sizeof face->lface);
   return face;
 }
 
@@ -4232,9 +4180,7 @@ make_realized_face (attr)
    be null.  */
 
 void
-free_realized_face (f, face)
-     struct frame *f;
-     struct face *face;
+free_realized_face (struct frame *f, struct face *face)
 {
   if (face)
     {
@@ -4269,9 +4215,7 @@ free_realized_face (f, face)
    by clearing the face cache.  */
 
 void
-prepare_face_for_display (f, face)
-     struct frame *f;
-     struct face *face;
+prepare_face_for_display (struct frame *f, struct face *face)
 {
 #ifdef HAVE_WINDOW_SYSTEM
   xassert (FRAME_WINDOW_P (f));
@@ -4308,8 +4252,7 @@ prepare_face_for_display (f, face)
 /* Returns the `distance' between the colors X and Y.  */
 
 static int
-color_distance (x, y)
-     XColor *x, *y;
+color_distance (XColor *x, XColor *y)
 {
   /* This formula is from a paper title `Colour metric' by Thiadmer Riemersma.
      Quoting from that paper:
@@ -4367,17 +4310,16 @@ If FRAME is unspecified or nil, the current frame is used.  */)
 /* Return a new face cache for frame F.  */
 
 static struct face_cache *
-make_face_cache (f)
-     struct frame *f;
+make_face_cache (struct frame *f)
 {
   struct face_cache *c;
   int size;
 
   c = (struct face_cache *) xmalloc (sizeof *c);
-  bzero (c, sizeof *c);
+  memset (c, 0, sizeof *c);
   size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
   c->buckets = (struct face **) xmalloc (size);
-  bzero (c->buckets, size);
+  memset (c->buckets, 0, size);
   c->size = 50;
   c->faces_by_id = (struct face **) xmalloc (c->size * sizeof *c->faces_by_id);
   c->f = f;
@@ -4391,8 +4333,7 @@ make_face_cache (f)
    keeping too many graphics contexts that are no longer needed.  */
 
 static void
-clear_face_gcs (c)
-     struct face_cache *c;
+clear_face_gcs (struct face_cache *c)
 {
   if (c && FRAME_WINDOW_P (c->f))
     {
@@ -4422,8 +4363,7 @@ clear_face_gcs (c)
    event doesn't try to use faces we destroyed.  */
 
 static void
-free_realized_faces (c)
-     struct face_cache *c;
+free_realized_faces (struct face_cache *c)
 {
   if (c && c->used)
     {
@@ -4443,7 +4383,7 @@ free_realized_faces (c)
 
       c->used = 0;
       size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
-      bzero (c->buckets, size);
+      memset (c->buckets, 0, size);
 
       /* Must do a thorough redisplay the next time.  Mark current
         matrices as invalid because they will reference faces freed
@@ -4463,9 +4403,7 @@ free_realized_faces (c)
 /* Free all realized faces that are using FONTSET on frame F.  */
 
 void
-free_realized_faces_for_fontset (f, fontset)
-     struct frame *f;
-     int fontset;
+free_realized_faces_for_fontset (struct frame *f, int fontset)
 {
   struct face_cache *cache = FRAME_FACE_CACHE (f);
   struct face *face;
@@ -4506,8 +4444,7 @@ free_realized_faces_for_fontset (f, fontset)
    because we can't tell which realized faces depend on that face.  */
 
 void
-free_all_realized_faces (frame)
-     Lisp_Object frame;
+free_all_realized_faces (Lisp_Object frame)
 {
   if (NILP (frame))
     {
@@ -4523,8 +4460,7 @@ free_all_realized_faces (frame)
 /* Free face cache C and faces in it, including their X resources.  */
 
 static void
-free_face_cache (c)
-     struct face_cache *c;
+free_face_cache (struct face_cache *c)
 {
   if (c)
     {
@@ -4544,10 +4480,7 @@ free_face_cache (c)
    that a requested face is not cached.  */
 
 static void
-cache_face (c, face, hash)
-     struct face_cache *c;
-     struct face *face;
-     unsigned hash;
+cache_face (struct face_cache *c, struct face *face, unsigned int hash)
 {
   int i = hash % FACE_CACHE_BUCKETS_SIZE;
 
@@ -4624,9 +4557,7 @@ cache_face (c, face, hash)
 /* Remove face FACE from cache C.  */
 
 static void
-uncache_face (c, face)
-     struct face_cache *c;
-     struct face *face;
+uncache_face (struct face_cache *c, struct face *face)
 {
   int i = face->hash % FACE_CACHE_BUCKETS_SIZE;
 
@@ -4650,9 +4581,7 @@ uncache_face (c, face)
    realize a new one.  */
 
 INLINE int
-lookup_face (f, attr)
-     struct frame *f;
-     Lisp_Object *attr;
+lookup_face (struct frame *f, Lisp_Object *attr)
 {
   struct face_cache *cache = FRAME_FACE_CACHE (f);
   unsigned hash;
@@ -4698,10 +4627,7 @@ lookup_face (f, attr)
    suitable face is found, realize a new one.  */
 
 int
-face_for_font (f, font_object, base_face)
-     struct frame *f;
-     Lisp_Object font_object;
-     struct face *base_face;
+face_for_font (struct frame *f, Lisp_Object font_object, struct face *base_face)
 {
   struct face_cache *cache = FRAME_FACE_CACHE (f);
   unsigned hash;
@@ -4736,10 +4662,7 @@ face_for_font (f, font_object, base_face)
    face isn't realized and cannot be realized.  */
 
 int
-lookup_named_face (f, symbol, signal_p)
-     struct frame *f;
-     Lisp_Object symbol;
-     int signal_p;
+lookup_named_face (struct frame *f, Lisp_Object symbol, int signal_p)
 {
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
@@ -4754,23 +4677,71 @@ lookup_named_face (f, symbol, signal_p)
        abort ();  /* realize_basic_faces must have set it up  */
     }
 
-  if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p))
+  if (! get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
     return -1;
 
-  bcopy (default_face->lface, attrs, sizeof attrs);
+  memcpy (attrs, default_face->lface, sizeof attrs);
   merge_face_vectors (f, symbol_attrs, attrs, 0);
 
   return lookup_face (f, attrs);
 }
 
 
+/* Return the display face-id of the basic face who's canonical face-id
+   is FACE_ID.  The return value will usually simply be FACE_ID, unless that
+   basic face has bee remapped via Vface_remapping_alist.  This function is
+   conservative: if something goes wrong, it will simply return FACE_ID
+   rather than signal an error.   */
+
+int
+lookup_basic_face (struct frame *f, int face_id)
+{
+  Lisp_Object name, mapping;
+  int remapped_face_id;
+
+  if (NILP (Vface_remapping_alist))
+    return face_id;            /* Nothing to do.  */
+
+  switch (face_id)
+    {
+    case DEFAULT_FACE_ID:              name = Qdefault;                break;
+    case MODE_LINE_FACE_ID:            name = Qmode_line;              break;
+    case MODE_LINE_INACTIVE_FACE_ID:   name = Qmode_line_inactive;     break;
+    case HEADER_LINE_FACE_ID:          name = Qheader_line;            break;
+    case TOOL_BAR_FACE_ID:             name = Qtool_bar;               break;
+    case FRINGE_FACE_ID:               name = Qfringe;                 break;
+    case SCROLL_BAR_FACE_ID:           name = Qscroll_bar;             break;
+    case BORDER_FACE_ID:               name = Qborder;                 break;
+    case CURSOR_FACE_ID:               name = Qcursor;                 break;
+    case MOUSE_FACE_ID:                        name = Qmouse;                  break;
+    case MENU_FACE_ID:                 name = Qmenu;                   break;
+
+    default:
+      abort ();            /* the caller is supposed to pass us a basic face id */
+    }
+
+  /* Do a quick scan through Vface_remapping_alist, and return immediately
+     if there is no remapping for face NAME.  This is just an optimization
+     for the very common no-remapping case.  */
+  mapping = assq_no_quit (name, Vface_remapping_alist);
+  if (NILP (mapping))
+    return face_id;            /* Give up.  */
+
+  /* If there is a remapping entry, lookup the face using NAME, which will
+     handle the remapping too.  */
+  remapped_face_id = lookup_named_face (f, name, 0);
+  if (remapped_face_id < 0)
+    return face_id;            /* Give up. */
+
+  return remapped_face_id;
+}
+
+
 /* Return the ID of the realized ASCII face of Lisp face with ID
    LFACE_ID on frame F.  Value is -1 if LFACE_ID isn't valid.  */
 
 int
-ascii_face_of_lisp_face (f, lface_id)
-     struct frame *f;
-     int lface_id;
+ascii_face_of_lisp_face (struct frame *f, int lface_id)
 {
   int face_id;
 
@@ -4791,9 +4762,7 @@ ascii_face_of_lisp_face (f, lface_id)
    STEPS < 0 means larger.  Value is the id of the face.  */
 
 int
-smaller_face (f, face_id, steps)
-     struct frame *f;
-     int face_id, steps;
+smaller_face (struct frame *f, int face_id, int steps)
 {
 #ifdef HAVE_WINDOW_SYSTEM
   struct face *face;
@@ -4812,7 +4781,7 @@ smaller_face (f, face_id, steps)
   steps = eabs (steps);
 
   face = FACE_FROM_ID (f, face_id);
-  bcopy (face->lface, attrs, sizeof attrs);
+  memcpy (attrs, face->lface, sizeof attrs);
   pt = last_pt = XFASTINT (attrs[LFACE_HEIGHT_INDEX]);
   new_face_id = face_id;
   last_height = FONT_HEIGHT (face->font);
@@ -4852,10 +4821,7 @@ smaller_face (f, face_id, steps)
    FACE_ID on frame F, but has height HEIGHT.  */
 
 int
-face_with_height (f, face_id, height)
-     struct frame *f;
-     int face_id;
-     int height;
+face_with_height (struct frame *f, int face_id, int height)
 {
 #ifdef HAVE_WINDOW_SYSTEM
   struct face *face;
@@ -4866,8 +4832,9 @@ face_with_height (f, face_id, height)
     return face_id;
 
   face = FACE_FROM_ID (f, face_id);
-  bcopy (face->lface, attrs, sizeof attrs);
+  memcpy (attrs, face->lface, sizeof attrs);
   attrs[LFACE_HEIGHT_INDEX] = make_number (height);
+  font_clear_prop (attrs, FONT_SIZE_INDEX);
   face_id = lookup_face (f, attrs);
 #endif /* HAVE_WINDOW_SYSTEM */
 
@@ -4883,11 +4850,7 @@ face_with_height (f, face_id, height)
    default face.  FACE_ID is assumed to be already realized.  */
 
 int
-lookup_derived_face (f, symbol, face_id, signal_p)
-     struct frame *f;
-     Lisp_Object symbol;
-     int face_id;
-     int signal_p;
+lookup_derived_face (struct frame *f, Lisp_Object symbol, int face_id, int signal_p)
 {
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
@@ -4896,8 +4859,10 @@ lookup_derived_face (f, symbol, face_id, signal_p)
   if (!default_face)
     abort ();
 
-  get_lface_attributes (f, symbol, symbol_attrs, signal_p);
-  bcopy (default_face->lface, attrs, sizeof attrs);
+  if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
+    return -1;
+
+  memcpy (attrs, default_face->lface, sizeof attrs);
   merge_face_vectors (f, symbol_attrs, attrs, 0);
   return lookup_face (f, attrs);
 }
@@ -4942,10 +4907,7 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
     \(2) `close in spirit' to what the attributes specify, if not exact.  */
 
 static int
-x_supports_face_attributes_p (f, attrs, def_face)
-     struct frame *f;
-     Lisp_Object *attrs;
-     struct face *def_face;
+x_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs, struct face *def_face)
 {
   Lisp_Object *def_attrs = def_face->lface;
 
@@ -4980,6 +4942,7 @@ x_supports_face_attributes_p (f, attrs, def_face)
   /* Check font-related attributes, as those are the most commonly
      "unsupported" on a window-system (because of missing fonts).  */
   if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
+      || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
       || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
       || !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
       || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
@@ -4990,7 +4953,7 @@ x_supports_face_attributes_p (f, attrs, def_face)
       Lisp_Object merged_attrs[LFACE_VECTOR_SIZE];
       int i;
 
-      bcopy (def_attrs, merged_attrs, sizeof merged_attrs);
+      memcpy (merged_attrs, def_attrs, sizeof merged_attrs);
 
       merge_face_vectors (f, attrs, merged_attrs, 0);
 
@@ -5000,8 +4963,10 @@ x_supports_face_attributes_p (f, attrs, def_face)
       if (! face)
        error ("Cannot make face");
 
-      /* If the font is the same, then not supported.  */
-      if (face->font == def_face->font)
+      /* If the font is the same, or no font is found, then not
+        supported.  */
+      if (face->font == def_face->font
+         || ! face->font)
        return 0;
       for (i = FONT_TYPE_INDEX; i <= FONT_SIZE_INDEX; i++)
        if (! EQ (face->font->props[i], def_face->font->props[i]))
@@ -5043,10 +5008,7 @@ x_supports_face_attributes_p (f, attrs, def_face)
    substitution of a `dim' face for italic.  */
 
 static int
-tty_supports_face_attributes_p (f, attrs, def_face)
-     struct frame *f;
-     Lisp_Object *attrs;
-     struct face *def_face;
+tty_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs, struct face *def_face)
 {
   int weight;
   Lisp_Object val, fg, bg;
@@ -5065,6 +5027,7 @@ tty_supports_face_attributes_p (f, attrs, def_face)
      because the faked result is too different from what the face
      specifies.  */
   if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
+      || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
       || !UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
       || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
       || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
@@ -5078,8 +5041,9 @@ tty_supports_face_attributes_p (f, attrs, def_face)
   /* Test for terminal `capabilities' (non-color character attributes).  */
 
   /* font weight (bold/dim) */
-  weight = FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]);
-  if (weight >= 0)
+  val = attrs[LFACE_WEIGHT_INDEX];
+  if (!UNSPECIFIEDP (val)
+      && (weight = FONT_WEIGHT_NAME_NUMERIC (val), weight >= 0))
     {
       int def_weight = FONT_WEIGHT_NAME_NUMERIC (def_attrs[LFACE_WEIGHT_INDEX]);
 
@@ -5292,7 +5256,7 @@ face for italic.  */)
                            Font selection
  ***********************************************************************/
 
- DEFUN ("internal-set-font-selection-order",
+DEFUN ("internal-set-font-selection-order",
        Finternal_set_font_selection_order,
        Sinternal_set_font_selection_order, 1, 1, 0,
        doc: /* Set font selection order for face font selection to ORDER.
@@ -5310,7 +5274,7 @@ Value is ORDER.  */)
   int indices[DIM (font_sort_order)];
 
   CHECK_LIST (order);
-  bzero (indices, sizeof indices);
+  memset (indices, 0, sizeof indices);
   i = 0;
 
   for (list = order;
@@ -5342,9 +5306,9 @@ Value is ORDER.  */)
     if (indices[i] == 0)
       signal_error ("Invalid font sort order", order);
 
-  if (bcmp (indices, font_sort_order, sizeof indices) != 0)
+  if (memcmp (indices, font_sort_order, sizeof indices) != 0)
     {
-      bcopy (indices, font_sort_order, sizeof font_sort_order);
+      memcpy (font_sort_order, indices, sizeof font_sort_order);
       free_all_realized_faces (Qnil);
     }
 
@@ -5364,7 +5328,20 @@ be found.  Value is ALIST.  */)
      (alist)
      Lisp_Object alist;
 {
+  Lisp_Object entry, tail, tail2;
+
   CHECK_LIST (alist);
+  alist = Fcopy_sequence (alist);
+  for (tail = alist; CONSP (tail); tail = XCDR (tail))
+    {
+      entry = XCAR (tail);
+      CHECK_LIST (entry);
+      entry = Fcopy_sequence (entry);
+      XSETCAR (tail, entry);
+      for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
+       XSETCAR (tail2, Fintern (XCAR (tail2), Qnil));
+    }
+
   Vface_alternative_font_family_alist = alist;
   free_all_realized_faces (Qnil);
   return alist;
@@ -5381,7 +5358,19 @@ be found.  Value is ALIST.  */)
      (alist)
      Lisp_Object alist;
 {
+  Lisp_Object entry, tail, tail2;
+
   CHECK_LIST (alist);
+  alist = Fcopy_sequence (alist);
+  for (tail = alist; CONSP (tail); tail = XCDR (tail))
+    {
+      entry = XCAR (tail);
+      CHECK_LIST (entry);
+      entry = Fcopy_sequence (entry);
+      XSETCAR (tail, entry);
+      for (tail2 = entry; CONSP (tail2); tail2 = XCDR (tail2))
+       XSETCAR (tail2, Fdowncase (XCAR (tail2)));
+    }
   Vface_alternative_font_registry_alist = alist;
   free_all_realized_faces (Qnil);
   return alist;
@@ -5399,8 +5388,7 @@ be found.  Value is ALIST.  */)
    attribute of ATTRS doesn't name a fontset.  */
 
 static int
-face_fontset (attrs)
-     Lisp_Object *attrs;
+face_fontset (Lisp_Object *attrs)
 {
   Lisp_Object name;
 
@@ -5423,8 +5411,7 @@ face_fontset (attrs)
    face.  */
 
 static int
-realize_basic_faces (f)
-     struct frame *f;
+realize_basic_faces (struct frame *f)
 {
   int success_p = 0;
   int count = SPECPDL_INDEX ();
@@ -5472,8 +5459,7 @@ realize_basic_faces (f)
    that are not explicitly specified are taken from frame parameters.  */
 
 static int
-realize_default_face (f)
-     struct frame *f;
+realize_default_face (struct frame *f)
 {
   struct face_cache *c = FRAME_FACE_CACHE (f);
   Lisp_Object lface;
@@ -5504,12 +5490,15 @@ realize_default_face (f)
   if (!FRAME_WINDOW_P (f))
     {
       LFACE_FAMILY (lface) = build_string ("default");
+      LFACE_FOUNDRY (lface) = LFACE_FAMILY (lface);
       LFACE_SWIDTH (lface) = Qnormal;
       LFACE_HEIGHT (lface) = make_number (1);
       if (UNSPECIFIEDP (LFACE_WEIGHT (lface)))
        LFACE_WEIGHT (lface) = Qnormal;
       if (UNSPECIFIEDP (LFACE_SLANT (lface)))
        LFACE_SLANT (lface) = Qnormal;
+      if (UNSPECIFIEDP (LFACE_FONTSET (lface)))
+       LFACE_FONTSET (lface) = Qnil;
     }
 
   if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
@@ -5564,7 +5553,7 @@ realize_default_face (f)
   /* Realize the face; it must be fully-specified now.  */
   xassert (lface_fully_specified_p (XVECTOR (lface)->contents));
   check_lface (lface);
-  bcopy (XVECTOR (lface)->contents, attrs, sizeof attrs);
+  memcpy (attrs, XVECTOR (lface)->contents, sizeof attrs);
   face = realize_face (c, attrs, DEFAULT_FACE_ID);
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -5575,7 +5564,7 @@ realize_default_face (f)
         not support the default font.  */
       if (!face->font)
        return 0;
+
       /* Otherwise, the font specified for the frame was not
         acceptable as a font for the default face (perhaps because
         auto-scaled fonts are rejected), so we must adjust the frame
@@ -5593,10 +5582,7 @@ realize_default_face (f)
    have.  The default face must have been realized already.  */
 
 static void
-realize_named_face (f, symbol, id)
-     struct frame *f;
-     Lisp_Object symbol;
-     int id;
+realize_named_face (struct frame *f, Lisp_Object symbol, int id)
 {
   struct face_cache *c = FRAME_FACE_CACHE (f);
   Lisp_Object lface = lface_from_face_name (f, symbol, 0);
@@ -5605,7 +5591,7 @@ realize_named_face (f, symbol, id)
   struct face *new_face;
 
   /* The default face must exist and be fully specified.  */
-  get_lface_attributes (f, Qdefault, attrs, 1);
+  get_lface_attributes_no_remap (f, Qdefault, attrs, 1);
   check_lface_attrs (attrs);
   xassert (lface_fully_specified_p (attrs));
 
@@ -5618,7 +5604,7 @@ realize_named_face (f, symbol, id)
     }
 
   /* Merge SYMBOL's face with the default face.  */
-  get_lface_attributes (f, symbol, symbol_attrs, 1);
+  get_lface_attributes_no_remap (f, symbol, symbol_attrs, 1);
   merge_face_vectors (f, symbol_attrs, attrs, 0);
 
   /* Realize the face.  */
@@ -5632,10 +5618,7 @@ realize_named_face (f, symbol, id)
    face.  Value is a pointer to the newly created realized face.  */
 
 static struct face *
-realize_face (cache, attrs, former_face_id)
-     struct face_cache *cache;
-     Lisp_Object *attrs;
-     int former_face_id;
+realize_face (struct face_cache *cache, Lisp_Object *attrs, int former_face_id)
 {
   struct face *face;
 
@@ -5676,10 +5659,7 @@ realize_face (cache, attrs, former_face_id)
    no-font.  */
 
 static struct face *
-realize_non_ascii_face (f, font_object, base_face)
-     struct frame *f;
-     Lisp_Object font_object;
-     struct face *base_face;
+realize_non_ascii_face (struct frame *f, Lisp_Object font_object, struct face *base_face)
 {
   struct face_cache *cache = FRAME_FACE_CACHE (f);
   struct face *face;
@@ -5713,9 +5693,7 @@ realize_non_ascii_face (f, font_object, base_face)
    created realized face.  */
 
 static struct face *
-realize_x_face (cache, attrs)
-     struct face_cache *cache;
-     Lisp_Object *attrs;
+realize_x_face (struct face_cache *cache, Lisp_Object *attrs)
 {
   struct face *face = NULL;
 #ifdef HAVE_WINDOW_SYSTEM
@@ -5738,7 +5716,8 @@ realize_x_face (cache, attrs)
       && lface_same_font_attributes_p (default_face->lface, attrs))
     {
       face->font = default_face->font;
-      face->fontset = make_fontset_for_ascii_face (f, -1, face);
+      face->fontset
+       = make_fontset_for_ascii_face (f, default_face->fontset, face);
     }
   else
     {
@@ -5755,9 +5734,12 @@ realize_x_face (cache, attrs)
         realizing the default face, thus the default face should have
         already been realized.  */
       if (fontset == -1)
-       fontset = default_face->fontset;
-      if (fontset == -1)
-       abort ();
+       {
+         if (default_face)
+           fontset = default_face->fontset;
+         if (fontset == -1)
+           abort ();
+       }
       if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
        attrs[LFACE_FONT_INDEX]
          = font_load_for_lface (f, attrs, attrs[LFACE_FONT_INDEX]);
@@ -5918,11 +5900,7 @@ realize_x_face (cache, attrs)
    default foreground/background colors.  */
 
 static void
-map_tty_color (f, face, idx, defaulted)
-     struct frame *f;
-     struct face *face;
-     enum lface_attribute_index idx;
-     int *defaulted;
+map_tty_color (struct frame *f, struct face *face, enum lface_attribute_index idx, int *defaulted)
 {
   Lisp_Object frame, color, def;
   int foreground_p = idx == LFACE_FOREGROUND_INDEX;
@@ -5999,9 +5977,7 @@ map_tty_color (f, face, idx, defaulted)
    Value is a pointer to the newly created realized face.  */
 
 static struct face *
-realize_tty_face (cache, attrs)
-     struct face_cache *cache;
-     Lisp_Object *attrs;
+realize_tty_face (struct face_cache *cache, Lisp_Object *attrs)
 {
   struct face *face;
   int weight, slant;
@@ -6082,10 +6058,7 @@ is non-nil.  */)
    property PROP on frame F in current_buffer.  */
 
 int
-compute_char_face (f, ch, prop)
-     struct frame *f;
-     int ch;
-     Lisp_Object prop;
+compute_char_face (struct frame *f, int ch, Lisp_Object prop)
 {
   int face_id;
 
@@ -6101,7 +6074,7 @@ compute_char_face (f, ch, prop)
     {
       Lisp_Object attrs[LFACE_VECTOR_SIZE];
       struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-      bcopy (default_face->lface, attrs, sizeof attrs);
+      memcpy (attrs, default_face->lface, sizeof attrs);
       merge_face_ref (f, prop, attrs, 1, 0);
       face_id = lookup_face (f, attrs);
     }
@@ -6122,17 +6095,21 @@ compute_char_face (f, ch, prop)
 
    If MOUSE is non-zero, use the character's mouse-face, not its face.
 
+   BASE_FACE_ID, if non-negative, specifies a base face id to use
+   instead of DEFAULT_FACE_ID.
+
    The face returned is suitable for displaying ASCII characters.  */
 
 int
 face_at_buffer_position (w, pos, region_beg, region_end,
-                        endptr, limit, mouse)
+                        endptr, limit, mouse, base_face_id)
      struct window *w;
      EMACS_INT pos;
      EMACS_INT region_beg, region_end;
      EMACS_INT *endptr;
      EMACS_INT limit;
      int mouse;
+     int base_face_id;
 {
   struct frame *f = XFRAME (w->frame);
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
@@ -6175,16 +6152,18 @@ face_at_buffer_position (w, pos, region_beg, region_end,
 
   *endptr = endpos;
 
-  default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+  default_face = FACE_FROM_ID (f, base_face_id >= 0 ? base_face_id
+                              : NILP (Vface_remapping_alist) ? DEFAULT_FACE_ID
+                              : lookup_basic_face (f, DEFAULT_FACE_ID));
 
   /* Optimize common cases where we can use the default face.  */
   if (noverlays == 0
       && NILP (prop)
       && !(pos >= region_beg && pos < region_end))
-    return DEFAULT_FACE_ID;
+    return default_face->id;
 
   /* Begin with attributes from the default face.  */
-  bcopy (default_face->lface, attrs, sizeof attrs);
+  memcpy (attrs, default_face->lface, sizeof attrs);
 
   /* Merge in attributes specified via text properties.  */
   if (!NILP (prop))
@@ -6278,7 +6257,7 @@ face_for_overlay_string (w, pos, region_beg, region_end,
     return DEFAULT_FACE_ID;
 
   /* Begin with attributes from the default face.  */
-  bcopy (default_face->lface, attrs, sizeof attrs);
+  memcpy (attrs, default_face->lface, sizeof attrs);
 
   /* Merge in attributes specified via text properties.  */
   if (!NILP (prop))
@@ -6379,7 +6358,7 @@ face_at_string_position (w, string, pos, bufpos, region_beg,
     return base_face->id;
 
   /* Begin with attributes from the base face.  */
-  bcopy (base_face->lface, attrs, sizeof attrs);
+  memcpy (attrs, base_face->lface, sizeof attrs);
 
   /* Merge in attributes specified via text properties.  */
   if (!NILP (prop))
@@ -6413,10 +6392,7 @@ face_at_string_position (w, string, pos, bufpos, region_beg,
 */
 
 int
-merge_faces (f, face_name, face_id, base_face_id)
-     struct frame *f;
-     Lisp_Object face_name;
-     int face_id, base_face_id;
+merge_faces (struct frame *f, Lisp_Object face_name, int face_id, int base_face_id)
 {
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   struct face *base_face;
@@ -6430,14 +6406,14 @@ merge_faces (f, face_name, face_id, base_face_id)
       if (face_id < 0 || face_id >= lface_id_to_name_size)
        return base_face_id;
       face_name = lface_id_to_name[face_id];
-      face_id = lookup_derived_face (f, face_name, base_face_id, 1);
-      if (face_id >= 0)
-       return face_id;
-      return base_face_id;
+      /* When called during make-frame, lookup_derived_face may fail
+        if the faces are uninitialized.  Don't signal an error.  */
+      face_id = lookup_derived_face (f, face_name, base_face_id, 0);
+      return (face_id >= 0 ? face_id : base_face_id);
     }
 
   /* Begin with attributes from the base face.  */
-  bcopy (base_face->lface, attrs, sizeof attrs);
+  memcpy (attrs, base_face->lface, sizeof attrs);
 
   if (!NILP (face_name))
     {
@@ -6461,6 +6437,60 @@ merge_faces (f, face_name, face_id, base_face_id)
 }
 
 \f
+
+#ifndef HAVE_X_WINDOWS
+DEFUN ("x-load-color-file", Fx_load_color_file,
+       Sx_load_color_file, 1, 1, 0,
+       doc: /* Create an alist of color entries from an external file.
+
+The file should define one named RGB color per line like so:
+  R G B   name
+where R,G,B are numbers between 0 and 255 and name is an arbitrary string.  */)
+    (filename)
+    Lisp_Object filename;
+{
+  FILE *fp;
+  Lisp_Object cmap = Qnil;
+  Lisp_Object abspath;
+
+  CHECK_STRING (filename);
+  abspath = Fexpand_file_name (filename, Qnil);
+
+  fp = fopen (SDATA (filename), "rt");
+  if (fp)
+    {
+      char buf[512];
+      int red, green, blue;
+      int num;
+
+      BLOCK_INPUT;
+
+      while (fgets (buf, sizeof (buf), fp) != NULL) {
+       if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
+         {
+           char *name = buf + num;
+           num = strlen (name) - 1;
+           if (num >= 0 && name[num] == '\n')
+             name[num] = 0;
+           cmap = Fcons (Fcons (build_string (name),
+#ifdef WINDOWSNT
+                                make_number (RGB (red, green, blue))),
+#else
+                                make_number ((red << 16) | (green << 8) | blue)),
+#endif
+                         cmap);
+         }
+      }
+      fclose (fp);
+
+      UNBLOCK_INPUT;
+    }
+
+  return cmap;
+}
+#endif
+
+\f
 /***********************************************************************
                                Tests
  ***********************************************************************/
@@ -6551,154 +6581,154 @@ DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
  ***********************************************************************/
 
 void
-syms_of_xfaces ()
+syms_of_xfaces (void)
 {
-  Qface = intern ("face");
+  Qface = intern_c_string ("face");
   staticpro (&Qface);
-  Qface_no_inherit = intern ("face-no-inherit");
+  Qface_no_inherit = intern_c_string ("face-no-inherit");
   staticpro (&Qface_no_inherit);
-  Qbitmap_spec_p = intern ("bitmap-spec-p");
+  Qbitmap_spec_p = intern_c_string ("bitmap-spec-p");
   staticpro (&Qbitmap_spec_p);
-  Qframe_set_background_mode = intern ("frame-set-background-mode");
+  Qframe_set_background_mode = intern_c_string ("frame-set-background-mode");
   staticpro (&Qframe_set_background_mode);
 
   /* Lisp face attribute keywords.  */
-  QCfamily = intern (":family");
+  QCfamily = intern_c_string (":family");
   staticpro (&QCfamily);
-  QCheight = intern (":height");
+  QCheight = intern_c_string (":height");
   staticpro (&QCheight);
-  QCweight = intern (":weight");
+  QCweight = intern_c_string (":weight");
   staticpro (&QCweight);
-  QCslant = intern (":slant");
+  QCslant = intern_c_string (":slant");
   staticpro (&QCslant);
-  QCunderline = intern (":underline");
+  QCunderline = intern_c_string (":underline");
   staticpro (&QCunderline);
-  QCinverse_video = intern (":inverse-video");
+  QCinverse_video = intern_c_string (":inverse-video");
   staticpro (&QCinverse_video);
-  QCreverse_video = intern (":reverse-video");
+  QCreverse_video = intern_c_string (":reverse-video");
   staticpro (&QCreverse_video);
-  QCforeground = intern (":foreground");
+  QCforeground = intern_c_string (":foreground");
   staticpro (&QCforeground);
-  QCbackground = intern (":background");
+  QCbackground = intern_c_string (":background");
   staticpro (&QCbackground);
-  QCstipple = intern (":stipple");
+  QCstipple = intern_c_string (":stipple");
   staticpro (&QCstipple);
-  QCwidth = intern (":width");
+  QCwidth = intern_c_string (":width");
   staticpro (&QCwidth);
-  QCfont = intern (":font");
+  QCfont = intern_c_string (":font");
   staticpro (&QCfont);
-  QCfontset = intern (":fontset");
+  QCfontset = intern_c_string (":fontset");
   staticpro (&QCfontset);
-  QCbold = intern (":bold");
+  QCbold = intern_c_string (":bold");
   staticpro (&QCbold);
-  QCitalic = intern (":italic");
+  QCitalic = intern_c_string (":italic");
   staticpro (&QCitalic);
-  QCoverline = intern (":overline");
+  QCoverline = intern_c_string (":overline");
   staticpro (&QCoverline);
-  QCstrike_through = intern (":strike-through");
+  QCstrike_through = intern_c_string (":strike-through");
   staticpro (&QCstrike_through);
-  QCbox = intern (":box");
+  QCbox = intern_c_string (":box");
   staticpro (&QCbox);
-  QCinherit = intern (":inherit");
+  QCinherit = intern_c_string (":inherit");
   staticpro (&QCinherit);
 
   /* Symbols used for Lisp face attribute values.  */
-  QCcolor = intern (":color");
+  QCcolor = intern_c_string (":color");
   staticpro (&QCcolor);
-  QCline_width = intern (":line-width");
+  QCline_width = intern_c_string (":line-width");
   staticpro (&QCline_width);
-  QCstyle = intern (":style");
+  QCstyle = intern_c_string (":style");
   staticpro (&QCstyle);
-  Qreleased_button = intern ("released-button");
+  Qreleased_button = intern_c_string ("released-button");
   staticpro (&Qreleased_button);
-  Qpressed_button = intern ("pressed-button");
+  Qpressed_button = intern_c_string ("pressed-button");
   staticpro (&Qpressed_button);
-  Qnormal = intern ("normal");
+  Qnormal = intern_c_string ("normal");
   staticpro (&Qnormal);
-  Qultra_light = intern ("ultra-light");
+  Qultra_light = intern_c_string ("ultra-light");
   staticpro (&Qultra_light);
-  Qextra_light = intern ("extra-light");
+  Qextra_light = intern_c_string ("extra-light");
   staticpro (&Qextra_light);
-  Qlight = intern ("light");
+  Qlight = intern_c_string ("light");
   staticpro (&Qlight);
-  Qsemi_light = intern ("semi-light");
+  Qsemi_light = intern_c_string ("semi-light");
   staticpro (&Qsemi_light);
-  Qsemi_bold = intern ("semi-bold");
+  Qsemi_bold = intern_c_string ("semi-bold");
   staticpro (&Qsemi_bold);
-  Qbold = intern ("bold");
+  Qbold = intern_c_string ("bold");
   staticpro (&Qbold);
-  Qextra_bold = intern ("extra-bold");
+  Qextra_bold = intern_c_string ("extra-bold");
   staticpro (&Qextra_bold);
-  Qultra_bold = intern ("ultra-bold");
+  Qultra_bold = intern_c_string ("ultra-bold");
   staticpro (&Qultra_bold);
-  Qoblique = intern ("oblique");
+  Qoblique = intern_c_string ("oblique");
   staticpro (&Qoblique);
-  Qitalic = intern ("italic");
+  Qitalic = intern_c_string ("italic");
   staticpro (&Qitalic);
-  Qreverse_oblique = intern ("reverse-oblique");
+  Qreverse_oblique = intern_c_string ("reverse-oblique");
   staticpro (&Qreverse_oblique);
-  Qreverse_italic = intern ("reverse-italic");
+  Qreverse_italic = intern_c_string ("reverse-italic");
   staticpro (&Qreverse_italic);
-  Qultra_condensed = intern ("ultra-condensed");
+  Qultra_condensed = intern_c_string ("ultra-condensed");
   staticpro (&Qultra_condensed);
-  Qextra_condensed = intern ("extra-condensed");
+  Qextra_condensed = intern_c_string ("extra-condensed");
   staticpro (&Qextra_condensed);
-  Qcondensed = intern ("condensed");
+  Qcondensed = intern_c_string ("condensed");
   staticpro (&Qcondensed);
-  Qsemi_condensed = intern ("semi-condensed");
+  Qsemi_condensed = intern_c_string ("semi-condensed");
   staticpro (&Qsemi_condensed);
-  Qsemi_expanded = intern ("semi-expanded");
+  Qsemi_expanded = intern_c_string ("semi-expanded");
   staticpro (&Qsemi_expanded);
-  Qexpanded = intern ("expanded");
+  Qexpanded = intern_c_string ("expanded");
   staticpro (&Qexpanded);
-  Qextra_expanded = intern ("extra-expanded");
+  Qextra_expanded = intern_c_string ("extra-expanded");
   staticpro (&Qextra_expanded);
-  Qultra_expanded = intern ("ultra-expanded");
+  Qultra_expanded = intern_c_string ("ultra-expanded");
   staticpro (&Qultra_expanded);
-  Qbackground_color = intern ("background-color");
+  Qbackground_color = intern_c_string ("background-color");
   staticpro (&Qbackground_color);
-  Qforeground_color = intern ("foreground-color");
+  Qforeground_color = intern_c_string ("foreground-color");
   staticpro (&Qforeground_color);
-  Qunspecified = intern ("unspecified");
+  Qunspecified = intern_c_string ("unspecified");
   staticpro (&Qunspecified);
-  Qignore_defface = intern (":ignore-defface");
+  Qignore_defface = intern_c_string (":ignore-defface");
   staticpro (&Qignore_defface);
 
-  Qface_alias = intern ("face-alias");
+  Qface_alias = intern_c_string ("face-alias");
   staticpro (&Qface_alias);
-  Qdefault = intern ("default");
+  Qdefault = intern_c_string ("default");
   staticpro (&Qdefault);
-  Qtool_bar = intern ("tool-bar");
+  Qtool_bar = intern_c_string ("tool-bar");
   staticpro (&Qtool_bar);
-  Qregion = intern ("region");
+  Qregion = intern_c_string ("region");
   staticpro (&Qregion);
-  Qfringe = intern ("fringe");
+  Qfringe = intern_c_string ("fringe");
   staticpro (&Qfringe);
-  Qheader_line = intern ("header-line");
+  Qheader_line = intern_c_string ("header-line");
   staticpro (&Qheader_line);
-  Qscroll_bar = intern ("scroll-bar");
+  Qscroll_bar = intern_c_string ("scroll-bar");
   staticpro (&Qscroll_bar);
-  Qmenu = intern ("menu");
+  Qmenu = intern_c_string ("menu");
   staticpro (&Qmenu);
-  Qcursor = intern ("cursor");
+  Qcursor = intern_c_string ("cursor");
   staticpro (&Qcursor);
-  Qborder = intern ("border");
+  Qborder = intern_c_string ("border");
   staticpro (&Qborder);
-  Qmouse = intern ("mouse");
+  Qmouse = intern_c_string ("mouse");
   staticpro (&Qmouse);
-  Qmode_line_inactive = intern ("mode-line-inactive");
+  Qmode_line_inactive = intern_c_string ("mode-line-inactive");
   staticpro (&Qmode_line_inactive);
-  Qvertical_border = intern ("vertical-border");
+  Qvertical_border = intern_c_string ("vertical-border");
   staticpro (&Qvertical_border);
-  Qtty_color_desc = intern ("tty-color-desc");
+  Qtty_color_desc = intern_c_string ("tty-color-desc");
   staticpro (&Qtty_color_desc);
-  Qtty_color_standard_values = intern ("tty-color-standard-values");
+  Qtty_color_standard_values = intern_c_string ("tty-color-standard-values");
   staticpro (&Qtty_color_standard_values);
-  Qtty_color_by_index = intern ("tty-color-by-index");
+  Qtty_color_by_index = intern_c_string ("tty-color-by-index");
   staticpro (&Qtty_color_by_index);
-  Qtty_color_alist = intern ("tty-color-alist");
+  Qtty_color_alist = intern_c_string ("tty-color-alist");
   staticpro (&Qtty_color_alist);
-  Qscalable_fonts_allowed = intern ("scalable-fonts-allowed");
+  Qscalable_fonts_allowed = intern_c_string ("scalable-fonts-allowed");
   staticpro (&Qscalable_fonts_allowed);
 
   Vparam_value_alist = Fcons (Fcons (Qnil, Qnil), Qnil);
@@ -6716,6 +6746,9 @@ syms_of_xfaces ()
 #endif
   defsubr (&Scolor_gray_p);
   defsubr (&Scolor_supported_p);
+#ifndef HAVE_X_WINDOWS
+  defsubr (&Sx_load_color_file);
+#endif
   defsubr (&Sface_attribute_relative_p);
   defsubr (&Smerge_face_attribute);
   defsubr (&Sinternal_get_lisp_face_attribute);
@@ -6758,7 +6791,7 @@ that number of fonts when searching for a matching font.  */);
 This stipple pattern is used on monochrome displays
 instead of shades of gray for a face background color.
 See `set-face-stipple' for possible values for this variable.  */);
-  Vface_default_stipple = build_string ("gray3");
+  Vface_default_stipple = make_pure_c_string ("gray3");
 
   DEFVAR_LISP ("tty-defined-color-alist", &Vtty_defined_color_alist,
    doc: /* An alist of defined terminal colors and their RGB values.  */);
@@ -6780,10 +6813,47 @@ Each element is a regular expression that matches names of fonts to
 ignore.  */);
   Vface_ignored_fonts = Qnil;
 
+  DEFVAR_LISP ("face-remapping-alist", &Vface_remapping_alist,
+              doc: /* Alist of face remappings.
+Each element is of the form:
+
+   (FACE REPLACEMENT...),
+
+which causes display of the face FACE to use REPLACEMENT... instead.
+REPLACEMENT... is interpreted the same way the value of a `face' text
+property is: it may be (1) A face name, (2) A list of face names, (3) A
+property-list of face attribute/value pairs, or (4) A list of face names
+intermixed with lists containing face attribute/value pairs.
+
+Multiple entries in REPLACEMENT... are merged together to form the final
+result, with faces or attributes earlier in the list taking precedence
+over those that are later.
+
+Face-name remapping cycles are suppressed; recursive references use the
+underlying face instead of the remapped face.  So a remapping of the form:
+
+   (FACE EXTRA-FACE... FACE)
+
+or:
+
+   (FACE (FACE-ATTR VAL ...) FACE)
+
+will cause EXTRA-FACE... or (FACE-ATTR VAL ...) to be _merged_ with the
+existing definition of FACE.  Note that for the default face, this isn't
+necessary, as every face inherits from the default face.
+
+Making this variable buffer-local is a good way to allow buffer-specific
+face definitions.  For instance, the mode my-mode could define a face
+`my-mode-default', and then in the mode setup function, do:
+
+   (set (make-local-variable 'face-remapping-alist)
+        '((default my-mode-default)))).  */);
+  Vface_remapping_alist = Qnil;
+
   DEFVAR_LISP ("face-font-rescale-alist", &Vface_font_rescale_alist,
               doc: /* Alist of fonts vs the rescaling factors.
-Each element is a cons (FONT-NAME-PATTERN . RESCALE-RATIO), where
-FONT-NAME-PATTERN is a regular expression matching a font name, and
+Each element is a cons (FONT-PATTERN . RESCALE-RATIO), where
+FONT-PATTERN is a font-spec or a regular expression matching a font name, and
 RESCALE-RATIO is a floating point number to specify how much larger
 \(or smaller) font we should use.  For instance, if a face requests
 a font of 10 point, we actually use a font of 10 * RESCALE-RATIO point.  */);
@@ -6794,8 +6864,7 @@ a font of 10 point, we actually use a font of 10 * RESCALE-RATIO point.  */);
   defsubr (&Sx_list_fonts);
   defsubr (&Sinternal_face_x_get_resource);
   defsubr (&Sx_family_fonts);
-  defsubr (&Sx_font_family_list);
-#endif /* HAVE_WINDOW_SYSTEM */
+#endif
 }
 
 /* arch-tag: 8a0f7598-5517-408d-9ab3-1da6fcd4c749