Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
[bpt/emacs.git] / src / xfaces.c
index 087dc86..d4d68eb 100644 (file)
@@ -1,13 +1,13 @@
 /* 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.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,9 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* New face implementation by Gerd Moellmann <gerd@gnu.org>.  */
 
@@ -29,42 +27,46 @@ Boston, MA 02110-1301, USA.  */
 
    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 pattern, or nil.  This is a special attribute.
-   When this attribute is specified, the face uses a font opened by
-   that pattern as is.  In addition, all the other font-related
-   attributes (1st thru 5th) are generated from the opened font name.
+   15. Font-spec, or nil.  This is a special attribute.
+
+   A font-spec is a collection of font attributes (specs).
+
+   When this attribute is specified, the face uses a font matching
+   with the specs as is except for what overwritten by the specs in
+   the fontset (see below).  In addition, the other font-related
+   attributes (1st thru 5th) are updated from the spec.
+
    On the other hand, if one of the other font-related attributes are
-   specified, this attribute is set to nil.  In that case, the face
-   doesn't inherit this attribute from the `default' face, and uses a
-   font determined by the other attributes (those may be inherited
-   from the `default' face).
+   specified, the correspoinding specs in this attribute is set to nil.
 
    15. A face name or list of face names from which to inherit attributes.
 
@@ -72,7 +74,11 @@ Boston, MA 02110-1301, USA.  */
    and is used to ensure that a font specified on the command line,
    for example, can be matched exactly.
 
-   17. A fontset name.
+   17. A fontset name.  This is another special attribute.
+
+   A fontset is a mappings from characters to font-specs, and the
+   specs overwrite the font-spec in the 14th attribute.
+
 
    Faces are frame-local by nature because Emacs allows to define the
    same named face (face names are symbols) differently for different
@@ -198,6 +204,7 @@ Boston, MA 02110-1301, USA.  */
 #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"
@@ -206,10 +213,6 @@ Boston, MA 02110-1301, USA.  */
 #include "frame.h"
 #include "termhooks.h"
 
-#ifdef HAVE_WINDOW_SYSTEM
-#include "fontset.h"
-#endif /* HAVE_WINDOW_SYSTEM */
-
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #ifdef USE_MOTIF
@@ -232,15 +235,18 @@ Boston, MA 02110-1301, USA.  */
 #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,9 +255,10 @@ Boston, MA 02110-1301, USA.  */
 #include "intervals.h"
 #include "termchar.h"
 
-#ifdef HAVE_WINDOW_SYSTEM
 #include "font.h"
-#endif /* HAVE_WINDOW_SYSTEM */
+#ifdef HAVE_WINDOW_SYSTEM
+#include "fontset.h"
+#endif /* HAVE_WINDOW_SYSTEM */
 
 #ifdef HAVE_X_WINDOWS
 
@@ -314,6 +321,11 @@ Lisp_Object QCreverse_video;
 Lisp_Object QCoverline, QCstrike_through, QCbox, QCinherit;
 Lisp_Object QCfontset;
 
+/* Keywords symbols used for font properties.  */
+extern Lisp_Object QCfoundry, QCadstyle, QCregistry;
+extern Lisp_Object QCspacing, QCsize, QCavgwidth;
+extern Lisp_Object Qp;
+
 /* Symbols used for attribute values.  */
 
 Lisp_Object Qnormal, Qbold, Qultra_light, Qextra_light, Qlight;
@@ -416,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;
@@ -478,110 +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 font_scalable_p P_ ((struct font_name *));
-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 *, int,
-                                               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_numeric_weight P_ ((Lisp_Object));
-static int face_numeric_slant P_ ((Lisp_Object));
-static int face_numeric_swidth P_ ((Lisp_Object));
-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_name P_ ((struct frame *, Lisp_Object,
-                                        Lisp_Object, int, int));
-static void set_lface_from_font_and_fontset P_ ((struct frame *, Lisp_Object,
-                                                Lisp_Object, int, 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 int xlfd_numeric_slant P_ ((struct font_name *));
-static int xlfd_numeric_weight P_ ((struct font_name *));
-static int xlfd_numeric_swidth P_ ((struct font_name *));
-static Lisp_Object xlfd_symbolic_slant P_ ((struct font_name *));
-static Lisp_Object xlfd_symbolic_weight P_ ((struct font_name *));
-static Lisp_Object xlfd_symbolic_swidth P_ ((struct font_name *));
-static int xlfd_fixed_p P_ ((struct font_name *));
-static int xlfd_numeric_value P_ ((struct table_entry *, int, struct font_name *,
-                                  int, int));
-static Lisp_Object xlfd_symbolic_value P_ ((struct table_entry *, int,
-                                           struct font_name *, int,
-                                           Lisp_Object));
-static struct table_entry *xlfd_lookup_field_contents P_ ((struct table_entry *, int,
-                                                          struct font_name *, int));
+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 int split_font_name P_ ((struct frame *, struct font_name *, int));
-static int xlfd_point_size P_ ((struct frame *, struct font_name *));
-static void sort_fonts P_ ((struct frame *, struct font_name *, int,
-                              int (*cmpfn) P_ ((const void *, const void *))));
-static GC x_create_gc P_ ((struct frame *, unsigned long, XGCValues *));
-static void x_free_gc P_ ((struct frame *, GC));
-static void clear_font_table P_ ((struct x_display_info *));
-
-#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 */
@@ -678,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;
 
@@ -703,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;
@@ -729,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;
@@ -746,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));
@@ -788,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)
@@ -797,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;
 }
 
@@ -810,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)
     {
@@ -839,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
@@ -864,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;
@@ -883,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)
@@ -894,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;
     }
@@ -909,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);
 
@@ -952,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))
     {
@@ -968,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;
@@ -978,16 +915,10 @@ clear_face_cache (clear_fonts_p)
   if (clear_fonts_p
       || ++clear_font_table_count == CLEAR_FONT_TABLE_COUNT)
     {
-      struct x_display_info *dpyinfo;
-
-#ifdef USE_FONT_BACKEND
-      if (! enable_font_backend)
-#endif /* USE_FONT_BACKEND */
-      /* Fonts are common for frames on one display, i.e. on
-        one X screen.  */
-      for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
-       if (dpyinfo->n_fonts > CLEAR_FONT_TABLE_NFONTS)
-         clear_font_table (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
@@ -1029,70 +960,6 @@ Optional THOROUGHLY non-nil means try to free unused fonts, too.  */)
   return Qnil;
 }
 
-
-
-#ifdef HAVE_WINDOW_SYSTEM
-
-
-/* Remove fonts from the font table of DPYINFO except for the default
-   ASCII fonts of frames on that display.  Called from clear_face_cache
-   from time to time.  */
-
-static void
-clear_font_table (dpyinfo)
-     struct x_display_info *dpyinfo;
-{
-  int i;
-
-  /* Free those fonts that are not used by frames on DPYINFO.  */
-  for (i = 0; i < dpyinfo->n_fonts; ++i)
-    {
-      struct font_info *font_info = dpyinfo->font_table + i;
-      Lisp_Object tail, frame;
-
-      /* Check if slot is already free.  */
-      if (font_info->name == NULL)
-       continue;
-
-      /* Don't free a default font of some frame.  */
-      FOR_EACH_FRAME (tail, frame)
-       {
-         struct frame *f = XFRAME (frame);
-         if (FRAME_WINDOW_P (f)
-             && font_info->font == FRAME_FONT (f))
-           break;
-       }
-
-      if (!NILP (tail))
-       continue;
-
-      /* Free names.  */
-      if (font_info->full_name != font_info->name)
-       xfree (font_info->full_name);
-      xfree (font_info->name);
-
-      /* Free the font.  */
-      BLOCK_INPUT;
-#ifdef HAVE_X_WINDOWS
-      XFreeFont (dpyinfo->display, font_info->font);
-#endif
-#ifdef WINDOWSNT
-      w32_unload_font (dpyinfo, font_info->font);
-#endif
-#ifdef MAC_OS
-      mac_unload_font (dpyinfo, font_info->font);
-#endif
-      UNBLOCK_INPUT;
-
-      /* Mark font table slot free.  */
-      font_info->font = NULL;
-      font_info->name = font_info->full_name = NULL;
-    }
-}
-
-#endif /* HAVE_WINDOW_SYSTEM */
-
-
 \f
 /***********************************************************************
                              X Pixmaps
@@ -1158,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;
 
@@ -1221,64 +1085,6 @@ load_pixmap (f, name, w_ptr, h_ptr)
 
 
 \f
-/***********************************************************************
-                               Fonts
- ***********************************************************************/
-
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* Load font of face FACE which is used on frame F to display ASCII
-   characters.  The name of the font to load is determined by lface.  */
-
-static void
-load_face_font (f, face)
-     struct frame *f;
-     struct face *face;
-{
-  struct font_info *font_info = NULL;
-  char *font_name;
-  int needs_overstrike;
-
-#ifdef USE_FONT_BACKEND
-  if (enable_font_backend)
-    abort ();
-#endif /* USE_FONT_BACKEND */
-  face->font_info_id = -1;
-  face->font = NULL;
-  face->font_name = NULL;
-
-  font_name = choose_face_font (f, face->lface, Qnil, &needs_overstrike);
-  if (!font_name)
-    return;
-
-  BLOCK_INPUT;
-  font_info = FS_LOAD_FONT (f, font_name);
-  UNBLOCK_INPUT;
-
-  if (font_info)
-    {
-      face->font_info_id = font_info->font_idx;
-      face->font = font_info->font;
-      face->font_name = font_info->full_name;
-      face->overstrike = needs_overstrike;
-      if (face->gc)
-       {
-         BLOCK_INPUT;
-         x_free_gc (f, face->gc);
-         face->gc = 0;
-         UNBLOCK_INPUT;
-       }
-    }
-  else
-    add_to_log ("Unable to load font %s",
-               build_string (font_name), Qnil);
-  xfree (font_name);
-}
-
-#endif /* HAVE_WINDOW_SYSTEM */
-
-
-\f
 /***********************************************************************
                                X Colors
  ***********************************************************************/
@@ -1288,9 +1094,7 @@ load_face_font (f, face)
    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)))                  \
@@ -1315,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;
 
@@ -1378,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;
 
@@ -1417,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);
@@ -1433,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 ();
@@ -1446,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)))
     {
@@ -1483,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;
@@ -1512,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;
@@ -1525,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))
@@ -1590,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;
 
@@ -1665,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;
 
@@ -1704,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)
@@ -1722,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;
@@ -1851,1279 +1627,189 @@ 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}
-};
-
-/* Structure used to hold the result of splitting font names in XLFD
-   format into their fields.  */
-
-struct font_name
-{
-  /* The original name which is modified destructively by
-     split_font_name.  The pointer is kept here to be able to free it
-     if it was allocated from the heap.  */
-  char *name;
-
-  /* Font name fields.  Each vector element points into `name' above.
-     Fields are NUL-terminated.  */
-  char *fields[XLFD_LAST];
-
-  /* Numeric values for those fields that interest us.  See
-     split_font_name for which these are.  */
-  int numeric[XLFD_LAST];
-
-  /* If the original name matches one of Vface_font_rescale_alist,
-     the value is the corresponding rescale ratio.  Otherwise, the
-     value is 1.0.  */
-  double rescale_ratio;
-
-  /* Lower value mean higher priority.  */
-  int registry_priority;
-};
-
-/* 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
 
-/* Look up FONT.fields[FIELD_INDEX] in TABLE which has DIM entries.
-   TABLE must be sorted by TABLE[i]->name in ascending order.  Value
-   is a pointer to the matching table entry or null if no table entry
-   matches.  */
+#ifdef HAVE_WINDOW_SYSTEM
 
-static struct table_entry *
-xlfd_lookup_field_contents (table, dim, font, field_index)
-     struct table_entry *table;
-     int dim;
-     struct font_name *font;
-     int field_index;
-{
-  /* Function split_font_name converts fields to lower-case, so there
-     is no need to use xstrlwr or xstricmp here.  */
-  char *s = font->fields[field_index];
-  int low, mid, high, cmp;
+static enum font_property_index font_props_for_sorting[FONT_SIZE_INDEX];
 
-  low = 0;
-  high = dim - 1;
+static int
+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;
 
-  while (low <= high)
+  for (i = 0; i < FONT_SIZE_INDEX; i++)
     {
-      mid = (low + high) / 2;
-      cmp = strcmp (table[mid].name, s);
+      enum font_property_index idx = font_props_for_sorting[i];
+      Lisp_Object val1 = AREF (font1, idx), val2 = AREF (font2, idx);
+      int result;
 
-      if (cmp < 0)
-       low = mid + 1;
-      else if (cmp > 0)
-       high = mid - 1;
+      if (idx <= FONT_REGISTRY_INDEX)
+       {
+         if (STRINGP (val1))
+           result = STRINGP (val2) ? strcmp (SDATA (val1), SDATA (val2)) : -1;
+         else
+           result = STRINGP (val2) ? 1 : 0;
+       }
       else
-       return table + mid;
+       {
+         if (INTEGERP (val1))
+           result = INTEGERP (val2) ? XINT (val1) - XINT (val2) : -1;
+         else
+           result = INTEGERP (val2) ? 1 : 0;
+       }
+      if (result)
+       return result;
     }
-
-  return NULL;
+  return 0;
 }
 
+DEFUN ("x-family-fonts", Fx_family_fonts, Sx_family_fonts, 0, 2, 0,
+       doc: /* Return a list of available fonts of family FAMILY on FRAME.
+If FAMILY is omitted or nil, list all families.
+Otherwise, FAMILY must be a string, possibly containing wildcards
+`?' and `*'.
+If FRAME is omitted or nil, use the selected frame.
+Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT
+SLANT FIXED-P FULL REGISTRY-AND-ENCODING].
+FAMILY is the font family name.  POINT-SIZE is the size of the
+font in 1/10 pt.  WIDTH, WEIGHT, and SLANT are symbols describing the
+width, weight and slant of the font.  These symbols are the same as for
+face attributes.  FIXED-P is non-nil if the font is fixed-pitch.
+FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string
+giving the registry and encoding of the font.
+The result list is sorted according to the current setting of
+the face font sort order.  */)
+     (family, frame)
+     Lisp_Object family, frame;
+{
+  Lisp_Object font_spec, list, *drivers, vec;
+  int i, nfonts, ndrivers;
+  Lisp_Object result;
 
-/* Return a numeric representation for font name field
-   FONT.fields[FIELD_INDEX].  The field is looked up in TABLE which
-   has DIM entries.  Value is the numeric value found or DFLT if no
-   table entry matches.  This function is used to translate weight,
-   slant, and swidth names of XLFD font names to numeric values.  */
-
-static INLINE int
-xlfd_numeric_value (table, dim, font, field_index, dflt)
-     struct table_entry *table;
-     int dim;
-     struct font_name *font;
-     int field_index;
-     int dflt;
-{
-  struct table_entry *p;
-  p = xlfd_lookup_field_contents (table, dim, font, field_index);
-  return p ? p->numeric : dflt;
-}
-
+  if (NILP (frame))
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame);
 
-/* Return a symbolic representation for font name field
-   FONT.fields[FIELD_INDEX].  The field is looked up in TABLE which
-   has DIM entries.  Value is the symbolic value found or DFLT if no
-   table entry matches.  This function is used to translate weight,
-   slant, and swidth names of XLFD font names to symbols.  */
+  font_spec = Ffont_spec (0, NULL);
+  if (!NILP (family))
+    {
+      CHECK_STRING (family);
+      font_parse_family_registry (family, Qnil, font_spec);
+    }
 
-static INLINE Lisp_Object
-xlfd_symbolic_value (table, dim, font, field_index, dflt)
-     struct table_entry *table;
-     int dim;
-     struct font_name *font;
-     int field_index;
-     Lisp_Object dflt;
-{
-  struct table_entry *p;
-  p = xlfd_lookup_field_contents (table, dim, font, field_index);
-  return p ? *p->symbol : dflt;
-}
+  list = font_list_entities (frame, font_spec);
+  if (NILP (list))
+    return Qnil;
 
+  /* 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;
 
-/* Return a numeric value for the slant of the font given by FONT.  */
+  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);
 
-static INLINE int
-xlfd_numeric_slant (font)
-     struct font_name *font;
-{
-  return xlfd_numeric_value (slant_table, DIM (slant_table),
-                            font, XLFD_SLANT, XLFD_SLANT_ROMAN);
-}
+  qsort (XVECTOR (vec)->contents, nfonts, sizeof (Lisp_Object),
+        compare_fonts_by_sort_order);
 
+  result = Qnil;
+  for (i = nfonts - 1; i >= 0; --i)
+    {
+      Lisp_Object font = AREF (vec, i);
+      Lisp_Object v = Fmake_vector (make_number (8), Qnil);
+      int point;
+      Lisp_Object spacing;
+
+      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,
+                             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, Ffont_xlfd_name (font, Qnil));
+      ASET (v, 7, AREF (font, FONT_REGISTRY_INDEX));
 
-/* Return a symbol representing the weight of the font given by FONT.  */
+      result = Fcons (v, result);
+    }
 
-static INLINE Lisp_Object
-xlfd_symbolic_slant (font)
-     struct font_name *font;
-{
-  return xlfd_symbolic_value (slant_table, DIM (slant_table),
-                             font, XLFD_SLANT, Qnormal);
+  return result;
 }
 
+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.
 
-/* Return a numeric value for the weight of the font given by FONT.  */
-
-static INLINE int
-xlfd_numeric_weight (font)
-     struct font_name *font;
-{
-  return xlfd_numeric_value (weight_table, DIM (weight_table),
-                            font, XLFD_WEIGHT, XLFD_WEIGHT_MEDIUM);
-}
-
+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.
 
-/* Return a symbol representing the slant of the font given by FONT.  */
+The return value is a list of strings, suitable as arguments to
+`set-face-font'.
 
-static INLINE Lisp_Object
-xlfd_symbolic_weight (font)
-     struct font_name *font;
+Fonts Emacs can't use may or may not be excluded
+even if they match PATTERN and FACE.
+The optional fourth argument MAXIMUM sets a limit on how many
+fonts to match.  The first MAXIMUM fonts are reported.
+The optional fifth argument WIDTH, if specified, is a number of columns
+occupied by a character of a font.  In that case, return only fonts
+the WIDTH times as wide as FACE on FRAME.  */)
+     (pattern, face, frame, maximum, width)
+    Lisp_Object pattern, face, frame, maximum, width;
 {
-  return xlfd_symbolic_value (weight_table, DIM (weight_table),
-                             font, XLFD_WEIGHT, Qnormal);
-}
+  struct frame *f;
+  int size, avgwidth;
 
+  check_x ();
+  CHECK_STRING (pattern);
 
-/* Return a numeric value for the swidth of the font whose XLFD font
-   name fields are found in FONT.  */
+  if (! NILP (maximum))
+    CHECK_NATNUM (maximum);
 
-static INLINE int
-xlfd_numeric_swidth (font)
-     struct font_name *font;
-{
-  return xlfd_numeric_value (swidth_table, DIM (swidth_table),
-                            font, XLFD_SWIDTH, XLFD_SWIDTH_MEDIUM);
-}
-
-
-/* Return a symbolic value for the swidth of FONT.  */
-
-static INLINE Lisp_Object
-xlfd_symbolic_swidth (font)
-     struct font_name *font;
-{
-  return xlfd_symbolic_value (swidth_table, DIM (swidth_table),
-                             font, XLFD_SWIDTH, Qnormal);
-}
-
-
-/* Look up the entry of SYMBOL in the vector TABLE which has DIM
-   entries.  Value is a pointer to the matching table entry or null if
-   no element of TABLE contains SYMBOL.  */
-
-static struct table_entry *
-face_value (table, dim, symbol)
-     struct table_entry *table;
-     int dim;
-     Lisp_Object symbol;
-{
-  int i;
-
-  xassert (SYMBOLP (symbol));
-
-  for (i = 0; i < dim; ++i)
-    if (EQ (*table[i].symbol, symbol))
-      break;
-
-  return i < dim ? table + i : NULL;
-}
-
-
-/* Return a numeric value for SYMBOL in the vector TABLE which has DIM
-   entries.  Value is -1 if SYMBOL is not found in TABLE.  */
-
-static INLINE int
-face_numeric_value (table, dim, symbol)
-     struct table_entry *table;
-     size_t dim;
-     Lisp_Object symbol;
-{
-  struct table_entry *p = face_value (table, dim, symbol);
-  return p ? p->numeric : -1;
-}
-
-
-/* Return a numeric value representing the weight specified by Lisp
-   symbol WEIGHT.  Value is one of the enumerators of enum
-   xlfd_weight.  */
-
-static INLINE int
-face_numeric_weight (weight)
-     Lisp_Object weight;
-{
-  return face_numeric_value (weight_table, DIM (weight_table), weight);
-}
-
-
-/* Return a numeric value representing the slant specified by Lisp
-   symbol SLANT.  Value is one of the enumerators of enum xlfd_slant.  */
-
-static INLINE int
-face_numeric_slant (slant)
-     Lisp_Object slant;
-{
-  return face_numeric_value (slant_table, DIM (slant_table), slant);
-}
-
-
-/* Return a numeric value representing the swidth specified by Lisp
-   symbol WIDTH.  Value is one of the enumerators of enum xlfd_swidth.  */
-
-static int
-face_numeric_swidth (width)
-     Lisp_Object width;
-{
-  return face_numeric_value (swidth_table, DIM (swidth_table), width);
-}
-
-#ifdef HAVE_WINDOW_SYSTEM
-
-#ifdef USE_FONT_BACKEND
-static INLINE Lisp_Object
-face_symbolic_value (table, dim, font_prop)
-     struct table_entry *table;
-     int dim;
-     Lisp_Object font_prop;
-{
-  struct table_entry *p;
-  char *s = SDATA (SYMBOL_NAME (font_prop));
-  int low, mid, high, cmp;
-
-  low = 0;
-  high = dim - 1;
-
-  while (low <= high)
-    {
-      mid = (low + high) / 2;
-      cmp = strcmp (table[mid].name, s);
-
-      if (cmp < 0)
-       low = mid + 1;
-      else if (cmp > 0)
-       high = mid - 1;
-      else
-       return *table[mid].symbol;
-    }
-
-  return Qnil;
-}
-
-static INLINE Lisp_Object
-face_symbolic_weight (weight)
-     Lisp_Object weight;
-{
-  return face_symbolic_value (weight_table, DIM (weight_table), weight);
-}
-
-static INLINE Lisp_Object
-face_symbolic_slant (slant)
-     Lisp_Object slant;
-{
-  return face_symbolic_value (slant_table, DIM (slant_table), slant);
-}
-
-static INLINE Lisp_Object
-face_symbolic_swidth (width)
-     Lisp_Object width;
-{
-  return face_symbolic_value (swidth_table, DIM (swidth_table), width);
-}
-#endif /* USE_FONT_BACKEND */
-
-Lisp_Object
-split_font_name_into_vector (fontname)
-     Lisp_Object fontname;
-{
-  struct font_name font;
-  Lisp_Object vec;
-  int i;
-
-  font.name = LSTRDUPA (fontname);
-  if (! split_font_name (NULL, &font, 0))
-    return Qnil;
-  vec = Fmake_vector (make_number (XLFD_LAST), Qnil);
-  for (i = 0; i < XLFD_LAST; i++)
-    if (font.fields[i][0] != '*')
-      ASET (vec, i, build_string (font.fields[i]));
-  return vec;
-}
-
-Lisp_Object
-build_font_name_from_vector (vec)
-     Lisp_Object vec;
-{
-  struct font_name font;
-  Lisp_Object fontname;
-  char *p;
-  int i;
-
-  for (i = 0; i < XLFD_LAST; i++)
-    {
-      font.fields[i] = (NILP (AREF (vec, i))
-                       ? "*" : (char *) SDATA (AREF (vec, i)));
-      if ((i == XLFD_FAMILY || i == XLFD_REGISTRY)
-         && (p = strchr (font.fields[i], '-')))
-       {
-         char *p1 = STRDUPA (font.fields[i]);
-
-         p1[p - font.fields[i]] = '\0';
-         if (i == XLFD_FAMILY)
-           {
-             font.fields[XLFD_FOUNDRY] = p1;
-             font.fields[XLFD_FAMILY] = p + 1;
-           }
-         else
-           {
-             font.fields[XLFD_REGISTRY] = p1;
-             font.fields[XLFD_ENCODING] = p + 1;
-             break;
-           }
-       }
-    }
-
-  p = build_font_name (&font);
-  fontname = build_string (p);
-  xfree (p);
-  return fontname;
-}
-
-/* Return non-zero if FONT is the name of a fixed-pitch font.  */
-
-static INLINE int
-xlfd_fixed_p (font)
-     struct font_name *font;
-{
-  /* Function split_font_name converts fields to lower-case, so there
-     is no need to use tolower here.  */
-  return *font->fields[XLFD_SPACING] != 'p';
-}
-
-
-/* Return the point size of FONT on frame F, measured in 1/10 pt.
-
-   The actual height of the font when displayed on F depends on the
-   resolution of both the font and frame.  For example, a 10pt font
-   designed for a 100dpi display will display larger than 10pt on a
-   75dpi display.  (It's not unusual to use fonts not designed for the
-   display one is using.  For example, some intlfonts are available in
-   72dpi versions, only.)
-
-   Value is the real point size of FONT on frame F, or 0 if it cannot
-   be determined.
-
-   By side effect, set FONT->numeric[XLFD_PIXEL_SIZE].  */
-
-static INLINE int
-xlfd_point_size (f, font)
-     struct frame *f;
-     struct font_name *font;
-{
-  double resy = FRAME_X_DISPLAY_INFO (f)->resy;
-  char *pixel_field = font->fields[XLFD_PIXEL_SIZE];
-  double pixel;
-  int real_pt;
-
-  if (*pixel_field == '[')
-    {
-      /* The pixel size field is `[A B C D]' which specifies
-        a transformation matrix.
-
-        A  B  0
-        C  D  0
-        0  0  1
-
-        by which all glyphs of the font are transformed.  The spec
-        says that s scalar value N for the pixel size is equivalent
-        to A = N * resx/resy, B = C = 0, D = N.  */
-      char *start = pixel_field + 1, *end;
-      double matrix[4];
-      int i;
-
-      for (i = 0; i < 4; ++i)
-       {
-         matrix[i] = strtod (start, &end);
-         start = end;
-       }
-
-      pixel = matrix[3];
-    }
-  else
-    pixel = atoi (pixel_field);
-
-  font->numeric[XLFD_PIXEL_SIZE] = pixel;
-  if (pixel == 0)
-    real_pt = 0;
-  else
-    real_pt = PT_PER_INCH * 10.0 * pixel / resy + 0.5;
-
-  return real_pt;
-}
-
-
-/* Return point size of PIXEL dots while considering Y-resultion (DPI)
-   of frame F.  This function is used to guess a point size of font
-   when only the pixel height of the font is available.  */
-
-static INLINE int
-pixel_point_size (f, pixel)
-     struct frame *f;
-     int pixel;
-{
-  double resy = FRAME_X_DISPLAY_INFO (f)->resy;
-  double real_pt;
-  int int_pt;
-
-  /* As one inch is PT_PER_INCH points, PT_PER_INCH/RESY gives the
-     point size of one dot.  */
-  real_pt = pixel * PT_PER_INCH / resy;
-  int_pt = real_pt + 0.5;
-
-  return int_pt;
-}
-
-
-/* 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;
-}
-
-
-/* Split XLFD font name FONT->name destructively into NUL-terminated,
-   lower-case fields in FONT->fields.  NUMERIC_P non-zero means
-   compute numeric values for fields XLFD_POINT_SIZE, XLFD_SWIDTH,
-   XLFD_RESY, XLFD_SLANT, and XLFD_WEIGHT in FONT->numeric.  Value is
-   zero if the font name doesn't have the format we expect.  The
-   expected format is a font name that starts with a `-' and has
-   XLFD_LAST fields separated by `-'.  */
-
-static int
-split_font_name (f, font, numeric_p)
-     struct frame *f;
-     struct font_name *font;
-     int numeric_p;
-{
-  int i = 0;
-  int success_p;
-  double rescale_ratio;
-
-  if (numeric_p)
-    /* This must be done before splitting the font name.  */
-    rescale_ratio = font_rescale_ratio (font->name);
-
-  if (*font->name == '-')
-    {
-      char *p = xstrlwr (font->name) + 1;
-
-      while (i < XLFD_LAST)
-       {
-         font->fields[i] = p;
-         ++i;
-
-         /* Pixel and point size may be of the form `[....]'.  For
-            BNF, see XLFD spec, chapter 4.  Negative values are
-            indicated by tilde characters which we replace with
-            `-' characters, here.  */
-         if (*p == '['
-             && (i - 1 == XLFD_PIXEL_SIZE
-                 || i - 1 == XLFD_POINT_SIZE))
-           {
-             char *start, *end;
-             int j;
-
-             for (++p; *p && *p != ']'; ++p)
-               if (*p == '~')
-                 *p = '-';
-
-             /* Check that the matrix contains 4 floating point
-                numbers.  */
-             for (j = 0, start = font->fields[i - 1] + 1;
-                  j < 4;
-                  ++j, start = end)
-               if (strtod (start, &end) == 0 && start == end)
-                 break;
-
-             if (j < 4)
-               break;
-           }
-
-         while (*p && *p != '-')
-           ++p;
-
-         if (*p != '-')
-           break;
-
-         *p++ = 0;
-       }
-    }
-
-  success_p = i == XLFD_LAST;
-
-  /* If requested, and font name was in the expected format,
-     compute numeric values for some fields.  */
-  if (numeric_p && success_p)
-    {
-      font->numeric[XLFD_POINT_SIZE] = xlfd_point_size (f, font);
-      font->numeric[XLFD_RESY] = atoi (font->fields[XLFD_RESY]);
-      font->numeric[XLFD_SLANT] = xlfd_numeric_slant (font);
-      font->numeric[XLFD_WEIGHT] = xlfd_numeric_weight (font);
-      font->numeric[XLFD_SWIDTH] = xlfd_numeric_swidth (font);
-      font->numeric[XLFD_AVGWIDTH] = atoi (font->fields[XLFD_AVGWIDTH]);
-      font->rescale_ratio = rescale_ratio;
-    }
-
-  /* Initialize it to zero.  It will be overridden by font_list while
-     trying alternate registries.  */
-  font->registry_priority = 0;
-
-  return success_p;
-}
-
-
-/* Build an XLFD font name from font name fields in FONT.  Value is a
-   pointer to the font name, which is allocated via xmalloc.  */
-
-static char *
-build_font_name (font)
-     struct font_name *font;
-{
-  int i;
-  int size = 100;
-  char *font_name = (char *) xmalloc (size);
-  int total_length = 0;
-
-  for (i = 0; i < XLFD_LAST; ++i)
-    {
-      /* Add 1 because of the leading `-'.  */
-      int len = strlen (font->fields[i]) + 1;
-
-      /* Reallocate font_name if necessary.  Add 1 for the final
-         NUL-byte.  */
-      if (total_length + len + 1 >= size)
-       {
-         int new_size = max (2 * size, size + len + 1);
-         int sz = new_size * sizeof *font_name;
-         font_name = (char *) xrealloc (font_name, sz);
-         size = new_size;
-       }
-
-      font_name[total_length] = '-';
-      bcopy (font->fields[i], font_name + total_length + 1, len - 1);
-      total_length += len;
-    }
-
-  font_name[total_length] = 0;
-  return font_name;
-}
-
-
-/* Free an array FONTS of N font_name structures.  This frees FONTS
-   itself and all `name' fields in its elements.  */
-
-static INLINE void
-free_font_names (fonts, n)
-     struct font_name *fonts;
-     int n;
-{
-  while (n)
-    xfree (fonts[--n].name);
-  xfree (fonts);
-}
-
-
-/* Sort vector FONTS of font_name structures which contains NFONTS
-   elements using qsort and comparison function CMPFN.  F is the frame
-   on which the fonts will be used.  The global variable font_frame
-   is temporarily set to F to make it available in CMPFN.  */
-
-static INLINE void
-sort_fonts (f, fonts, nfonts, cmpfn)
-     struct frame *f;
-     struct font_name *fonts;
-     int nfonts;
-     int (*cmpfn) P_ ((const void *, const void *));
-{
-  font_frame = f;
-  qsort (fonts, nfonts, sizeof *fonts, cmpfn);
-  font_frame = NULL;
-}
-
-
-/* Get fonts matching PATTERN on frame F.  If F is null, use the first
-   display in x_display_list.  FONTS is a pointer to a vector of
-   NFONTS font_name structures.  TRY_ALTERNATIVES_P non-zero means try
-   alternative patterns from Valternate_fontname_alist if no fonts are
-   found matching PATTERN.
-
-   For all fonts found, set FONTS[i].name to the name of the font,
-   allocated via xmalloc, and split font names into fields.  Ignore
-   fonts that we can't parse.  Value is the number of fonts found.  */
-
-static int
-x_face_list_fonts (f, pattern, pfonts, nfonts, try_alternatives_p)
-     struct frame *f;
-     char *pattern;
-     struct font_name **pfonts;
-     int nfonts, try_alternatives_p;
-{
-  int n, nignored;
-
-  /* NTEMACS_TODO : currently this uses w32_list_fonts, but it may be
-     better to do it the other way around. */
-  Lisp_Object lfonts;
-  Lisp_Object lpattern, tem;
-  struct font_name *fonts = 0;
-  int num_fonts = nfonts;
-
-  *pfonts = 0;
-  lpattern = build_string (pattern);
-
-  /* Get the list of fonts matching PATTERN.  */
-#ifdef WINDOWSNT
-  BLOCK_INPUT;
-  lfonts = w32_list_fonts (f, lpattern, 0, nfonts);
-  UNBLOCK_INPUT;
-#else
-  lfonts = x_list_fonts (f, lpattern, -1, nfonts);
-#endif
-
-  if (nfonts < 0 && CONSP (lfonts))
-    num_fonts = XFASTINT (Flength (lfonts));
-
-  /* Make a copy of the font names we got from X, and
-     split them into fields.  */
-  n = nignored = 0;
-  for (tem = lfonts; CONSP (tem) && n < num_fonts; tem = XCDR (tem))
-    {
-      Lisp_Object elt, tail;
-      const char *name = SDATA (XCAR (tem));
-
-      /* Ignore fonts matching a pattern from face-ignored-fonts.  */
-      for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
-       {
-         elt = XCAR (tail);
-         if (STRINGP (elt)
-             && fast_c_string_match_ignore_case (elt, name) >= 0)
-           break;
-       }
-      if (!NILP (tail))
-       {
-         ++nignored;
-         continue;
-       }
-
-      if (! fonts)
-        {
-          *pfonts = (struct font_name *) xmalloc (num_fonts * sizeof **pfonts);
-          fonts = *pfonts;
-        }
-
-      /* Make a copy of the font name.  */
-      fonts[n].name = xstrdup (name);
-
-      if (split_font_name (f, fonts + n, 1))
-       {
-         if (font_scalable_p (fonts + n)
-             && !may_use_scalable_font_p (name))
-           {
-             ++nignored;
-             xfree (fonts[n].name);
-           }
-         else
-           ++n;
-       }
-      else
-       xfree (fonts[n].name);
-    }
-
-  /* If no fonts found, try patterns from Valternate_fontname_alist.  */
-  if (n == 0 && try_alternatives_p)
-    {
-      Lisp_Object list = Valternate_fontname_alist;
-
-      if (*pfonts)
-        {
-          xfree (*pfonts);
-          *pfonts = 0;
-        }
-
-      while (CONSP (list))
-       {
-         Lisp_Object entry = XCAR (list);
-         if (CONSP (entry)
-             && STRINGP (XCAR (entry))
-             && strcmp (SDATA (XCAR (entry)), pattern) == 0)
-           break;
-         list = XCDR (list);
-       }
-
-      if (CONSP (list))
-       {
-         Lisp_Object patterns = XCAR (list);
-         Lisp_Object name;
-
-         while (CONSP (patterns)
-                /* If list is screwed up, give up.  */
-                && (name = XCAR (patterns),
-                    STRINGP (name))
-                /* Ignore patterns equal to PATTERN because we tried that
-                   already with no success.  */
-                && (strcmp (SDATA (name), pattern) == 0
-                    || (n = x_face_list_fonts (f, SDATA (name),
-                                               pfonts, nfonts, 0),
-                        n == 0)))
-           patterns = XCDR (patterns);
-       }
-    }
-
-  return n;
-}
-
-
-/* Check if a font matching pattern_offset_t on frame F is available
-   or not.  PATTERN may be a cons (FAMILY . REGISTRY), in which case,
-   a font name pattern is generated from FAMILY and REGISTRY.  */
-
-int
-face_font_available_p (f, pattern)
-     struct frame *f;
-     Lisp_Object pattern;
-{
-  Lisp_Object fonts;
-
-  if (! STRINGP (pattern))
-    {
-      Lisp_Object family, registry;
-      char *family_str, *registry_str, *pattern_str;
-
-      CHECK_CONS (pattern);
-      family = XCAR (pattern);
-      if (NILP (family))
-       family_str = "*";
-      else
-       {
-         CHECK_STRING (family);
-         family_str = (char *) SDATA (family);
-       }
-      registry = XCDR (pattern);
-      if (NILP (registry))
-       registry_str = "*";
-      else
-       {
-         CHECK_STRING (registry);
-         registry_str = (char *) SDATA (registry);
-       }
-
-      pattern_str = (char *) alloca (strlen (family_str)
-                                    + strlen (registry_str)
-                                    + 10);
-      strcpy (pattern_str, index (family_str, '-') ? "-" : "-*-");
-      strcat (pattern_str, family_str);
-      strcat (pattern_str, "-*-");
-      strcat (pattern_str, registry_str);
-      if (!index (registry_str, '-'))
-       {
-         if (registry_str[strlen (registry_str) - 1] == '*')
-           strcat (pattern_str, "-*");
-         else
-           strcat (pattern_str, "*-*");
-       }
-      pattern = build_string (pattern_str);
-    }
-
-  /* Get the list of fonts matching PATTERN.  */
-#ifdef WINDOWSNT
-  BLOCK_INPUT;
-  fonts = w32_list_fonts (f, pattern, 0, 1);
-  UNBLOCK_INPUT;
-#else
-  fonts = x_list_fonts (f, pattern, -1, 1);
-#endif
-  return XINT (Flength (fonts));
-}
-
-
-/* Determine fonts matching PATTERN on frame F.  Sort resulting fonts
-   using comparison function CMPFN.  Value is the number of fonts
-   found.  If value is non-zero, *FONTS is set to a vector of
-   font_name structures allocated from the heap containing matching
-   fonts.  Each element of *FONTS contains a name member that is also
-   allocated from the heap.  Font names in these structures are split
-   into fields.  Use free_font_names to free such an array.  */
-
-static int
-sorted_font_list (f, pattern, cmpfn, fonts)
-     struct frame *f;
-     char *pattern;
-     int (*cmpfn) P_ ((const void *, const void *));
-     struct font_name **fonts;
-{
-  int nfonts;
-
-  /* Get the list of fonts matching pattern.  100 should suffice.  */
-  nfonts = DEFAULT_FONT_LIST_LIMIT;
-  if (INTEGERP (Vfont_list_limit))
-    nfonts = XINT (Vfont_list_limit);
-
-  *fonts = NULL;
-  nfonts = x_face_list_fonts (f, pattern, fonts, nfonts, 1);
-
-  /* Sort the resulting array and return it in *FONTS.  If no
-     fonts were found, make sure to set *FONTS to null.  */
-  if (nfonts)
-    sort_fonts (f, *fonts, nfonts, cmpfn);
-  else if (*fonts)
-    {
-      xfree (*fonts);
-      *fonts = NULL;
-    }
-
-  return nfonts;
-}
-
-
-/* Compare two font_name structures *A and *B.  Value is analogous to
-   strcmp.  Sort order is given by the global variable
-   font_sort_order.  Font names are sorted so that, everything else
-   being equal, fonts with a resolution closer to that of the frame on
-   which they are used are listed first.  The global variable
-   font_frame is the frame on which we operate.  */
-
-static int
-cmp_font_names (a, b)
-     const void *a, *b;
-{
-  struct font_name *x = (struct font_name *) a;
-  struct font_name *y = (struct font_name *) b;
-  int cmp;
-
-  /* All strings have been converted to lower-case by split_font_name,
-     so we can use strcmp here.  */
-  cmp = strcmp (x->fields[XLFD_FAMILY], y->fields[XLFD_FAMILY]);
-  if (cmp == 0)
-    {
-      int i;
-
-      for (i = 0; i < DIM (font_sort_order) && cmp == 0; ++i)
-       {
-         int j = font_sort_order[i];
-         cmp = x->numeric[j] - y->numeric[j];
-       }
-
-      if (cmp == 0)
-       {
-         /* Everything else being equal, we prefer fonts with an
-            y-resolution closer to that of the frame.  */
-         int resy = FRAME_X_DISPLAY_INFO (font_frame)->resy;
-         int x_resy = x->numeric[XLFD_RESY];
-         int y_resy = y->numeric[XLFD_RESY];
-         cmp = eabs (resy - x_resy) - eabs (resy - y_resy);
-       }
-    }
-
-  return cmp;
-}
-
-
-/* Get a sorted list of fonts matching PATTERN on frame F.  If PATTERN
-   is nil, list fonts matching FAMILY and REGISTRY.  FAMILY is a
-   family name string or nil.  REGISTRY is a registry name string.
-   Set *FONTS to a vector of font_name structures allocated from the
-   heap containing the fonts found.  Value is the number of fonts
-   found.  */
-
-static int
-font_list_1 (f, pattern, family, registry, fonts)
-     struct frame *f;
-     Lisp_Object pattern, family, registry;
-     struct font_name **fonts;
-{
-  char *pattern_str, *family_str, *registry_str;
-
-  if (NILP (pattern))
-    {
-      family_str = (NILP (family) ? "*" : (char *) SDATA (family));
-      registry_str = (NILP (registry) ? "*" : (char *) SDATA (registry));
-
-      pattern_str = (char *) alloca (strlen (family_str)
-                                    + strlen (registry_str)
-                                    + 10);
-      strcpy (pattern_str, index (family_str, '-') ? "-" : "-*-");
-      strcat (pattern_str, family_str);
-      strcat (pattern_str, "-*-");
-      strcat (pattern_str, registry_str);
-      if (!index (registry_str, '-'))
-       {
-         if (registry_str[strlen (registry_str) - 1] == '*')
-           strcat (pattern_str, "-*");
-         else
-           strcat (pattern_str, "*-*");
-       }
-    }
-  else
-    pattern_str = (char *) SDATA (pattern);
-
-  return sorted_font_list (f, pattern_str, cmp_font_names, fonts);
-}
-
-
-/* Concatenate font list FONTS1 and FONTS2.  FONTS1 and FONTS2
-   contains NFONTS1 fonts and NFONTS2 fonts respectively.  Return a
-   pointer to a newly allocated font list.  FONTS1 and FONTS2 are
-   freed.  */
-
-static struct font_name *
-concat_font_list (fonts1, nfonts1, fonts2, nfonts2)
-     struct font_name *fonts1, *fonts2;
-     int nfonts1, nfonts2;
-{
-  int new_nfonts = nfonts1 + nfonts2;
-  struct font_name *new_fonts;
-
-  new_fonts = (struct font_name *) xmalloc (sizeof *new_fonts * new_nfonts);
-  bcopy (fonts1, new_fonts, sizeof *new_fonts * nfonts1);
-  bcopy (fonts2, new_fonts + nfonts1, sizeof *new_fonts * nfonts2);
-  xfree (fonts1);
-  xfree (fonts2);
-  return new_fonts;
-}
-
-
-/* Get a sorted list of fonts of family FAMILY on frame F.
-
-   If PATTERN is non-nil, list fonts matching that pattern.
-
-   If REGISTRY is non-nil, it is a list of registry (and encoding)
-   names.  Return fonts with those registries and the alternative
-   registries from Vface_alternative_font_registry_alist.
-
-   If REGISTRY is nil return fonts of any registry.
-
-   Set *FONTS to a vector of font_name structures allocated from the
-   heap containing the fonts found.  Value is the number of fonts
-   found.  */
-
-static int
-font_list (f, pattern, family, registry, fonts)
-     struct frame *f;
-     Lisp_Object pattern, family, registry;
-     struct font_name **fonts;
-{
-  int nfonts;
-  int reg_prio;
-  int i;
-
-  if (NILP (registry))
-    return font_list_1 (f, pattern, family, registry, fonts);
-
-  for (reg_prio = 0, nfonts = 0; CONSP (registry); registry = XCDR (registry))
-    {
-      Lisp_Object elt, alter;
-      int nfonts2;
-      struct font_name *fonts2;
-
-      elt = XCAR (registry);
-      alter = Fassoc (elt, Vface_alternative_font_registry_alist);
-      if (NILP (alter))
-       alter = Fcons (elt, Qnil);
-      for (; CONSP (alter); alter = XCDR (alter), reg_prio++)
-       {
-         nfonts2 = font_list_1 (f, pattern, family, XCAR (alter), &fonts2);
-         if (nfonts2 > 0)
-           {
-             if (reg_prio > 0)
-               for (i = 0; i < nfonts2; i++)
-                 fonts2[i].registry_priority = reg_prio;
-             if (nfonts > 0)
-               *fonts = concat_font_list (*fonts, nfonts, fonts2, nfonts2);
-             else
-               *fonts = fonts2;
-             nfonts += nfonts2;
-           }
-       }
-    }
-
-  return nfonts;
-}
-
-
-/* Remove elements from LIST whose cars are `equal'.  Called from
-   x-family-fonts and x-font-family-list to remove duplicate font
-   entries.  */
-
-static void
-remove_duplicates (list)
-     Lisp_Object list;
-{
-  Lisp_Object tail = list;
-
-  while (!NILP (tail) && !NILP (XCDR (tail)))
-    {
-      Lisp_Object next = XCDR (tail);
-      if (!NILP (Fequal (XCAR (next), XCAR (tail))))
-       XSETCDR (tail, XCDR (next));
-      else
-       tail = XCDR (tail);
-    }
-}
-
-
-DEFUN ("x-family-fonts", Fx_family_fonts, Sx_family_fonts, 0, 2, 0,
-       doc: /* Return a list of available fonts of family FAMILY on FRAME.
-If FAMILY is omitted or nil, list all families.
-Otherwise, FAMILY must be a string, possibly containing wildcards
-`?' and `*'.
-If FRAME is omitted or nil, use the selected frame.
-Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT
-SLANT FIXED-P FULL REGISTRY-AND-ENCODING].
-FAMILY is the font family name.  POINT-SIZE is the size of the
-font in 1/10 pt.  WIDTH, WEIGHT, and SLANT are symbols describing the
-width, weight and slant of the font.  These symbols are the same as for
-face attributes.  FIXED-P is non-nil if the font is fixed-pitch.
-FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string
-giving the registry and encoding of the font.
-The result list is sorted according to the current setting of
-the face font sort order.  */)
-     (family, frame)
-     Lisp_Object family, frame;
-{
-  struct frame *f = check_x_frame (frame);
-  struct font_name *fonts;
-  int i, nfonts;
-  Lisp_Object result;
-  struct gcpro gcpro1;
-
-  if (!NILP (family))
-    CHECK_STRING (family);
-
-  result = Qnil;
-  GCPRO1 (result);
-  nfonts = font_list (f, Qnil, family, Qnil, &fonts);
-  for (i = nfonts - 1; i >= 0; --i)
-    {
-      Lisp_Object v = Fmake_vector (make_number (8), Qnil);
-      char *tem;
-
-      ASET (v, 0, build_string (fonts[i].fields[XLFD_FAMILY]));
-      ASET (v, 1, xlfd_symbolic_swidth (fonts + i));
-      ASET (v, 2, make_number (xlfd_point_size (f, fonts + i)));
-      ASET (v, 3, xlfd_symbolic_weight (fonts + i));
-      ASET (v, 4, xlfd_symbolic_slant (fonts + i));
-      ASET (v, 5, xlfd_fixed_p (fonts + i) ? Qt : Qnil);
-      tem = build_font_name (fonts + i);
-      ASET (v, 6, build_string (tem));
-      sprintf (tem, "%s-%s", fonts[i].fields[XLFD_REGISTRY],
-              fonts[i].fields[XLFD_ENCODING]);
-      ASET (v, 7, build_string (tem));
-      xfree (tem);
-
-      result = Fcons (v, result);
-    }
-
-  remove_duplicates (result);
-  free_font_names (fonts, nfonts);
-  UNGCPRO;
-  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;
-{
-  struct frame *f = check_x_frame (frame);
-  int nfonts, i;
-  struct font_name *fonts;
-  Lisp_Object result;
-  struct gcpro gcpro1;
-  int count = SPECPDL_INDEX ();
-
-  /* Let's consider all fonts.  */
-  specbind (intern ("font-list-limit"), make_number (-1));
-  nfonts = font_list (f, Qnil, Qnil, Qnil, &fonts);
-
-  result = Qnil;
-  GCPRO1 (result);
-  for (i = nfonts - 1; i >= 0; --i)
-    result = Fcons (Fcons (build_string (fonts[i].fields[XLFD_FAMILY]),
-                          xlfd_fixed_p (fonts + i) ? Qt : Qnil),
-                   result);
-
-  remove_duplicates (result);
-  free_font_names (fonts, nfonts);
-  UNGCPRO;
-  return unbind_to (count, result);
-}
-
-
-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;
-  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.
-
-Fonts Emacs can't use may or may not be excluded
-even if they match PATTERN and FACE.
-The optional fourth argument MAXIMUM sets a limit on how many
-fonts to match.  The first MAXIMUM fonts are reported.
-The optional fifth argument WIDTH, if specified, is a number of columns
-occupied by a character of a font.  In that case, return only fonts
-the WIDTH times as wide as FACE on FRAME.  */)
-     (pattern, face, frame, maximum, width)
-    Lisp_Object pattern, face, frame, maximum, width;
-{
-  struct frame *f;
-  int size;
-  int maxnames;
-
-  check_x ();
-  CHECK_STRING (pattern);
-
-  if (NILP (maximum))
-    maxnames = -1;
-  else
-    {
-      CHECK_NATNUM (maximum);
-      maxnames = XINT (maximum);
-    }
-
-  if (!NILP (width))
-    CHECK_NUMBER (width);
+  if (!NILP (width))
+    CHECK_NUMBER (width);
 
   /* We can't simply call check_x_frame because this function may be
      called before any frame is created.  */
+  if (NILP (frame))
+    frame = selected_frame;
   f = frame_or_selected_frame (frame, 2);
-  if (!FRAME_WINDOW_P (f))
+  if (! FRAME_WINDOW_P (f))
     {
       /* Perhaps we have not yet created any frame.  */
       f = NULL;
+      frame = Qnil;
       face = Qnil;
     }
 
@@ -3141,19 +1827,51 @@ the WIDTH times as wide as FACE on FRAME.  */)
                           : FACE_FROM_ID (f, face_id));
 
       if (face && face->font)
-       size = FONT_WIDTH (face->font);
+       {
+         size = face->font->pixel_size;
+         avgwidth = face->font->average_width;
+       }
       else
-       size = FONT_WIDTH (FRAME_FONT (f));  /* FRAME_COLUMN_WIDTH (f) */
-
+       {
+         size = FRAME_FONT (f)->pixel_size;
+         avgwidth = FRAME_FONT (f)->average_width;
+       }
       if (!NILP (width))
-       size *= XINT (width);
+       avgwidth *= XINT (width);
     }
 
   {
-    Lisp_Object args[2];
+    Lisp_Object font_spec;
+    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, font_spec);
+    for (tail = args[0]; CONSP (tail); tail = XCDR (tail))
+      {
+       Lisp_Object font_entity;
 
-    args[0] = x_list_fonts (f, pattern, size, maxnames);
-    if (f == NULL)
+       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];
     args[1] = list_fontsets (f, pattern, size);
@@ -3163,7 +1881,6 @@ the WIDTH times as wide as FACE on FRAME.  */)
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
-
 \f
 /***********************************************************************
                              Lisp Faces
@@ -3172,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)
@@ -3186,7 +1904,6 @@ the WIDTH times as wide as FACE on FRAME.  */)
 #define LFACE_BOX(LFACE)           AREF ((LFACE), LFACE_BOX_INDEX)
 #define LFACE_FONT(LFACE)          AREF ((LFACE), LFACE_FONT_INDEX)
 #define LFACE_INHERIT(LFACE)       AREF ((LFACE), LFACE_INHERIT_INDEX)
-#define LFACE_AVGWIDTH(LFACE)      AREF ((LFACE), LFACE_AVGWIDTH_INDEX)
 #define LFACE_FONTSET(LFACE)       AREF ((LFACE), LFACE_FONTSET_INDEX)
 
 /* Non-zero if LFACE is a Lisp face.  A Lisp face is a vector of size
@@ -3209,12 +1926,12 @@ 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]));
-  xassert (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
-          || IGNORE_DEFFACE_P (attrs[LFACE_AVGWIDTH_INDEX])
-          || INTEGERP (attrs[LFACE_AVGWIDTH_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
           || IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX])
           || INTEGERP (attrs[LFACE_HEIGHT_INDEX])
@@ -3265,11 +1982,7 @@ check_lface_attrs (attrs)
           || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
   xassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
           || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX])
-          || NILP (attrs[LFACE_FONT_INDEX])
-#ifdef USE_FONT_BACKEND
-          || FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])
-#endif /* USE_FONT_BACKEND */
-          || STRINGP (attrs[LFACE_FONT_INDEX]));
+          || FONTP (attrs[LFACE_FONT_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
           || STRINGP (attrs[LFACE_FONTSET_INDEX]));
 #endif
@@ -3300,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
@@ -3309,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;
@@ -3363,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;
@@ -3407,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
@@ -3434,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
@@ -3445,193 +2183,87 @@ 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))
-    {
-      bcopy (XVECTOR (lface)->contents, attrs,
-            LFACE_VECTOR_SIZE * sizeof *attrs);
-      success_p = 1;
-    }
-  else
-    success_p = 0;
 
-  return success_p;
-}
-
-
-/* Non-zero if all attributes in face attribute vector ATTRS are
-   specified, i.e. are non-nil.  */
-
-static int
-lface_fully_specified_p (attrs)
-     Lisp_Object *attrs;
-{
-  int i;
+  lface = lface_from_face_name_no_resolve (f, face_name, signal_p);
 
-  for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-    if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX
-       && i != LFACE_AVGWIDTH_INDEX && i != LFACE_FONTSET_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
-          )
-        break;
+  if (! NILP (lface))
+    memcpy (attrs, XVECTOR (lface)->contents,
+           LFACE_VECTOR_SIZE * sizeof *attrs);
 
-  return i == LFACE_VECTOR_SIZE;
+  return !NILP (lface);
 }
 
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* Set font-related attributes of Lisp face LFACE from the fullname of
-   the font opened by FONTNAME.  If FORCE_P is zero, set only
-   unspecified attributes of LFACE.  The exception is `font'
-   attribute.  It is set to FONTNAME as is regardless of FORCE_P.
-
-   If FONTNAME is not available on frame F,
-       return 0 if MAY_FAIL_P is non-zero, otherwise abort.
-   If the fullname is not in a valid XLFD format,
-       return 0 if MAY_FAIL_P is non-zero, otherwise set normal values
-       in LFACE and return 1.
-   Otherwise, return 1.  */
+/* 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 int
-set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
-     struct frame *f;
-     Lisp_Object lface;
-     Lisp_Object fontname;
-     int force_p, may_fail_p;
+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)
 {
-  struct font_name font;
-  char *buffer;
-  int pt;
-  int have_xlfd_p;
-  int fontset;
-  char *font_name = SDATA (fontname);
-  struct font_info *font_info;
-
-  /* If FONTNAME is actually a fontset name, get ASCII font name of it.  */
-  fontset = fs_query_fontset (fontname, 0);
+  Lisp_Object face_remapping;
 
-  if (fontset > 0)
-    font_name = SDATA (fontset_ascii (fontset));
-  else if (fontset == 0)
-    {
-      if (may_fail_p)
-       return 0;
-      abort ();
-    }
-
-  /* Check if FONT_NAME is surely available on the system.  Usually
-     FONT_NAME is already cached for the frame F and FS_LOAD_FONT
-     returns quickly.  But, even if FONT_NAME is not yet cached,
-     caching it now is not futail because we anyway load the font
-     later.  */
-  BLOCK_INPUT;
-  font_info = FS_LOAD_FONT (f, font_name);
-  UNBLOCK_INPUT;
+  face_name = resolve_face_name (face_name, signal_p);
 
-  if (!font_info)
+  /* 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))
     {
-      if (may_fail_p)
-       return 0;
-      abort ();
-    }
+      struct named_merge_point named_merge_point;
 
-  font.name = STRDUPA (font_info->full_name);
-  have_xlfd_p = split_font_name (f, &font, 1);
+      if (push_named_merge_point (&named_merge_point,
+                                 face_name, NAMED_MERGE_POINT_REMAP,
+                                 &named_merge_points))
+       {
+         int i;
 
-  /* Set attributes only if unspecified, otherwise face defaults for
-     new frames would never take effect.  If we couldn't get a font
-     name conforming to XLFD, set normal values.  */
+         for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
+           attrs[i] = Qunspecified;
 
-  if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
-    {
-      Lisp_Object val;
-      if (have_xlfd_p)
-       {
-         buffer = (char *) alloca (strlen (font.fields[XLFD_FAMILY])
-                                   + strlen (font.fields[XLFD_FOUNDRY])
-                                   + 2);
-         sprintf (buffer, "%s-%s", font.fields[XLFD_FOUNDRY],
-                  font.fields[XLFD_FAMILY]);
-         val = build_string (buffer);
+         return merge_face_ref (f, XCDR (face_remapping), attrs,
+                                signal_p, named_merge_points);
        }
-      else
-       val = build_string ("*");
-      LFACE_FAMILY (lface) = val;
     }
 
-  if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
-    {
-      if (have_xlfd_p)
-       pt = xlfd_point_size (f, &font);
-      else
-       pt = pixel_point_size (f, font_info->height * 10);
-      xassert (pt > 0);
-      LFACE_HEIGHT (lface) = make_number (pt);
-    }
+  /* Default case, no remapping.  */
+  return get_lface_attributes_no_remap (f, face_name, attrs, signal_p);
+}
 
-  if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
-    LFACE_SWIDTH (lface)
-      = have_xlfd_p ? xlfd_symbolic_swidth (&font) : Qnormal;
 
-  if (force_p || UNSPECIFIEDP (LFACE_AVGWIDTH (lface)))
-    LFACE_AVGWIDTH (lface)
-      = (have_xlfd_p
-        ? make_number (font.numeric[XLFD_AVGWIDTH])
-        : Qunspecified);
+/* Non-zero if all attributes in face attribute vector ATTRS are
+   specified, i.e. are non-nil.  */
 
-  if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
-    LFACE_WEIGHT (lface)
-      = have_xlfd_p ? xlfd_symbolic_weight (&font) : Qnormal;
+static int
+lface_fully_specified_p (Lisp_Object *attrs)
+{
+  int i;
 
-  if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
-    LFACE_SLANT (lface)
-      = have_xlfd_p ? xlfd_symbolic_slant (&font) : Qnormal;
+  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])))
+        break;
 
-  if (fontset > 0)
-    {
-      LFACE_FONT (lface) = build_string (font_info->full_name);
-      LFACE_FONTSET (lface) = fontset_name (fontset);
-    }
-  else
-    {
-      LFACE_FONT (lface) = fontname;
-      fontset
-       = new_fontset_from_font_name (build_string (font_info->full_name));
-      LFACE_FONTSET (lface) = fontset_name (fontset);
-    }
-  return 1;
+  return i == LFACE_VECTOR_SIZE;
 }
 
-#ifdef USE_FONT_BACKEND
-/* Set font-related attributes of Lisp face LFACE from FONT-OBJECT and
-   FONTSET.  If FORCE_P is zero, set only unspecified attributes of
-   LFACE.  The exceptions are `font' and `fontset' attributes.  They
-   are set regardless of FORCE_P.  */
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* Set font-related attributes of Lisp face LFACE from FONT-OBJECT.
+   If FORCE_P is zero, set only unspecified attributes of LFACE.  The
+   exception is `font' attribute.  It is set to FONT_OBJECT regardless
+   of FORCE_P.  */
 
-static void
-set_lface_from_font_and_fontset (f, lface, font_object, fontset, force_p)
-     struct frame *f;
-     Lisp_Object lface, font_object;
-     int fontset;
-     int force_p;
+static int
+set_lface_from_font (struct frame *f, Lisp_Object lface, Lisp_Object font_object, int force_p)
 {
-  struct font *font = XSAVE_VALUE (font_object)->pointer;
-  Lisp_Object entity = font->entity;
   Lisp_Object val;
+  struct font *font = XFONT_OBJECT (font_object);
 
   /* Set attributes only if unspecified, otherwise face defaults for
      new frames would never take effect.  If the font doesn't have a
@@ -3639,65 +2271,45 @@ set_lface_from_font_and_fontset (f, lface, font_object, fontset, force_p)
 
   if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
     {
-      Lisp_Object foundry = AREF (entity, FONT_FOUNDRY_INDEX);
-      Lisp_Object family = AREF (entity, FONT_FAMILY_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)))
     {
-      int pt = pixel_point_size (f, font->pixel_size * 10);
+      int pt = PIXEL_TO_POINT (font->pixel_size * 10, f->resy);
 
       xassert (pt > 0);
       LFACE_HEIGHT (lface) = make_number (pt);
     }
 
-  if (force_p || UNSPECIFIEDP (LFACE_AVGWIDTH (lface)))
-    LFACE_AVGWIDTH (lface) = make_number (font->font.average_width);
-
   if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
     {
-      Lisp_Object weight = font_symbolic_weight (entity);
-
-      val = NILP (weight) ? Qnormal : face_symbolic_weight (weight);
-      LFACE_WEIGHT (lface) = ! NILP (val) ? val : weight;
+      val = FONT_WEIGHT_FOR_FACE (font_object);
+      LFACE_WEIGHT (lface) = ! NILP (val) ? val :Qnormal;
     }
   if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
     {
-      Lisp_Object slant = font_symbolic_slant (entity);
-
-      val = NILP (slant) ? Qnormal : face_symbolic_slant (slant);
-      LFACE_SLANT (lface) = ! NILP (val) ? val : slant;
+      val = FONT_SLANT_FOR_FACE (font_object);
+      LFACE_SLANT (lface) = ! NILP (val) ? val : Qnormal;
     }
   if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
     {
-      Lisp_Object width = font_symbolic_width (entity);
-
-      val = NILP (width) ? Qnormal : face_symbolic_swidth (width);
-      LFACE_SWIDTH (lface) = ! NILP (val) ? val : width;
+      val = FONT_WIDTH_FOR_FACE (font_object);
+      LFACE_SWIDTH (lface) = ! NILP (val) ? val : Qnormal;
     }
 
-  LFACE_FONT (lface) = make_unibyte_string (font->font.full_name,
-                                           strlen (font->font.full_name));
-  LFACE_FONTSET (lface) = fontset_name (fontset);
+  LFACE_FONT (lface) = font_object;
+  return 1;
 }
-#endif /* USE_FONT_BACKEND */
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
@@ -3706,13 +2318,10 @@ set_lface_from_font_and_fontset (f, lface, font_object, fontset, 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;
 
@@ -3757,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;
 
@@ -3777,26 +2383,47 @@ merge_face_vectors (f, from, to, named_merge_points)
       && !NILP (from[LFACE_INHERIT_INDEX]))
     merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, 0, named_merge_points);
 
-  /* If TO specifies a :font attribute, and FROM specifies some
-     font-related attribute, we need to clear TO's :font attribute
-     (because it will be inconsistent with whatever FROM specifies, and
-     FROM takes precedence).  */
-  if (!NILP (to[LFACE_FONT_INDEX])
-      && (!UNSPECIFIEDP (from[LFACE_FAMILY_INDEX])
-         || !UNSPECIFIEDP (from[LFACE_HEIGHT_INDEX])
-         || !UNSPECIFIEDP (from[LFACE_WEIGHT_INDEX])
-         || !UNSPECIFIEDP (from[LFACE_SLANT_INDEX])
-         || !UNSPECIFIEDP (from[LFACE_SWIDTH_INDEX])
-         || !UNSPECIFIEDP (from[LFACE_AVGWIDTH_INDEX])))
-    to[LFACE_FONT_INDEX] = Qnil;
+  i = LFACE_FONT_INDEX;
+  if (!UNSPECIFIEDP (from[i]))
+    {
+      if (!UNSPECIFIEDP (to[i]))
+       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);
+    }
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (!UNSPECIFIEDP (from[i]))
       {
        if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
-         to[i] = merge_face_heights (from[i], to[i], to[i]);
-       else
-         to[i] = from[i];
+         {
+           to[i] = merge_face_heights (from[i], to[i], to[i]);
+           font_clear_prop (to, FONT_SIZE_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
+                               : FONT_SLANT_INDEX));
+         }
       }
 
   /* TO is always an absolute face, which should inherit from nothing.
@@ -3810,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)
        {
@@ -3863,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? */
 
@@ -3914,7 +2533,20 @@ merge_face_ref (f, face_ref, to, err_msgs, named_merge_points)
              else if (EQ (keyword, QCfamily))
                {
                  if (STRINGP (value))
-                   to[LFACE_FAMILY_INDEX] = value;
+                   {
+                     to[LFACE_FAMILY_INDEX] = value;
+                     font_clear_prop (to, FONT_FAMILY_INDEX);
+                   }
+                 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;
                }
@@ -3924,23 +2556,30 @@ merge_face_ref (f, face_ref, to, err_msgs, named_merge_points)
                    merge_face_heights (value, to[LFACE_HEIGHT_INDEX], Qnil);
 
                  if (! NILP (new_height))
-                   to[LFACE_HEIGHT_INDEX] = new_height;
+                   {
+                     to[LFACE_HEIGHT_INDEX] = new_height;
+                     font_clear_prop (to, FONT_SIZE_INDEX);
+                   }
                  else
                    err = 1;
                }
              else if (EQ (keyword, QCweight))
                {
-                 if (SYMBOLP (value)
-                     && face_numeric_weight (value) >= 0)
-                   to[LFACE_WEIGHT_INDEX] = value;
+                 if (SYMBOLP (value) && FONT_WEIGHT_NAME_NUMERIC (value) >= 0)
+                   {
+                     to[LFACE_WEIGHT_INDEX] = value;
+                     font_clear_prop (to, FONT_WEIGHT_INDEX);
+                   }
                  else
                    err = 1;
                }
              else if (EQ (keyword, QCslant))
                {
-                 if (SYMBOLP (value)
-                     && face_numeric_slant (value) >= 0)
-                   to[LFACE_SLANT_INDEX] = value;
+                 if (SYMBOLP (value) && FONT_SLANT_NAME_NUMERIC (value) >= 0)
+                   {
+                     to[LFACE_SLANT_INDEX] = value;
+                     font_clear_prop (to, FONT_SLANT_INDEX);
+                   }
                  else
                    err = 1;
                }
@@ -4007,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;
@@ -4017,9 +2656,11 @@ merge_face_ref (f, face_ref, to, err_msgs, named_merge_points)
                }
              else if (EQ (keyword, QCwidth))
                {
-                 if (SYMBOLP (value)
-                     && face_numeric_swidth (value) >= 0)
-                   to[LFACE_SWIDTH_INDEX] = value;
+                 if (SYMBOLP (value) && FONT_WIDTH_NAME_NUMERIC (value) >= 0)
+                   {
+                     to[LFACE_SWIDTH_INDEX] = value;
+                     font_clear_prop (to, FONT_WIDTH_INDEX);
+                   }
                  else
                    err = 1;
                }
@@ -4161,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.  */)
@@ -4189,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.  */)
@@ -4219,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
@@ -4250,10 +2892,9 @@ FRAME 0 means change the face on all frames, and change the default
 {
   Lisp_Object lface;
   Lisp_Object old_value = Qnil;
-  /* Set 1 if ATTR is QCfont.  */
-  int font_attr_p = 0;
-  /* Set 1 if ATTR is one of font-related attributes other than QCfont.  */
-  int font_related_attr_p = 0;
+  /* Set one of enum font_property_index (> 0) if ATTR is one of
+     font-related attributes other than QCfont and QCfontset.  */
+  enum font_property_index prop_index = 0;
 
   CHECK_SYMBOL (face);
   CHECK_SYMBOL (attr);
@@ -4308,52 +2949,69 @@ FRAME 0 means change the face on all frames, and change the default
        }
       old_value = LFACE_FAMILY (lface);
       LFACE_FAMILY (lface) = value;
-      font_related_attr_p = 1;
+      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);
       LFACE_HEIGHT (lface) = value;
-      font_related_attr_p = 1;
+      prop_index = FONT_SIZE_INDEX;
     }
   else if (EQ (attr, QCweight))
     {
       if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
        {
          CHECK_SYMBOL (value);
-         if (face_numeric_weight (value) < 0)
+         if (FONT_WEIGHT_NAME_NUMERIC (value) < 0)
            signal_error ("Invalid face weight", value);
        }
       old_value = LFACE_WEIGHT (lface);
       LFACE_WEIGHT (lface) = value;
-      font_related_attr_p = 1;
+      prop_index = FONT_WEIGHT_INDEX;
     }
   else if (EQ (attr, QCslant))
     {
       if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
        {
          CHECK_SYMBOL (value);
-         if (face_numeric_slant (value) < 0)
+         if (FONT_SLANT_NAME_NUMERIC (value) < 0)
            signal_error ("Invalid face slant", value);
        }
       old_value = LFACE_SLANT (lface);
       LFACE_SLANT (lface) = value;
-      font_related_attr_p = 1;
+      prop_index = FONT_SLANT_INDEX;
     }
   else if (EQ (attr, QCunderline))
     {
@@ -4474,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
@@ -4488,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
@@ -4502,98 +3166,86 @@ 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))
     {
       if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
        {
          CHECK_SYMBOL (value);
-         if (face_numeric_swidth (value) < 0)
+         if (FONT_WIDTH_NAME_NUMERIC (value) < 0)
            signal_error ("Invalid face width", value);
        }
       old_value = LFACE_SWIDTH (lface);
       LFACE_SWIDTH (lface) = value;
-      font_related_attr_p = 1;
+      prop_index = FONT_WIDTH_INDEX;
     }
-  else if (EQ (attr, QCfont) || EQ (attr, QCfontset))
+  else if (EQ (attr, QCfont))
     {
 #ifdef HAVE_WINDOW_SYSTEM
       if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
        {
-         /* Set font-related attributes of the Lisp face from an XLFD
-            font name.  */
-         struct frame *f;
-         Lisp_Object tmp;
-
-         if (EQ (frame, Qt))
-           f = SELECTED_FRAME ();
-         else
-           f = check_x_frame (frame);
-
-#ifdef USE_FONT_BACKEND
-         if (enable_font_backend
-             && !UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+         if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
            {
-             tmp = Fquery_fontset (value, Qnil);
-             if (EQ (attr, QCfontset))
+             FRAME_PTR f;
+
+             old_value = LFACE_FONT (lface);
+             if (! FONTP (value))
                {
-                 if (NILP (tmp))
-                   signal_error ("Invalid fontset name", value);
-                 LFACE_FONTSET (lface) = tmp;
+                 if (STRINGP (value))
+                   {
+                     Lisp_Object name = value;
+                     int fontset = fs_query_fontset (name, 0);
+
+                     if (fontset >= 0)
+                       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);
                }
+             if (EQ (frame, Qt))
+               f = XFRAME (selected_frame);
              else
+               f = XFRAME (frame);
+             if (! FONT_OBJECT_P (value))
                {
-                 int fontset;
+                 Lisp_Object *attrs = XVECTOR (lface)->contents;
                  Lisp_Object font_object;
 
-                 if (! NILP (tmp))
-                   {
-                     fontset = fs_query_fontset (tmp, 0);
-                     value = fontset_ascii (fontset);
-                   }
-                 else
-                   {
-                     fontset = FRAME_FONTSET (f);
-                   }
-                 font_object = font_open_by_name (f, SDATA (value));
+                 font_object = font_load_for_lface (f, attrs, value);
                  if (NILP (font_object))
-                   signal_error ("Invalid font", value);
-                 set_lface_from_font_and_fontset (f, lface, font_object,
-                                                  fontset, 1);
+                   signal_error ("Font not available", value);
+                 value = font_object;
                }
+             set_lface_from_font (f, lface, value, 1);
            }
          else
-#endif /* USE_FONT_BACKEND */
-         if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
-           {
-             CHECK_STRING (value);
-
-             /* VALUE may be a fontset name or an alias of fontset.  In
-                such a case, use the base fontset name.  */
-             tmp = Fquery_fontset (value, Qnil);
-             if (!NILP (tmp))
-               value = tmp;
-             else if (EQ (attr, QCfontset))
-               signal_error ("Invalid fontset name", value);
-
-             if (EQ (attr, QCfont))
-               {
-                 if (!set_lface_from_font_name (f, lface, value, 1, 1))
-                   signal_error ("Invalid font or fontset name", value);
-               }
-             else
-               LFACE_FONTSET (lface) = value;
-           }
+           LFACE_FONT (lface) = value;
+       }
+#endif /* HAVE_WINDOW_SYSTEM */
+    }
+  else if (EQ (attr, QCfontset))
+    {
+#ifdef HAVE_WINDOW_SYSTEM
+      if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
+       {
+         Lisp_Object tmp;
 
-         font_attr_p = 1;
+         old_value = LFACE_FONTSET (lface);
+         tmp = Fquery_fontset (value, Qnil);
+         if (NILP (tmp))
+           signal_error ("Invalid fontset name", value);
+         LFACE_FONTSET (lface) = value = tmp;
        }
 #endif /* HAVE_WINDOW_SYSTEM */
     }
@@ -4615,24 +3267,28 @@ FRAME 0 means change the face on all frames, and change the default
     {
       old_value = LFACE_WEIGHT (lface);
       LFACE_WEIGHT (lface) = NILP (value) ? Qnormal : Qbold;
-      font_related_attr_p = 1;
+      prop_index = FONT_WEIGHT_INDEX;
     }
   else if (EQ (attr, QCitalic))
     {
+      attr = QCslant;
       old_value = LFACE_SLANT (lface);
       LFACE_SLANT (lface) = NILP (value) ? Qnormal : Qitalic;
-      font_related_attr_p = 1;
+      prop_index = FONT_SLANT_INDEX;
     }
   else
     signal_error ("Invalid face attribute name", attr);
 
-  if (font_related_attr_p
-      && !UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
-    /* If a font-related attribute other than QCfont is specified, the
-       original `font' attribute nor that of default face is useless
-       to determine a new font.  Thus, we set it to nil so that font
-       selection mechanism doesn't use it.  */
-    LFACE_FONT (lface) = Qnil;
+  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.  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
@@ -4641,9 +3297,7 @@ FRAME 0 means change the face on all frames, and change the default
      init_iterator will then free realized faces.  */
   if (!EQ (frame, Qt)
       && NILP (Fget (face, Qface_no_inherit))
-      && (EQ (attr, QCfont)
-         || EQ (attr, QCfontset)
-         || NILP (Fequal (old_value, value))))
+      && NILP (Fequal (old_value, value)))
     {
       ++face_change_count;
       ++windows_or_buffers_changed;
@@ -4662,7 +3316,7 @@ FRAME 0 means change the face on all frames, and change the default
          /* Changed font-related attributes of the `default' face are
             reflected in changed `font' frame parameters. */
          if (FRAMEP (frame)
-             && (font_related_attr_p || font_attr_p)
+             && (prop_index || EQ (attr, QCfont))
              && lface_fully_specified_p (XVECTOR (lface)->contents))
            set_font_frame_param (frame, lface);
          else
@@ -4747,70 +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 `default'
-   face attributes LFACE.  If a font name is explicitely
-   specfied in LFACE, use it as is.  Otherwise, determine a font name
-   from the other font-related atrributes of LFACE.  In that case, if
-   there's no matching font, signals an error.  */
-
-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_name;
-      char *font;
-
-      if (STRINGP (LFACE_FONT (lface)))
-       font_name = LFACE_FONT (lface);
-#ifdef USE_FONT_BACKEND
-      else if (enable_font_backend)
-       {
-         /* We set FONT_NAME to a font-object.  */
-         if (FONT_OBJECT_P (LFACE_FONT (lface)))
-           font_name = LFACE_FONT (lface);
-         else
-           {
-             font_name = font_find_for_lface (f, &AREF (lface, 0), Qnil, -1);
-             if (NILP (font_name))
-               error ("No font matches the specified attribute");
-             font_name = font_open_for_lface (f, font_name, &AREF (lface, 0),
-                                              Qnil);
-             if (NILP (font_name))
-               error ("No font matches the specified attribute");
-           }
-       }
-#endif
-      else
-       {
-         /* Choose a font name that reflects LFACE's attributes and has
-            the registry and encoding pattern specified in the default
-            fontset (3rd arg: -1) for ASCII characters (4th arg: 0).  */
-         font = choose_face_font (f, XVECTOR (lface)->contents, Qnil, NULL);
-         if (!font)
-           error ("No font matches the specified attribute");
-         font_name = build_string (font);
-         xfree (font);
-       }
-
-      f->default_face_done_p = 0;
-      Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font_name), 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;
@@ -4835,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);
 
@@ -4845,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;
@@ -4866,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
@@ -4881,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.  */
@@ -4908,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);
@@ -4942,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))
     {
@@ -5031,14 +3656,19 @@ x_update_menu_appearance (f)
          changed_p = 1;
        }
 
-      if (face->font_name
+      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_AVGWIDTH (lface))
              || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
              || !UNSPECIFIEDP (LFACE_SLANT (lface))
              || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
        {
+         Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface), Qnil);
 #ifdef USE_MOTIF
          const char *suffix = "List";
          Bool motif = True;
@@ -5051,22 +3681,26 @@ x_update_menu_appearance (f)
 #endif
          Bool motif = False;
 #endif
+
+         if (! NILP (xlfd))
+           {
 #if defined HAVE_X_I18N
-         extern char *xic_create_fontsetname
-           P_ ((char *base_fontname, Bool motif));
-         char *fontsetname = xic_create_fontsetname (face->font_name, motif);
+             extern char *xic_create_fontsetname
+                (char *base_fontname, Bool motif);
+             char *fontsetname = xic_create_fontsetname (SDATA (xlfd), motif);
 #else
-         char *fontsetname = face->font_name;
+             char *fontsetname = (char *) SDATA (xlfd);
 #endif
-         sprintf (line, "%s.pane.menubar*font%s: %s",
-                  myname, suffix, fontsetname);
-         XrmPutLineResource (&rdb, line);
-         sprintf (line, "%s.%s*font%s: %s",
-                  myname, popup_path, suffix, fontsetname);
-         XrmPutLineResource (&rdb, line);
-         changed_p = 1;
-         if (fontsetname != face->font_name)
-           xfree (fontsetname);
+             sprintf (line, "%s.pane.menubar*font%s: %s",
+                      myname, suffix, fontsetname);
+             XrmPutLineResource (&rdb, line);
+             sprintf (line, "%s.%s*font%s: %s",
+                      myname, popup_path, suffix, fontsetname);
+             XrmPutLineResource (&rdb, line);
+             changed_p = 1;
+             if (fontsetname != (char *) SDATA (xlfd))
+               xfree (fontsetname);
+           }
        }
 
       if (changed_p && f->output_data.x->menubar_widget)
@@ -5145,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))
@@ -5198,35 +3834,7 @@ Value is nil if ATTR doesn't have a discrete set of valid values.  */)
 
   CHECK_SYMBOL (attr);
 
-  if (EQ (attr, QCweight)
-      || EQ (attr, QCslant)
-      || EQ (attr, QCwidth))
-    {
-      /* Extract permissible symbols from tables.  */
-      struct table_entry *table;
-      int i, dim;
-
-      if (EQ (attr, QCweight))
-       table = weight_table, dim = DIM (weight_table);
-      else if (EQ (attr, QCslant))
-       table = slant_table, dim = DIM (slant_table);
-      else
-       table = swidth_table, dim = DIM (swidth_table);
-
-      for (i = 0; i < dim; ++i)
-       {
-         Lisp_Object symbol = *table[i].symbol;
-         Lisp_Object tail = result;
-
-         while (!NILP (tail)
-                && !EQ (XCAR (tail), symbol))
-           tail = XCDR (tail);
-
-         if (NILP (tail))
-           result = Fcons (symbol, result);
-       }
-    }
-  else if (EQ (attr, QCunderline))
+  if (EQ (attr, QCunderline))
     result = Fcons (Qt, Fcons (Qnil, Qnil));
   else if (EQ (attr, QCoverline))
     result = Fcons (Qt, Fcons (Qnil, Qnil));
@@ -5248,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);
 
@@ -5263,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;
 }
@@ -5322,12 +3962,16 @@ return the font name used for CHARACTER.  */)
          CHECK_CHARACTER (character);
          face_id = FACE_FOR_CHAR (f, face, XINT (character), -1, Qnil);
          face = FACE_FROM_ID (f, face_id);
-         return (face->font && face->font_name
-                 ? build_string (face->font_name)
-                 : Qnil);
        }
+      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
-      return build_string (face->font_name);
     }
 }
 
@@ -5337,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.  */
@@ -5354,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;
 
@@ -5371,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;
 
@@ -5460,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;
@@ -5475,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])
@@ -5490,32 +4131,28 @@ lface_hash (v)
 
 /* Return non-zero if LFACE1 and LFACE2 specify the same font (without
    considering charsets/registries).  They do if they specify the same
-   family, point size, weight, width, slant, font, and fontset.  Both
+   family, point size, weight, width, slant, and font.  Both
    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_AVGWIDTH_INDEX], lface2[LFACE_AVGWIDTH_INDEX])
          && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
          && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX])
-         && (EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
-             || (STRINGP (lface1[LFACE_FONT_INDEX])
-                 && STRINGP (lface2[LFACE_FONT_INDEX])
-                 && ! xstricmp (SDATA (lface1[LFACE_FONT_INDEX]),
-                                SDATA (lface2[LFACE_FONT_INDEX]))))
+         && EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
          && (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]))))
          );
 }
 
@@ -5529,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;
 }
 
@@ -5544,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)
     {
@@ -5559,10 +4193,8 @@ free_realized_face (f, face)
          if (face->gc)
            {
              BLOCK_INPUT;
-#ifdef USE_FONT_BACKEND
-             if (enable_font_backend && face->font_info)
+             if (face->font)
                font_done_for_face (f, face);
-#endif /* USE_FONT_BACKEND */
              x_free_gc (f, face->gc);
              face->gc = 0;
              UNBLOCK_INPUT;
@@ -5583,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));
@@ -5600,25 +4230,6 @@ prepare_face_for_display (f, face)
 #ifdef HAVE_X_WINDOWS
       xgcv.graphics_exposures = False;
 #endif
-      /* The font of FACE may be null if we couldn't load it.  */
-      if (face->font)
-       {
-#ifdef HAVE_X_WINDOWS
-#ifdef USE_FONT_BACKEND
-         if (enable_font_backend)
-           xgcv.font = FRAME_X_DISPLAY_INFO (f)->font->fid;
-         else
-#endif
-         xgcv.font = face->font->fid;
-#endif
-#ifdef WINDOWSNT
-         xgcv.font = face->font;
-#endif
-#ifdef MAC_OS
-         xgcv.font = face->font;
-#endif
-         mask |= GCFont;
-       }
 
       BLOCK_INPUT;
 #ifdef HAVE_X_WINDOWS
@@ -5630,10 +4241,8 @@ prepare_face_for_display (f, face)
        }
 #endif
       face->gc = x_create_gc (f, mask, &xgcv);
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend && face->font)
+      if (face->font)
        font_prepare_for_face (f, face);
-#endif /* USE_FONT_BACKEND */
       UNBLOCK_INPUT;
     }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -5643,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:
@@ -5702,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;
@@ -5726,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))
     {
@@ -5739,10 +4345,8 @@ clear_face_gcs (c)
          if (face && face->gc)
            {
              BLOCK_INPUT;
-#ifdef USE_FONT_BACKEND
-             if (enable_font_backend && face->font_info)
+             if (face->font)
                font_done_for_face (c->f, face);
-#endif /* USE_FONT_BACKEND */
              x_free_gc (c->f, face->gc);
              face->gc = 0;
              UNBLOCK_INPUT;
@@ -5759,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)
     {
@@ -5780,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
@@ -5800,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;
@@ -5843,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))
     {
@@ -5860,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)
     {
@@ -5881,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;
 
@@ -5961,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;
 
@@ -5987,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;
@@ -6029,54 +4621,13 @@ lookup_face (f, attr)
 
 #ifdef HAVE_WINDOW_SYSTEM
 /* Look up a realized face that has the same attributes as BASE_FACE
-   except for the font in the face cache of frame F.  If FONT_ID is
-   not negative, it is an ID number of an already opened font that is
-   used by the face.  If FONT_ID is negative, the face has no font.
-   Value is the ID of the face found.  If no suitable face is found,
-   realize a new one.  */
-
-int
-lookup_non_ascii_face (f, font_id, base_face)
-     struct frame *f;
-     int font_id;
-     struct face *base_face;
-{
-  struct face_cache *cache = FRAME_FACE_CACHE (f);
-  unsigned hash;
-  int i;
-  struct face *face;
-
-  xassert (cache != NULL);
-  base_face = base_face->ascii_face;
-  hash = lface_hash (base_face->lface);
-  i = hash % FACE_CACHE_BUCKETS_SIZE;
-
-  for (face = cache->buckets[i]; face; face = face->next)
-    {
-      if (face->ascii_face == face)
-       continue;
-      if (face->ascii_face == base_face
-         && face->font_info_id == font_id)
-       break;
-    }
-
-  /* If not found, realize a new face.  */
-  if (face == NULL)
-    face = realize_non_ascii_face (f, font_id, base_face);
-
-#if GLYPH_DEBUG
-  xassert (face == FACE_FROM_ID (f, face->id));
-#endif /* GLYPH_DEBUG */
-
-  return face->id;
-}
+   except for the font in the face cache of frame F.  If FONT-OBJECT
+   is not nil, it is an already opened font.  If FONT-OBJECT is nil,
+   the face has no font.  Value is the ID of the face found.  If no
+   suitable face is found, realize a new one.  */
 
-#ifdef USE_FONT_BACKEND
 int
-face_for_font (f, font, base_face)
-     struct frame *f;
-     struct font *font;
-     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;
@@ -6093,21 +4644,16 @@ face_for_font (f, font, base_face)
       if (face->ascii_face == face)
        continue;
       if (face->ascii_face == base_face
-         && face->font == font->font.font
-         && face->font_info == (struct font_info *) font)
+         && face->font == (NILP (font_object) ? NULL
+                           : XFONT_OBJECT (font_object))
+         && lface_equal_p (face->lface, base_face->lface))
        return face->id;
     }
 
   /* If not found, realize a new face.  */
-  face = realize_non_ascii_face (f, -1, base_face);
-  face->font = font->font.font;
-  face->font_info = (struct font_info *) font;
-  face->font_info_id = 0;
-  face->font_name = font->font.full_name;
+  face = realize_non_ascii_face (f, font_object, base_face);
   return face->id;
 }
-#endif /* USE_FONT_BACKEND */
-
 #endif /* HAVE_WINDOW_SYSTEM */
 
 /* Return the face id of the realized face for named face SYMBOL on
@@ -6116,10 +4662,7 @@ face_for_font (f, font, 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];
@@ -6134,13 +4677,63 @@ 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);
-  merge_face_vectors (f, symbol_attrs, attrs, 0);
+  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 lookup_face (f, attrs);
+  return remapped_face_id;
 }
 
 
@@ -6148,9 +4741,7 @@ lookup_named_face (f, symbol, signal_p)
    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;
 
@@ -6171,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;
@@ -6192,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);
@@ -6232,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;
@@ -6246,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 */
 
@@ -6263,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];
@@ -6276,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);
 }
@@ -6322,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;
 
@@ -6360,17 +4942,18 @@ 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])
-      || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
-      || !UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX]))
+      || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]))
     {
       int face_id;
       struct face *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);
 
@@ -6380,9 +4963,26 @@ 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]))
+         {
+           Lisp_Object s1, s2;
+
+           if (i < FONT_FOUNDRY_INDEX || i > FONT_REGISTRY_INDEX
+               || face->font->driver->case_sensitive)
+             return 1;
+           s1 = SYMBOL_NAME (face->font->props[i]);
+           s2 = SYMBOL_NAME (def_face->font->props[i]);
+           if (! EQ (Fcompare_strings (s1, make_number (0), Qnil,
+                                       s2, make_number (0), Qnil, Qt), Qt))
+             return 1;
+         }
+      return 0;
     }
 
   /* Everything checks out, this face is supported.  */
@@ -6408,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;
@@ -6430,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])
@@ -6443,24 +5041,25 @@ tty_supports_face_attributes_p (f, attrs, def_face)
   /* Test for terminal `capabilities' (non-color character attributes).  */
 
   /* font weight (bold/dim) */
-  weight = face_numeric_weight (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 = face_numeric_weight (def_attrs[LFACE_WEIGHT_INDEX]);
+      int def_weight = FONT_WEIGHT_NAME_NUMERIC (def_attrs[LFACE_WEIGHT_INDEX]);
 
-      if (weight > XLFD_WEIGHT_MEDIUM)
+      if (weight > 100)
        {
-         if (def_weight > XLFD_WEIGHT_MEDIUM)
+         if (def_weight > 100)
            return 0;           /* same as default */
          test_caps = TTY_CAP_BOLD;
        }
-      else if (weight < XLFD_WEIGHT_MEDIUM)
+      else if (weight < 100)
        {
-         if (def_weight < XLFD_WEIGHT_MEDIUM)
+         if (def_weight < 100)
            return 0;           /* same as default */
          test_caps = TTY_CAP_DIM;
        }
-      else if (def_weight == XLFD_WEIGHT_MEDIUM)
+      else if (def_weight == 100)
        return 0;               /* same as default */
     }
 
@@ -6624,635 +5223,172 @@ face for italic.  */)
        }
     }
 
-  CHECK_LIVE_FRAME (frame);
-  f = XFRAME (frame);
-
-  for (i = 0; i < LFACE_VECTOR_SIZE; i++)
-    attrs[i] = Qunspecified;
-  merge_face_ref (f, attributes, attrs, 1, 0);
-
-  def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-  if (def_face == NULL)
-    {
-      if (! realize_basic_faces (f))
-       error ("Cannot realize default face");
-      def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-      if (def_face == NULL)
-       abort ();  /* realize_basic_faces must have set it up  */
-    }
-
-  /* Dispatch to the appropriate handler.  */
-  if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
-    supports = tty_supports_face_attributes_p (f, attrs, def_face);
-#ifdef HAVE_WINDOW_SYSTEM
-  else
-    supports = x_supports_face_attributes_p (f, attrs, def_face);
-#endif
-
-  return supports ? Qt : Qnil;
-}
-
-\f
-/***********************************************************************
-                           Font selection
- ***********************************************************************/
-
- 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.
-ORDER must be a list of length 4 containing the symbols `:width',
-`:height', `:weight', and `:slant'.  Face attributes appearing
-first in ORDER are matched first, e.g. if `:height' appears before
-`:weight' in ORDER, font selection first tries to find a font with
-a suitable height, and then tries to match the font weight.
-Value is ORDER.  */)
-     (order)
-     Lisp_Object order;
-{
-  Lisp_Object list;
-  int i;
-  int indices[DIM (font_sort_order)];
-
-  CHECK_LIST (order);
-  bzero (indices, sizeof indices);
-  i = 0;
-
-  for (list = order;
-       CONSP (list) && i < DIM (indices);
-       list = XCDR (list), ++i)
-    {
-      Lisp_Object attr = XCAR (list);
-      int xlfd;
-
-      if (EQ (attr, QCwidth))
-       xlfd = XLFD_SWIDTH;
-      else if (EQ (attr, QCheight))
-       xlfd = XLFD_POINT_SIZE;
-      else if (EQ (attr, QCweight))
-       xlfd = XLFD_WEIGHT;
-      else if (EQ (attr, QCslant))
-       xlfd = XLFD_SLANT;
-      else
-       break;
-
-      if (indices[i] != 0)
-       break;
-      indices[i] = xlfd;
-    }
-
-  if (!NILP (list) || i != DIM (indices))
-    signal_error ("Invalid font sort order", order);
-  for (i = 0; i < DIM (font_sort_order); ++i)
-    if (indices[i] == 0)
-      signal_error ("Invalid font sort order", order);
-
-  if (bcmp (indices, font_sort_order, sizeof indices) != 0)
-    {
-      bcopy (indices, font_sort_order, sizeof font_sort_order);
-      free_all_realized_faces (Qnil);
-    }
-
-#ifdef USE_FONT_BACKEND
-  if (enable_font_backend)
-    font_update_sort_order (font_sort_order);
-#endif /* USE_FONT_BACKEND */
-
-  return Qnil;
-}
-
-
-DEFUN ("internal-set-alternative-font-family-alist",
-       Finternal_set_alternative_font_family_alist,
-       Sinternal_set_alternative_font_family_alist, 1, 1, 0,
-       doc: /* Define alternative font families to try in face font selection.
-ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
-Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can
-be found.  Value is ALIST.  */)
-     (alist)
-     Lisp_Object alist;
-{
-  CHECK_LIST (alist);
-  Vface_alternative_font_family_alist = alist;
-  free_all_realized_faces (Qnil);
-  return alist;
-}
-
-
-DEFUN ("internal-set-alternative-font-registry-alist",
-       Finternal_set_alternative_font_registry_alist,
-       Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
-       doc: /* Define alternative font registries to try in face font selection.
-ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
-Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can
-be found.  Value is ALIST.  */)
-     (alist)
-     Lisp_Object alist;
-{
-  CHECK_LIST (alist);
-  Vface_alternative_font_registry_alist = alist;
-  free_all_realized_faces (Qnil);
-  return alist;
-}
-
-
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* Value is non-zero if FONT is the name of a scalable font.  The
-   X11R6 XLFD spec says that point size, pixel size, and average width
-   are zero for scalable fonts.  Intlfonts contain at least one
-   scalable font ("*-muleindian-1") for which this isn't true, so we
-   just test average width.  */
-
-static int
-font_scalable_p (font)
-     struct font_name *font;
-{
-  char *s = font->fields[XLFD_AVGWIDTH];
-  return (*s == '0' && *(s + 1) == '\0')
-#ifdef WINDOWSNT
-  /* Windows implementation of XLFD is slightly broken for backward
-     compatibility with previous broken versions, so test for
-     wildcards as well as 0. */
-  || *s == '*'
-#endif
-    ;
-}
-
-
-/* Ignore the difference of font point size less than this value.  */
-
-#define FONT_POINT_SIZE_QUANTUM 5
-
-/* Value is non-zero if FONT1 is a better match for font attributes
-   VALUES than FONT2.  VALUES is an array of face attribute values in
-   font sort order.  COMPARE_PT_P zero means don't compare point
-   sizes.  AVGWIDTH, if not zero, is a specified font average width
-   to compare with.  */
-
-static int
-better_font_p (values, font1, font2, compare_pt_p, avgwidth)
-     int *values;
-     struct font_name *font1, *font2;
-     int compare_pt_p, avgwidth;
-{
-  int i;
-
-  /* Any font is better than no font.  */
-  if (! font1)
-    return 0;
-  if (! font2)
-    return 1;
-
-  for (i = 0; i < DIM (font_sort_order); ++i)
-    {
-      int xlfd_idx = font_sort_order[i];
-
-      if (compare_pt_p || xlfd_idx != XLFD_POINT_SIZE)
-       {
-         int delta1, delta2;
-
-         if (xlfd_idx == XLFD_POINT_SIZE)
-           {
-             delta1 = eabs (values[i] - (font1->numeric[xlfd_idx]
-                                        / font1->rescale_ratio));
-             delta2 = eabs (values[i] - (font2->numeric[xlfd_idx]
-                                        / font2->rescale_ratio));
-             if (eabs (delta1 - delta2) < FONT_POINT_SIZE_QUANTUM)
-               continue;
-           }
-         else
-           {
-             delta1 = eabs (values[i] - font1->numeric[xlfd_idx]);
-             delta2 = eabs (values[i] - font2->numeric[xlfd_idx]);
-           }
-
-         if (delta1 > delta2)
-           return 0;
-         else if (delta1 < delta2)
-           return 1;
-         else
-           {
-             /* The difference may be equal because, e.g., the face
-                specifies `italic' but we have only `regular' and
-                `oblique'.  Prefer `oblique' in this case.  */
-             if ((xlfd_idx == XLFD_WEIGHT || xlfd_idx == XLFD_SLANT)
-                 && font1->numeric[xlfd_idx] > values[i]
-                 && font2->numeric[xlfd_idx] < values[i])
-               return 1;
-           }
-       }
-    }
-
-  if (avgwidth)
-    {
-      int delta1 = eabs (avgwidth - font1->numeric[XLFD_AVGWIDTH]);
-      int delta2 = eabs (avgwidth - font2->numeric[XLFD_AVGWIDTH]);
-      if (delta1 > delta2)
-       return 0;
-      else if (delta1 < delta2)
-       return 1;
-    }
-
-  if (! compare_pt_p)
-    {
-      /* We prefer a real scalable font; i.e. not what autoscaled.  */
-      int auto_scaled_1 = (font1->numeric[XLFD_POINT_SIZE] == 0
-                          && font1->numeric[XLFD_RESY] > 0);
-      int auto_scaled_2 = (font2->numeric[XLFD_POINT_SIZE] == 0
-                          && font2->numeric[XLFD_RESY] > 0);
-
-      if (auto_scaled_1 != auto_scaled_2)
-       return auto_scaled_2;
-    }
-
-  return font1->registry_priority < font2->registry_priority;
-}
-
-
-/* Value is non-zero if FONT is an exact match for face attributes in
-   SPECIFIED.  SPECIFIED is an array of face attribute values in font
-   sort order.  AVGWIDTH, if non-zero, is an average width to compare
-   with.  */
-
-static int
-exact_face_match_p (specified, font, avgwidth)
-     int *specified;
-     struct font_name *font;
-     int avgwidth;
-{
-  int i;
-
-  for (i = 0; i < DIM (font_sort_order); ++i)
-    if (specified[i] != font->numeric[font_sort_order[i]])
-      break;
-
-  return (i == DIM (font_sort_order)
-         && (avgwidth <= 0
-             || avgwidth == font->numeric[XLFD_AVGWIDTH]));
-}
-
-
-/* Value is the name of a scaled font, generated from scalable font
-   FONT on frame F.  SPECIFIED_PT is the point-size to scale FONT to.
-   Value is allocated from heap.  */
-
-static char *
-build_scalable_font_name (f, font, specified_pt)
-     struct frame *f;
-     struct font_name *font;
-     int specified_pt;
-{
-  char pixel_size[20];
-  int pixel_value;
-  double resy = FRAME_X_DISPLAY_INFO (f)->resy;
-  double pt;
-
-  if (font->numeric[XLFD_PIXEL_SIZE] != 0
-      || font->numeric[XLFD_POINT_SIZE] != 0)
-    /* This is a scalable font but is requested for a specific size.
-       We should not change that size.  */
-    return build_font_name (font);
-
-  /* If scalable font is for a specific resolution, compute
-     the point size we must specify from the resolution of
-     the display and the specified resolution of the font.  */
-  if (font->numeric[XLFD_RESY] != 0)
-    {
-      pt = resy / font->numeric[XLFD_RESY] * specified_pt + 0.5;
-      pixel_value = font->numeric[XLFD_RESY] / (PT_PER_INCH * 10.0) * pt + 0.5;
-    }
-  else
-    {
-      pt = specified_pt;
-      pixel_value = resy / (PT_PER_INCH * 10.0) * pt + 0.5;
-    }
-  /* We may need a font of the different size.  */
-  pixel_value *= font->rescale_ratio;
-
-  /* We should keep POINT_SIZE 0.  Otherwise, X server can't open a
-     font of the specified PIXEL_SIZE.  */
-#if 0
-  { /* Set point size of the font.  */
-    char point_size[20];
-    sprintf (point_size, "%d", (int) pt);
-    font->fields[XLFD_POINT_SIZE] = point_size;
-    font->numeric[XLFD_POINT_SIZE] = pt;
-  }
-#endif
-
-  /* Set pixel size.  */
-  sprintf (pixel_size, "%d", pixel_value);
-  font->fields[XLFD_PIXEL_SIZE] = pixel_size;
-  font->numeric[XLFD_PIXEL_SIZE] = pixel_value;
-
-  /* If font doesn't specify its resolution, use the
-     resolution of the display.  */
-  if (font->numeric[XLFD_RESY] == 0)
-    {
-      char buffer[20];
-      sprintf (buffer, "%d", (int) resy);
-      font->fields[XLFD_RESY] = buffer;
-      font->numeric[XLFD_RESY] = resy;
-    }
-
-  if (strcmp (font->fields[XLFD_RESX], "0") == 0)
-    {
-      char buffer[20];
-      int resx = FRAME_X_DISPLAY_INFO (f)->resx;
-      sprintf (buffer, "%d", resx);
-      font->fields[XLFD_RESX] = buffer;
-      font->numeric[XLFD_RESX] = resx;
-    }
-
-  return build_font_name (font);
-}
-
-
-/* Value is non-zero if we are allowed to use scalable font FONT.  We
-   can't run a Lisp function here since this function may be called
-   with input blocked.  */
-
-static int
-may_use_scalable_font_p (font)
-     const char *font;
-{
-  if (EQ (Vscalable_fonts_allowed, Qt))
-    return 1;
-  else if (CONSP (Vscalable_fonts_allowed))
-    {
-      Lisp_Object tail, regexp;
-
-      for (tail = Vscalable_fonts_allowed; CONSP (tail); tail = XCDR (tail))
-       {
-         regexp = XCAR (tail);
-         if (STRINGP (regexp)
-             && fast_c_string_match_ignore_case (regexp, font) >= 0)
-           return 1;
-       }
-    }
-
-  return 0;
-}
-
-
-
-/* Return the name of the best matching font for face attributes ATTRS
-   in the array of font_name structures FONTS which contains NFONTS
-   elements.  WIDTH_RATIO is a factor with which to multiply average
-   widths if ATTRS specifies such a width.
-
-   Value is a font name which is allocated from the heap.  FONTS is
-   freed by this function.
-
-   If NEEDS_OVERSTRIKE is non-zero, a boolean is returned in it to
-   indicate whether the resulting font should be drawn using overstrike
-   to simulate bold-face.  */
-
-static char *
-best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike)
-     struct frame *f;
-     Lisp_Object *attrs;
-     struct font_name *fonts;
-     int nfonts;
-     int width_ratio;
-     int *needs_overstrike;
-{
-  char *font_name;
-  struct font_name *best;
-  int i, pt = 0;
-  int specified[5];
-  int exact_p, avgwidth;
-
-  if (nfonts == 0)
-    return NULL;
-
-  /* Make specified font attributes available in `specified',
-     indexed by sort order.  */
-  for (i = 0; i < DIM (font_sort_order); ++i)
-    {
-      int xlfd_idx = font_sort_order[i];
-
-      if (xlfd_idx == XLFD_SWIDTH)
-       specified[i] = face_numeric_swidth (attrs[LFACE_SWIDTH_INDEX]);
-      else if (xlfd_idx == XLFD_POINT_SIZE)
-       specified[i] = pt = XFASTINT (attrs[LFACE_HEIGHT_INDEX]);
-      else if (xlfd_idx == XLFD_WEIGHT)
-       specified[i] = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
-      else if (xlfd_idx == XLFD_SLANT)
-       specified[i] = face_numeric_slant (attrs[LFACE_SLANT_INDEX]);
-      else
-       abort ();
-    }
-
-  avgwidth = (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
-             ? 0
-             : XFASTINT (attrs[LFACE_AVGWIDTH_INDEX]) * width_ratio);
-
-  exact_p = 0;
+  CHECK_LIVE_FRAME (frame);
+  f = XFRAME (frame);
 
-  if (needs_overstrike)
-    *needs_overstrike = 0;
+  for (i = 0; i < LFACE_VECTOR_SIZE; i++)
+    attrs[i] = Qunspecified;
+  merge_face_ref (f, attributes, attrs, 1, 0);
 
-  best = NULL;
+  def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+  if (def_face == NULL)
+    {
+      if (! realize_basic_faces (f))
+       error ("Cannot realize default face");
+      def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+      if (def_face == NULL)
+       abort ();  /* realize_basic_faces must have set it up  */
+    }
 
-  /* Find the best match among the non-scalable fonts.  */
-  for (i = 0; i < nfonts; ++i)
-    if (!font_scalable_p (fonts + i)
-       && better_font_p (specified, fonts + i, best, 1, avgwidth))
-      {
-       best = fonts + i;
+  /* Dispatch to the appropriate handler.  */
+  if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+    supports = tty_supports_face_attributes_p (f, attrs, def_face);
+#ifdef HAVE_WINDOW_SYSTEM
+  else
+    supports = x_supports_face_attributes_p (f, attrs, def_face);
+#endif
 
-       exact_p = exact_face_match_p (specified, best, avgwidth);
-       if (exact_p)
-         break;
-      }
+  return supports ? Qt : Qnil;
+}
 
-  /* Unless we found an exact match among non-scalable fonts, see if
-     we can find a better match among scalable fonts.  */
-  if (!exact_p)
-    {
-      /* A scalable font is better if
+\f
+/***********************************************************************
+                           Font selection
+ ***********************************************************************/
 
-        1. its weight, slant, swidth attributes are better, or.
+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.
+ORDER must be a list of length 4 containing the symbols `:width',
+`:height', `:weight', and `:slant'.  Face attributes appearing
+first in ORDER are matched first, e.g. if `:height' appears before
+`:weight' in ORDER, font selection first tries to find a font with
+a suitable height, and then tries to match the font weight.
+Value is ORDER.  */)
+     (order)
+     Lisp_Object order;
+{
+  Lisp_Object list;
+  int i;
+  int indices[DIM (font_sort_order)];
 
-        2. the best non-scalable font doesn't have the required
-        point size, and the scalable fonts weight, slant, swidth
-        isn't worse.  */
+  CHECK_LIST (order);
+  memset (indices, 0, sizeof indices);
+  i = 0;
 
-      int non_scalable_has_exact_height_p;
+  for (list = order;
+       CONSP (list) && i < DIM (indices);
+       list = XCDR (list), ++i)
+    {
+      Lisp_Object attr = XCAR (list);
+      int xlfd;
 
-      if (best && best->numeric[XLFD_POINT_SIZE] == pt)
-       non_scalable_has_exact_height_p = 1;
+      if (EQ (attr, QCwidth))
+       xlfd = XLFD_SWIDTH;
+      else if (EQ (attr, QCheight))
+       xlfd = XLFD_POINT_SIZE;
+      else if (EQ (attr, QCweight))
+       xlfd = XLFD_WEIGHT;
+      else if (EQ (attr, QCslant))
+       xlfd = XLFD_SLANT;
       else
-       non_scalable_has_exact_height_p = 0;
+       break;
 
-      for (i = 0; i < nfonts; ++i)
-       if (font_scalable_p (fonts + i))
-         {
-           if (better_font_p (specified, fonts + i, best, 0, 0)
-               || (!non_scalable_has_exact_height_p
-                   && !better_font_p (specified, best, fonts + i, 0, 0)))
-             {
-               non_scalable_has_exact_height_p = 1;
-               best = fonts + i;
-             }
-         }
+      if (indices[i] != 0)
+       break;
+      indices[i] = xlfd;
     }
 
-  /* We should have found SOME font.  */
-  if (best == NULL)
-    abort ();
+  if (!NILP (list) || i != DIM (indices))
+    signal_error ("Invalid font sort order", order);
+  for (i = 0; i < DIM (font_sort_order); ++i)
+    if (indices[i] == 0)
+      signal_error ("Invalid font sort order", order);
 
-  if (! exact_p && needs_overstrike)
+  if (memcmp (indices, font_sort_order, sizeof indices) != 0)
     {
-      enum xlfd_weight want_weight = specified[XLFD_WEIGHT];
-      enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT];
-
-      if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight)
-       {
-         /* We want a bold font, but didn't get one; try to use
-            overstriking instead to simulate bold-face.  However,
-            don't overstrike an already-bold font unless the
-            desired weight grossly exceeds the available weight.  */
-         if (got_weight > XLFD_WEIGHT_MEDIUM)
-           *needs_overstrike = (want_weight - got_weight) > 2;
-         else
-           *needs_overstrike = 1;
-       }
+      memcpy (font_sort_order, indices, sizeof font_sort_order);
+      free_all_realized_faces (Qnil);
     }
 
-  if (font_scalable_p (best))
-    font_name = build_scalable_font_name (f, best, pt);
-  else
-    font_name = build_font_name (best);
-
-  /* Free font_name structures.  */
-  free_font_names (fonts, nfonts);
+  font_update_sort_order (font_sort_order);
 
-  return font_name;
+  return Qnil;
 }
 
 
-/* Get a list of matching fonts on frame F, considering FAMILY
-   and alternative font families from Vface_alternative_font_registry_alist.
-
-   FAMILY is the font family whose alternatives are considered.
-
-   REGISTRY, if a string, specifies a font registry and encoding to
-   match.  A value of nil means include fonts of any registry and
-   encoding.
-
-   Return in *FONTS a pointer to a vector of font_name structures for
-   the fonts matched.  Value is the number of fonts found.  */
-
-static int
-try_alternative_families (f, family, registry, fonts)
-     struct frame *f;
-     Lisp_Object family, registry;
-     struct font_name **fonts;
+DEFUN ("internal-set-alternative-font-family-alist",
+       Finternal_set_alternative_font_family_alist,
+       Sinternal_set_alternative_font_family_alist, 1, 1, 0,
+       doc: /* Define alternative font families to try in face font selection.
+ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
+Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can
+be found.  Value is ALIST.  */)
+     (alist)
+     Lisp_Object alist;
 {
-  Lisp_Object alter;
-  int nfonts = 0;
+  Lisp_Object entry, tail, tail2;
 
-  nfonts = font_list (f, Qnil, family, registry, fonts);
-  if (nfonts == 0)
+  CHECK_LIST (alist);
+  alist = Fcopy_sequence (alist);
+  for (tail = alist; CONSP (tail); tail = XCDR (tail))
     {
-      /* Try alternative font families.  */
-      alter = Fassoc (family, Vface_alternative_font_family_alist);
-      if (CONSP (alter))
-       {
-         for (alter = XCDR (alter);
-              CONSP (alter) && nfonts == 0;
-              alter = XCDR (alter))
-           {
-             if (STRINGP (XCAR (alter)))
-               nfonts = font_list (f, Qnil, XCAR (alter), registry, fonts);
-           }
-       }
-
-      /* Try all scalable fonts before giving up.  */
-      if (nfonts == 0 && ! EQ (Vscalable_fonts_allowed, Qt))
-       {
-         int count = SPECPDL_INDEX ();
-         specbind (Qscalable_fonts_allowed, Qt);
-         nfonts = try_alternative_families (f, family, registry, fonts);
-         unbind_to (count, Qnil);
-       }
+      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));
     }
-  return nfonts;
-}
-
-
-/* Get a list of matching fonts on frame F.
 
-   PATTERN, if a string, specifies a font name pattern to match while
-   ignoring FAMILY and REGISTRY.
-
-   FAMILY, if a list, specifies a list of font families to try.
-
-   REGISTRY, if a list, specifies a list of font registries and
-   encodinging to try.
+  Vface_alternative_font_family_alist = alist;
+  free_all_realized_faces (Qnil);
+  return alist;
+}
 
-   Return in *FONTS a pointer to a vector of font_name structures for
-   the fonts matched.  Value is the number of fonts found.  */
 
-static int
-try_font_list (f, pattern, family, registry, fonts)
-     struct frame *f;
-     Lisp_Object pattern, family, registry;
-     struct font_name **fonts;
+DEFUN ("internal-set-alternative-font-registry-alist",
+       Finternal_set_alternative_font_registry_alist,
+       Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
+       doc: /* Define alternative font registries to try in face font selection.
+ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
+Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can
+be found.  Value is ALIST.  */)
+     (alist)
+     Lisp_Object alist;
 {
-  int nfonts = 0;
+  Lisp_Object entry, tail, tail2;
 
-  if (STRINGP (pattern))
+  CHECK_LIST (alist);
+  alist = Fcopy_sequence (alist);
+  for (tail = alist; CONSP (tail); tail = XCDR (tail))
     {
-      nfonts = font_list (f, pattern, Qnil, Qnil, fonts);
-      if (nfonts == 0 && ! EQ (Vscalable_fonts_allowed, Qt))
-       {
-         int count = SPECPDL_INDEX ();
-         specbind (Qscalable_fonts_allowed, Qt);
-         nfonts = font_list (f, pattern, Qnil, Qnil, fonts);
-         unbind_to (count, Qnil);
-       }
+      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)));
     }
-  else
-    {
-      Lisp_Object tail;
-
-      if (NILP (family))
-       nfonts = font_list (f, Qnil, Qnil, registry, fonts);
-      else
-       for (tail = family; ! nfonts && CONSP (tail); tail = XCDR (tail))
-         nfonts = try_alternative_families (f, XCAR (tail), registry, fonts);
+  Vface_alternative_font_registry_alist = alist;
+  free_all_realized_faces (Qnil);
+  return alist;
+}
 
-      /* Try font family of the default face or "fixed".  */
-      if (nfonts == 0 && !NILP (family))
-       {
-         struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-         if (default_face)
-           family = default_face->lface[LFACE_FAMILY_INDEX];
-         else
-           family = build_string ("fixed");
-         nfonts = try_alternative_families (f, family, registry, fonts);
-       }
 
-      /* Try any family with the given registry.  */
-      if (nfonts == 0 && !NILP (family))
-       nfonts = try_alternative_families (f, Qnil, registry, fonts);
-    }
+#ifdef HAVE_WINDOW_SYSTEM
 
-  return nfonts;
-}
+/* Ignore the difference of font point size less than this value.  */
 
+#define FONT_POINT_SIZE_QUANTUM 5
 
 /* Return the fontset id of the base fontset name or alias name given
    by the fontset attribute of ATTRS.  Value is -1 if the fontset
    attribute of ATTRS doesn't name a fontset.  */
 
 static int
-face_fontset (attrs)
-     Lisp_Object *attrs;
+face_fontset (Lisp_Object *attrs)
 {
   Lisp_Object name;
 
@@ -7262,107 +5398,6 @@ face_fontset (attrs)
   return fs_query_fontset (name, 0);
 }
 
-
-/* Choose a name of font to use on frame F to display characters with
-   Lisp face attributes specified by ATTRS.  The font name is
-   determined by the font-related attributes in ATTRS and FONT-SPEC
-   (if specified).
-
-   When we are choosing a font for ASCII characters, FONT-SPEC is
-   always nil.  Otherwise FONT-SPEC is an object created by
-   `font-spec' or a string specifying a font name pattern.
-
-   If NEEDS_OVERSTRIKE is not NULL, a boolean is returned in it to
-   indicate whether the resulting font should be drawn using
-   overstrike to simulate bold-face.
-
-   Value is the font name which is allocated from the heap and must be
-   freed by the caller.  */
-
-char *
-choose_face_font (f, attrs, font_spec, needs_overstrike)
-     struct frame *f;
-     Lisp_Object *attrs;
-     Lisp_Object font_spec;
-     int *needs_overstrike;
-{
-  Lisp_Object pattern, family, adstyle, registry;
-  char *font_name = NULL;
-  struct font_name *fonts;
-  int nfonts;
-
-  if (needs_overstrike)
-    *needs_overstrike = 0;
-
-  /* If we are choosing an ASCII font and a font name is explicitly
-     specified in ATTRS, return it.  */
-  if (NILP (font_spec) && STRINGP (attrs[LFACE_FONT_INDEX]))
-    return xstrdup (SDATA (attrs[LFACE_FONT_INDEX]));
-
-  if (NILP (attrs[LFACE_FAMILY_INDEX]))
-    family = Qnil;
-  else
-    family = Fcons (attrs[LFACE_FAMILY_INDEX], Qnil);
-
-  /* Decide FAMILY, ADSTYLE, and REGISTRY from FONT_SPEC.  But,
-     ADSTYLE is not used in the font selector for the moment.  */
-  if (VECTORP (font_spec))
-    {
-      pattern = Qnil;
-      if (! NILP (AREF (font_spec, FONT_FAMILY_INDEX)))
-       family = Fcons (SYMBOL_NAME (AREF (font_spec, FONT_FAMILY_INDEX)),
-                       family);
-      adstyle = AREF (font_spec, FONT_ADSTYLE_INDEX);
-      registry = Fcons (SYMBOL_NAME (AREF (font_spec, FONT_REGISTRY_INDEX)),
-                       Qnil);
-    }
-  else if (STRINGP (font_spec))
-    {
-      pattern = font_spec;
-      family = Qnil;
-      adstyle = Qnil;
-      registry = Qnil;
-    }
-  else
-    {
-      /* We are choosing an ASCII font.  By default, use the registry
-        name "iso8859-1".  But, if the registry name of the ASCII
-        font specified in the fontset of ATTRS is not "iso8859-1"
-        (e.g "iso10646-1"), use also that name with higher
-        priority.  */
-      int fontset = face_fontset (attrs);
-      Lisp_Object ascii;
-      int len;
-      struct font_name font;
-
-      pattern = Qnil;
-      adstyle = Qnil;
-      registry = Fcons (build_string ("iso8859-1"), Qnil);
-
-      ascii = fontset_ascii (fontset);
-      len = SBYTES (ascii);
-      if (len < 9
-         || strcmp (SDATA (ascii) + len - 9, "iso8859-1"))
-       {
-         font.name = LSTRDUPA (ascii);
-         /* Check if the name is in XLFD.  */
-         if (split_font_name (f, &font, 0))
-           {
-             font.fields[XLFD_ENCODING][-1] = '-';
-             registry = Fcons (build_string (font.fields[XLFD_REGISTRY]),
-                               registry);
-           }
-       }
-    }
-
-  /* Get a list of fonts matching that pattern and choose the
-     best match for the specified face attributes from it.  */
-  nfonts = try_font_list (f, pattern, family, registry, &fonts);
-  font_name = best_matching_font (f, attrs, fonts, nfonts, NILP (font_spec),
-                                 needs_overstrike);
-  return font_name;
-}
-
 #endif /* HAVE_WINDOW_SYSTEM */
 
 
@@ -7376,8 +5411,7 @@ choose_face_font (f, attrs, font_spec, needs_overstrike)
    face.  */
 
 static int
-realize_basic_faces (f)
-     struct frame *f;
+realize_basic_faces (struct frame *f)
 {
   int success_p = 0;
   int count = SPECPDL_INDEX ();
@@ -7425,13 +5459,11 @@ 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;
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
-  Lisp_Object frame_font;
   struct face *face;
 
   /* If the `default' face is not yet known, create it.  */
@@ -7443,31 +5475,14 @@ realize_default_face (f)
        lface = Finternal_make_lisp_face (Qdefault, frame);
   }
 
-
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
     {
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend)
-       {
-         frame_font = font_find_object (FRAME_FONT_OBJECT (f));
-         xassert (FONT_OBJECT_P (frame_font));
-         set_lface_from_font_and_fontset (f, lface, frame_font,
-                                          FRAME_FONTSET (f),
-                                          f->default_face_done_p);
-       }
-      else
-       {
-#endif /* USE_FONT_BACKEND */
-      /* Set frame_font to the value of the `font' frame parameter.  */
-      frame_font = Fassq (Qfont, f->param_alist);
-      xassert (CONSP (frame_font) && STRINGP (XCDR (frame_font)));
-      frame_font = XCDR (frame_font);
-      set_lface_from_font_name (f, lface, frame_font,
-                                f->default_face_done_p, 1);
-#ifdef USE_FONT_BACKEND
-       }
-#endif /* USE_FONT_BACKEND */
+      Lisp_Object font_object;
+
+      XSETFONT (font_object, FRAME_FONT (f));
+      set_lface_from_font (f, lface, font_object, f->default_face_done_p);
+      LFACE_FONTSET (lface) = fontset_name (FRAME_FONTSET (f));
       f->default_face_done_p = 1;
     }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -7475,13 +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;
-      LFACE_AVGWIDTH (lface) = Qunspecified;
+      if (UNSPECIFIEDP (LFACE_FONTSET (lface)))
+       LFACE_FONTSET (lface) = Qnil;
     }
 
   if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
@@ -7536,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
@@ -7547,12 +5564,12 @@ 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
         font.  */
-      x_set_font (f, build_string (face->font_name), Qnil);
+      x_set_font (f, LFACE_FONT (lface), Qnil);
     }
 #endif /* HAVE_X_WINDOWS */
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -7565,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);
@@ -7577,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));
 
@@ -7590,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.  */
@@ -7604,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;
 
@@ -7642,45 +5653,29 @@ realize_face (cache, attrs, former_face_id)
 
 
 #ifdef HAVE_WINDOW_SYSTEM
-/* Realize the fully-specified face that has the same attributes as
-   BASE_FACE except for the font on frame F.  If FONT_ID is not
-   negative, it is an ID number of an already opened font that should
-   be used by the face.  If FONT_ID is negative, the face has no font,
-   i.e., characters are displayed by empty boxes.  */
+/* Realize the fully-specified face that uses FONT-OBJECT and has the
+   same attributes as BASE_FACE except for the font on frame F.
+   FONT-OBJECT may be nil, in which case, realized a face of
+   no-font.  */
 
 static struct face *
-realize_non_ascii_face (f, font_id, base_face)
-     struct frame *f;
-     int font_id;
-     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;
-  struct font_info *font_info;
 
   face = (struct face *) xmalloc (sizeof *face);
   *face = *base_face;
   face->gc = 0;
-#ifdef USE_FONT_BACKEND
   face->extra = NULL;
-#endif /* USE_FONT_BACKEND */
+  face->overstrike
+    = (! NILP (font_object)
+       && FONT_WEIGHT_NAME_NUMERIC (face->lface[LFACE_WEIGHT_INDEX]) > 100
+       && FONT_WEIGHT_NUMERIC (font_object) <= 100);
 
   /* Don't try to free the colors copied bitwise from BASE_FACE.  */
   face->colors_copied_bitwise_p = 1;
-
-  face->font_info_id = font_id;
-  if (font_id >= 0)
-    {
-      font_info = FONT_INFO_FROM_ID (f, font_id);
-      face->font = font_info->font;
-      face->font_name = font_info->full_name;
-    }
-  else
-    {
-      face->font = NULL;
-      face->font_name = NULL;
-    }
-
+  face->font = NILP (font_object) ? NULL : XFONT_OBJECT (font_object);
   face->gc = 0;
 
   cache_face (cache, face, face->hash);
@@ -7698,9 +5693,7 @@ realize_non_ascii_face (f, font_id, 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
@@ -7723,12 +5716,6 @@ realize_x_face (cache, attrs)
       && lface_same_font_attributes_p (default_face->lface, attrs))
     {
       face->font = default_face->font;
-      face->font_info_id = default_face->font_info_id;
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend)
-       face->font_info = default_face->font_info;
-#endif /* USE_FONT_BACKEND */
-      face->font_name = default_face->font_name;
       face->fontset
        = make_fontset_for_ascii_face (f, default_face->fontset, face);
     }
@@ -7747,21 +5734,32 @@ 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 ();
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend)
-       font_load_for_face (f, face);
-      else
-#endif /* USE_FONT_BACKEND */
-       load_face_font (f, face);
-      if (face->font)
-       face->fontset = make_fontset_for_ascii_face (f, fontset, face);
+       {
+         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]);
+      if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
+       {
+         face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]);
+         face->fontset = make_fontset_for_ascii_face (f, fontset, face);
+       }
       else
-       face->fontset = -1;
+       {
+         face->font = NULL;
+         face->fontset = -1;
+       }
     }
 
+  if (face->font
+      && FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]) > 100
+      && FONT_WEIGHT_NUMERIC (attrs[LFACE_FONT_INDEX]) <= 100)
+    face->overstrike = 1;
+
   /* Load colors, and set remaining attributes.  */
 
   load_face_colors (f, face, attrs);
@@ -7902,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;
@@ -7983,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;
@@ -7997,17 +5989,18 @@ realize_tty_face (cache, attrs)
 
   /* Allocate a new realized face.  */
   face = make_realized_face (attrs);
+#if 0
   face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
+#endif
 
   /* Map face attributes to TTY appearances.  We map slant to
      dimmed text because we want italic text to appear differently
      and because dimmed text is probably used infrequently.  */
-  weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
-  slant = face_numeric_slant (attrs[LFACE_SLANT_INDEX]);
-
-  if (weight > XLFD_WEIGHT_MEDIUM)
+  weight = FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]);
+  slant = FONT_SLANT_NAME_NUMERIC (attrs[LFACE_SLANT_INDEX]);
+  if (weight > 100)
     face->tty_bold_p = 1;
-  if (weight < XLFD_WEIGHT_MEDIUM || slant != XLFD_SLANT_ROMAN)
+  if (weight < 100 || slant != 100)
     face->tty_dim_p = 1;
   if (!NILP (attrs[LFACE_UNDERLINE_INDEX]))
     face->tty_underline_p = 1;
@@ -8065,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;
 
@@ -8084,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);
     }
@@ -8105,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];
@@ -8158,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))
@@ -8261,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))
@@ -8362,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))
@@ -8396,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;
@@ -8413,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))
     {
@@ -8444,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
  ***********************************************************************/
@@ -8466,13 +6513,13 @@ dump_realized_face (face)
   fprintf (stderr, "background: 0x%lx (%s)\n",
           face->background,
           SDATA (face->lface[LFACE_BACKGROUND_INDEX]));
-  fprintf (stderr, "font_name: %s (%s)\n",
-          face->font_name,
-          SDATA (face->lface[LFACE_FAMILY_INDEX]));
+  if (face->font)
+    fprintf (stderr, "font_name: %s (%s)\n",
+            SDATA (face->font->props[FONT_NAME_INDEX]),
+            SDATA (face->lface[LFACE_FAMILY_INDEX]));
 #ifdef HAVE_X_WINDOWS
   fprintf (stderr, "font = %p\n", face->font);
 #endif
-  fprintf (stderr, "font_info_id = %d\n", face->font_info_id);
   fprintf (stderr, "fontset: %d\n", face->fontset);
   fprintf (stderr, "underline: %d (%s)\n",
           face->underline_p,
@@ -8534,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);
@@ -8699,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);
@@ -8741,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.  */);
@@ -8763,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.  */);
@@ -8777,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