(menu_face_changed_default): New variable.
[bpt/emacs.git] / src / xfaces.c
index 44f47b8..e39dfe2 100644 (file)
@@ -1,5 +1,6 @@
 /* xfaces.c -- "Face" primitives.
-   Copyright (C) 1993, 1994, 1998, 1999 Free Software Foundation.
+   Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001
+   Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -27,18 +28,18 @@ Boston, MA 02111-1307, USA.  */
    display attributes:
 
    1. Font family name.
-   
+
    2. Relative proportionate width, aka character set width or set
    width (swidth), e.g. `semi-compressed'.
-   
+
    3. Font height in 1/10pt.
-   
+
    4. Font weight, e.g. `bold'.
-   
+
    5. Font slant, e.g. `italic'.
-   
+
    6. Foreground color.
-   
+
    7. Background color.
 
    8. Whether or not characters should be underlined, and in what color.
@@ -56,7 +57,7 @@ Boston, MA 02111-1307, USA.  */
    type, and, for simple boxes, in what color.
 
    14. Font or fontset pattern, or nil.  This is a special attribute.
-   When this attribyte is specified, the face uses a font opened by
+   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.
    On the other hand, if one of the other font-related attributes are
@@ -65,6 +66,12 @@ Boston, MA 02111-1307, USA.  */
    font determined by the other attributes (those may be inherited
    from the `default' face).
 
+   15. A face name or list of face names from which to inherit attributes.
+
+   16. A specified average font width, which is invisible from Lisp,
+   and is used to ensure that a font specified on the command line,
+   for example, can be matched exactly.
+
    Faces are frame-local by nature because Emacs allows to define the
    same named face (face names are symbols) differently for different
    frames.  Each frame has an alist of face definitions for all named
@@ -75,7 +82,7 @@ Boston, MA 02111-1307, USA.  */
    There is also a global face alist `Vface_new_frame_defaults'.  Face
    definitions from this list are used to initialize faces of newly
    created frames.
-   
+
    A face doesn't have to specify all attributes.  Those not specified
    have a value of `unspecified'.  Faces specifying all attributes but
    the 14th are called `fully-specified'.
@@ -92,7 +99,7 @@ Boston, MA 02111-1307, USA.  */
 
 
    Face realization.
-   
+
    After all face attributes for a character have been determined by
    merging faces of that character, that face is `realized'.  The
    realization process maps face attributes to what is physically
@@ -116,7 +123,7 @@ Boston, MA 02111-1307, USA.  */
    is realized, it inherits (thus shares) a fontset of an ASCII face
    that has the same attributes other than font-related ones.
 
-   Thus, all realzied face have a realized fontset.
+   Thus, all realized face have a realized fontset.
 
 
    Unibyte text.
@@ -154,12 +161,19 @@ Boston, MA 02111-1307, USA.  */
    width---tries to find a best match for the specified font height,
    etc.
 
-   2. Setting face-alternative-font-family-alist allows the user to
+   2. Setting face-font-family-alternatives allows the user to
    specify alternative font families to try if a family specified by a
    face doesn't exist.
 
+   3. Setting face-font-registry-alternatives allows the user to
+   specify all alternative font registries to try for a face
+   specifying a registry.
+
+   4. Setting face-ignored-fonts allows the user to ignore specific
+   fonts.
+
 
-   Character compositition.   
+   Character composition.
 
    Usually, the realization process is already finished when Emacs
    actually reflects the desired glyph matrix on the screen.  However,
@@ -169,7 +183,7 @@ Boston, MA 02111-1307, USA.  */
    screen, i.e.  the realization process is delayed but in principle
    the same.
 
-   
+
    Initialization of basic faces.
 
    The faces `default', `modeline' are considered `basic faces'.
@@ -177,30 +191,25 @@ Boston, MA 02111-1307, USA.  */
    basic faces are realized for CHARSET_ASCII.  Frame parameters are
    used to fill in unspecified attributes of the default face.  */
 
-/* Define SCALABLE_FONTS to a non-zero value to enable scalable
-   font use. Define it to zero to disable scalable font use.
-
-   Use of too many or too large scalable fonts can crash XFree86
-   servers.  That's why I've put the code dealing with scalable fonts
-   in #if's.  */
-
-#define SCALABLE_FONTS 1
-
 #include <config.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "lisp.h"
 #include "charset.h"
+#include "keyboard.h"
 #include "frame.h"
 
+#ifdef HAVE_WINDOW_SYSTEM
+#include "fontset.h"
+#endif /* HAVE_WINDOW_SYSTEM */
+
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
-#include "fontset.h"
 #ifdef USE_MOTIF
 #include <Xm/Xm.h>
 #include <Xm/XmStrDefs.h>
 #endif /* USE_MOTIF */
-#endif
+#endif /* HAVE_X_WINDOWS */
 
 #ifdef MSDOS
 #include "dosfns.h"
@@ -211,6 +220,7 @@ Boston, MA 02111-1307, USA.  */
 #include "fontset.h"
 /* Redefine X specifics to W32 equivalents to avoid cluttering the
    code with #ifdef blocks. */
+#undef FRAME_X_DISPLAY_INFO
 #define FRAME_X_DISPLAY_INFO FRAME_W32_DISPLAY_INFO
 #define x_display_info w32_display_info
 #define FRAME_X_FONT_TABLE FRAME_W32_FONT_TABLE
@@ -219,7 +229,35 @@ Boston, MA 02111-1307, USA.  */
 #define GCGraphicsExposures 0
 /* For historic reasons, FONT_WIDTH refers to average width on W32,
    not maximum as on X. Redefine here. */
+#undef FONT_WIDTH
 #define FONT_WIDTH FONT_MAX_WIDTH
+#endif /* WINDOWSNT */
+
+#ifdef macintosh
+#include "macterm.h"
+#define x_display_info mac_display_info
+#define check_x check_mac
+
+extern XGCValues *XCreateGC (void *, WindowPtr, unsigned long, XGCValues *);
+
+static INLINE GC
+x_create_gc (f, mask, xgcv)
+     struct frame *f;
+     unsigned long mask;
+     XGCValues *xgcv;
+{
+  GC gc;
+  gc = XCreateGC (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), mask, xgcv);
+  return gc;
+}
+
+static INLINE void
+x_free_gc (f, gc)
+     struct frame *f;
+     GC gc;
+{
+  XFreeGC (FRAME_MAC_DISPLAY (f), gc);
+}
 #endif
 
 #include "buffer.h"
@@ -249,7 +287,6 @@ Boston, MA 02111-1307, USA.  */
 
 #include <stdio.h>
 #include <ctype.h>
-#include "keyboard.h"
 
 #ifndef max
 #define max(A, B)      ((A) > (B) ? (A) : (B))
@@ -257,6 +294,10 @@ Boston, MA 02111-1307, USA.  */
 #define abs(X)         ((X) < 0 ? -(X) : (X))
 #endif
 
+/* Number of pt per inch (from the TeXbook).  */
+
+#define PT_PER_INCH 72.27
+
 /* Non-zero if face attribute ATTR is unspecified.  */
 
 #define UNSPECIFIEDP(ATTR) EQ ((ATTR), Qunspecified)
@@ -265,7 +306,7 @@ Boston, MA 02111-1307, USA.  */
 
 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
 
-/* Make a copy of string S on the stack using alloca.  Value is a pointer 
+/* Make a copy of string S on the stack using alloca.  Value is a pointer
    to the copy.  */
 
 #define STRDUPA(S) strcpy ((char *) alloca (strlen ((S)) + 1), (S))
@@ -275,20 +316,25 @@ Boston, MA 02111-1307, USA.  */
 
 #define LSTRDUPA(S) STRDUPA (XSTRING ((S))->data)
 
-/* Size of hash table of realized faces in face caches (should be a 
+/* Size of hash table of realized faces in face caches (should be a
    prime number).  */
 
 #define FACE_CACHE_BUCKETS_SIZE 1001
 
 /* A definition of XColor for non-X frames.  */
+
 #ifndef HAVE_X_WINDOWS
-typedef struct {
+
+typedef struct
+{
   unsigned long pixel;
   unsigned short red, green, blue;
   char flags;
   char pad;
-} XColor;
-#endif
+}
+XColor;
+
+#endif /* not HAVE_X_WINDOWS */
 
 /* Keyword symbols used for face attribute names.  */
 
@@ -296,7 +342,7 @@ Lisp_Object QCfamily, QCheight, QCweight, QCslant, QCunderline;
 Lisp_Object QCinverse_video, QCforeground, QCbackground, QCstipple;
 Lisp_Object QCwidth, QCfont, QCbold, QCitalic;
 Lisp_Object QCreverse_video;
-Lisp_Object QCoverline, QCstrike_through, QCbox;
+Lisp_Object QCoverline, QCstrike_through, QCbox, QCinherit;
 
 /* Symbols used for attribute values.  */
 
@@ -347,15 +393,23 @@ Lisp_Object Vface_default_stipple;
 
 Lisp_Object Vface_alternative_font_family_alist;
 
+/* Alist of alternative font registries.  Each element is of the form
+   (REGISTRY REGISTRY1 REGISTRY2...).  If fonts of REGISTRY can't be
+   loaded, try REGISTRY1, then REGISTRY2, ...  */
+
+Lisp_Object Vface_alternative_font_registry_alist;
+
 /* Allowed scalable fonts.  A value of nil means don't allow any
    scalable fonts.  A value of t means allow the use of any scalable
    font.  Otherwise, value must be a list of regular expressions.  A
    font may be scaled if its name matches a regular expression in the
    list.  */
 
-#if SCALABLE_FONTS
-Lisp_Object Vscalable_fonts_allowed;
-#endif
+Lisp_Object Vscalable_fonts_allowed, Qscalable_fonts_allowed;
+
+/* List of regular expressions that matches names of fonts to ignore. */
+
+Lisp_Object Vface_ignored_fonts;
 
 /* Maximum number of fonts to consider in font_list.  If not an
    integer > 0, DEFAULT_FONT_LIST_LIMIT is used instead.  */
@@ -394,9 +448,18 @@ static int next_lface_id;
 static Lisp_Object *lface_id_to_name;
 static int lface_id_to_name_size;
 
-/* tty color-related functions (defined on lisp/term/tty-colors.el).  */
+/* TTY color-related functions (defined in tty-colors.el).  */
+
 Lisp_Object Qtty_color_desc, Qtty_color_by_index;
 
+/* The name of the function used to compute colors on TTYs.  */
+
+Lisp_Object Qtty_color_alist;
+
+/* An alist of defined terminal colors and their RGB values.  */
+
+Lisp_Object Vtty_defined_color_alist;
+
 /* Counter for calls to clear_face_cache.  If this counter reaches
    CLEAR_FONT_TABLE_COUNT, and a frame has more than
    CLEAR_FONT_TABLE_NFONTS load, unused fonts are freed.  */
@@ -417,6 +480,11 @@ int face_change_count;
 
 int tty_suppress_bold_inverse_default_colors_p;
 
+/* A list of the form `((x . y))' used to avoid consing in
+   Finternal_set_lisp_face_attribute.  */
+
+static Lisp_Object Vparam_value_alist;
+
 /* The total number of colors currently allocated.  */
 
 #if GLYPH_DEBUG
@@ -425,6 +493,10 @@ static int npixmaps_allocated;
 static int ngcs;
 #endif
 
+/* Non-zero means the definition of the `menu' face for new frames has
+   been changed.  */
+
+int menu_face_changed_default;
 
 \f
 /* Function prototypes.  */
@@ -432,15 +504,15 @@ static int ngcs;
 struct font_name;
 struct table_entry;
 
+static void map_tty_color P_ ((struct frame *, struct face *,
+                              enum lface_attribute_index, int *));
 static Lisp_Object resolve_face_name P_ ((Lisp_Object));
-static int may_use_scalable_font_p P_ ((struct font_name *, char *));
+static int may_use_scalable_font_p P_ ((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));
-static int first_font_matching P_ ((struct frame *f, char *,
-                                   struct font_name *));
+                             int, int));
 static int x_face_list_fonts P_ ((struct frame *, char *,
-                                 struct font_name *, int, int, int));
+                                 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 *));
@@ -456,10 +528,14 @@ 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,
+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,
                                      struct face *, int));
@@ -484,7 +560,9 @@ static int face_numeric_slant P_ ((Lisp_Object));
 static int face_numeric_swidth P_ ((Lisp_Object));
 static int face_fontset P_ ((Lisp_Object *));
 static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int, int));
-static void merge_face_vectors P_ ((Lisp_Object *from, Lisp_Object *));
+static void merge_face_vectors P_ ((struct frame *, Lisp_Object *, Lisp_Object*, Lisp_Object));
+static void merge_face_inheritance P_ ((struct frame *f, Lisp_Object,
+                                       Lisp_Object *, Lisp_Object));
 static void merge_face_vector_with_property P_ ((struct frame *, Lisp_Object *,
                                                 Lisp_Object));
 static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object,
@@ -493,7 +571,7 @@ static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
 static struct face *make_realized_face P_ ((Lisp_Object *));
 static void free_realized_faces P_ ((struct face_cache *));
 static char *best_matching_font P_ ((struct frame *, Lisp_Object *,
-                                    struct font_name *, int));
+                                    struct font_name *, 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 *));
@@ -519,12 +597,16 @@ 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 frame *));
+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 */
 
+#ifdef USE_X_TOOLKIT
+static void x_update_menu_appearance P_ ((struct frame *));
+#endif /* USE_X_TOOLKIT */
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 \f
@@ -594,7 +676,7 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
   int i, n;
 
   fputc ('\n', stderr);
-  
+
   for (i = n = 0; i < sizeof color_count / sizeof color_count[0]; ++i)
     if (color_count[i])
       {
@@ -611,9 +693,9 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
   return Qnil;
 }
 
-
 #endif /* DEBUG_X_COLORS */
 
+
 /* Free colors used on frame F.  PIXELS is an array of NPIXELS pixel
    color values.  Interrupt input must be blocked when this function
    is called.  */
@@ -630,11 +712,11 @@ x_free_colors (f, pixels, npixels)
      necessary and some servers don't allow it.  So don't do it.  */
   if (class != StaticColor && class != StaticGray && class != TrueColor)
     {
-      XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
-                  pixels, npixels, 0);
 #ifdef DEBUG_X_COLORS
       unregister_colors (pixels, npixels);
 #endif
+      XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+                  pixels, npixels, 0);
     }
 }
 
@@ -658,10 +740,10 @@ x_free_dpy_colors (dpy, screen, cmap, pixels, npixels)
      necessary and some servers don't allow it.  So don't do it.  */
   if (class != StaticColor && class != StaticGray && class != TrueColor)
     {
-      XFreeColors (dpy, cmap, pixels, npixels, 0);
 #ifdef DEBUG_X_COLORS
       unregister_colors (pixels, npixels);
 #endif
+      XFreeColors (dpy, cmap, pixels, npixels, 0);
     }
 }
 
@@ -793,7 +875,7 @@ frame_or_selected_frame (frame, nparam)
 {
   if (NILP (frame))
     frame = selected_frame;
-  
+
   CHECK_LIVE_FRAME (frame, nparam);
   return XFRAME (frame);
 }
@@ -812,7 +894,7 @@ init_frame_faces (f)
   /* Make a face cache, if F doesn't have one.  */
   if (FRAME_FACE_CACHE (f) == NULL)
     FRAME_FACE_CACHE (f) = make_face_cache (f);
-      
+
 #ifdef HAVE_WINDOW_SYSTEM
   /* Make the image cache.  */
   if (FRAME_WINDOW_P (f))
@@ -823,7 +905,7 @@ init_frame_faces (f)
     }
 #endif /* HAVE_WINDOW_SYSTEM */
 
-  /* Realize basic faces.  Must have enough information in frame 
+  /* Realize basic faces.  Must have enough information in frame
      parameters to realize basic faces at this point.  */
 #ifdef HAVE_X_WINDOWS
   if (!FRAME_X_P (f) || FRAME_X_WINDOW (f))
@@ -843,7 +925,7 @@ free_frame_faces (f)
      struct frame *f;
 {
   struct face_cache *face_cache = FRAME_FACE_CACHE (f);
-  
+
   if (face_cache)
     {
       free_face_cache (face_cache);
@@ -897,6 +979,14 @@ clear_face_cache (clear_fonts_p)
   if (clear_fonts_p
       || ++clear_font_table_count == CLEAR_FONT_TABLE_COUNT)
     {
+      struct x_display_info *dpyinfo;
+      
+      /* 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);
+      
       /* From time to time see if we can unload some fonts.  This also
         frees all realized faces on all frames.  Fonts needed by
         faces will be loaded again when faces are realized again.  */
@@ -904,13 +994,10 @@ clear_face_cache (clear_fonts_p)
 
       FOR_EACH_FRAME (tail, frame)
        {
-         f = XFRAME (frame);
+         struct frame *f = XFRAME (frame);
          if (FRAME_WINDOW_P (f)
              && FRAME_X_DISPLAY_INFO (f)->n_fonts > CLEAR_FONT_TABLE_NFONTS)
-           {
-             free_all_realized_faces (frame);
-             clear_font_table (f);
-           }
+           free_all_realized_faces (frame);
        }
     }
   else
@@ -933,10 +1020,12 @@ clear_face_cache (clear_fonts_p)
 DEFUN ("clear-face-cache", Fclear_face_cache, Sclear_face_cache, 0, 1, 0,
   "Clear face caches on all frames.\n\
 Optional THOROUGHLY non-nil means try to free unused fonts, too.")
-  (thorougly)
-     Lisp_Object thorougly;
+  (thoroughly)
+     Lisp_Object thoroughly;
 {
-  clear_face_cache (!NILP (thorougly));
+  clear_face_cache (!NILP (thoroughly));
+  ++face_change_count;
+  ++windows_or_buffers_changed;
   return Qnil;
 }
 
@@ -945,26 +1034,37 @@ Optional THOROUGHLY non-nil means try to free unused fonts, too.")
 #ifdef HAVE_WINDOW_SYSTEM
 
 
-/* Remove those fonts from the font table of frame F exept for the
-   default ASCII font for the frame.  Called from clear_face_cache
+/* 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 (f)
-     struct frame *f;
+clear_font_table (dpyinfo)
+     struct x_display_info *dpyinfo;
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   int i;
 
-  xassert (FRAME_WINDOW_P (f));
-
-  /* Free those fonts that are not used by the frame F as the default.  */
+  /* 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 on this display.  */
+      FOR_EACH_FRAME (tail, frame)
+       {
+         struct frame *f = XFRAME (frame);
+         if (FRAME_WINDOW_P (f)
+             && FRAME_X_DISPLAY_INFO (f) == dpyinfo
+             && font_info->font == FRAME_FONT (f))
+           break;
+       }
 
-      if (!font_info->name
-         || font_info->font == FRAME_FONT (f))
+      if (!NILP (tail))
        continue;
 
       /* Free names.  */
@@ -1009,7 +1109,7 @@ the pixmap.  Bits are stored row by row, each row occupies\n\
      Lisp_Object object;
 {
   int pixmap_p = 0;
-  
+
   if (STRINGP (object))
     /* If OBJECT is a string, it's a file name.  */
     pixmap_p = 1;
@@ -1021,7 +1121,7 @@ the pixmap.  Bits are stored row by row, each row occupies\n\
       Lisp_Object width, height, data;
 
       height = width = data = Qnil;
-      
+
       if (CONSP (object))
        {
          width = XCAR (object);
@@ -1136,7 +1236,7 @@ frame_update_line_height (f)
      struct frame *f;
 {
   int line_height, changed_p;
-  
+
   line_height = FONT_HEIGHT (FRAME_FONT (f));
   changed_p = line_height != FRAME_LINE_HEIGHT (f);
   FRAME_LINE_HEIGHT (f) = line_height;
@@ -1164,7 +1264,7 @@ load_face_font (f, face, c)
 {
   struct font_info *font_info = NULL;
   char *font_name;
-        
+
   face->font_info_id = -1;
   face->font = NULL;
 
@@ -1211,8 +1311,8 @@ tty_defined_color (f, color_name, color_def, alloc)
      int alloc;
 {
   Lisp_Object color_desc;
-  unsigned long color_idx = FACE_TTY_DEFAULT_COLOR,
-    red = 0, green = 0, blue = 0;
+  unsigned long color_idx = FACE_TTY_DEFAULT_COLOR;
+  unsigned long red = 0, green = 0, blue = 0;
   int status = 1;
 
   if (*color_name && !NILP (Ffboundp (Qtty_color_desc)))
@@ -1285,7 +1385,6 @@ defined_color (f, color_name, color_def, alloc)
 #endif
 #ifdef macintosh
   else if (FRAME_MAC_P (f))
-    /* FIXME: mac_defined_color doesn't exist!  */
     return mac_defined_color (f, color_name, color_def, alloc);
 #endif
   else
@@ -1352,7 +1451,7 @@ face_color_gray_p (f, color_name)
                  < max (color.blue, color.red) / 20));
   else
     gray_p = 0;
-  
+
   return gray_p;
 }
 
@@ -1436,7 +1535,7 @@ load_color (f, face, name, target_index)
      enum lface_attribute_index target_index;
 {
   XColor color;
-  
+
   xassert (STRINGP (name));
   xassert (target_index == LFACE_FOREGROUND_INDEX
           || target_index == LFACE_BACKGROUND_INDEX
@@ -1444,40 +1543,40 @@ load_color (f, face, name, target_index)
           || target_index == LFACE_OVERLINE_INDEX
           || target_index == LFACE_STRIKE_THROUGH_INDEX
           || target_index == LFACE_BOX_INDEX);
-      
+
   /* if the color map is full, defined_color will return a best match
      to the values in an existing cell. */
   if (!defined_color (f, XSTRING (name)->data, &color, 1))
     {
       add_to_log ("Unable to load color \"%s\"", name, Qnil);
-      
+
       switch (target_index)
        {
        case LFACE_FOREGROUND_INDEX:
          face->foreground_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_BACKGROUND_INDEX:
          face->background_defaulted_p = 1;
          color.pixel = FRAME_BACKGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_UNDERLINE_INDEX:
          face->underline_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_OVERLINE_INDEX:
          face->overline_color_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_STRIKE_THROUGH_INDEX:
          face->strike_through_color_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_BOX_INDEX:
          face->box_color_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
@@ -1491,7 +1590,7 @@ load_color (f, face, name, target_index)
   else
     ++ncolors_allocated;
 #endif
-  
+
   return color.pixel;
 }
 
@@ -1548,9 +1647,12 @@ unload_color (f, pixel)
      unsigned long pixel;
 {
 #ifdef HAVE_X_WINDOWS
-  BLOCK_INPUT;
-  x_free_colors (f, &pixel, 1);
-  UNBLOCK_INPUT;
+  if (pixel != -1)
+    {
+      BLOCK_INPUT;
+      x_free_colors (f, &pixel, 1);
+      UNBLOCK_INPUT;
+    }
 #endif
 }
 
@@ -1564,13 +1666,13 @@ free_face_colors (f, face)
 {
 #ifdef HAVE_X_WINDOWS
   BLOCK_INPUT;
-      
+
   if (!face->foreground_defaulted_p)
     {
       x_free_colors (f, &face->foreground, 1);
       IF_DEBUG (--ncolors_allocated);
     }
-      
+
   if (!face->background_defaulted_p)
     {
       x_free_colors (f, &face->background, 1);
@@ -1638,7 +1740,7 @@ enum xlfd_field
   XLFD_LAST
 };
 
-/* An enumerator for each possible slant value of a font.  Taken from 
+/* An enumerator for each possible slant value of a font.  Taken from
    the XLFD specification.  */
 
 enum xlfd_slant
@@ -1716,6 +1818,7 @@ 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},
@@ -1769,6 +1872,9 @@ struct font_name
   /* Numeric values for those fields that interest us.  See
      split_font_name for which these are.  */
   int numeric[XLFD_LAST];
+
+  /* Lower value mean higher priority.  */
+  int registry_priority;
 };
 
 /* The frame in effect when sorting font names.  Set temporarily in
@@ -1781,8 +1887,13 @@ static struct frame *font_frame;
    font height, then for weight, then for slant.'  This variable can be
    set via set-face-font-sort-order.  */
 
+#ifdef macintosh
+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
@@ -1808,7 +1919,7 @@ xlfd_lookup_field_contents (table, dim, font, field_index)
     {
       mid = (low + high) / 2;
       cmp = strcmp (table[mid].name, s);
-      
+
       if (cmp < 0)
        low = mid + 1;
       else if (cmp > 0)
@@ -1926,7 +2037,7 @@ xlfd_symbolic_swidth (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
@@ -1941,7 +2052,7 @@ face_value (table, dim, symbol)
   int i;
 
   xassert (SYMBOLP (symbol));
-  
+
   for (i = 0; i < dim; ++i)
     if (EQ (*table[i].symbol, symbol))
       break;
@@ -2030,14 +2141,41 @@ xlfd_point_size (f, font)
      struct font_name *font;
 {
   double resy = FRAME_X_DISPLAY_INFO (f)->resy;
-  double font_resy = atoi (font->fields[XLFD_RESY]);
-  double font_pt = atoi (font->fields[XLFD_POINT_SIZE]);
+  char *pixel_field = font->fields[XLFD_PIXEL_SIZE];
+  double pixel;
   int real_pt;
 
-  if (font_resy == 0 || font_pt == 0)
+  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);
+  
+  if (pixel == 0)
     real_pt = 0;
   else
-    real_pt = (font_resy / resy) * font_pt + 0.5;
+    real_pt = PT_PER_INCH * 10.0 * pixel / resy + 0.5;
 
   return real_pt;
 }
@@ -2056,8 +2194,9 @@ pixel_point_size (f, pixel)
   double real_pt;
   int int_pt;
 
-  /* As one inch is 72 points, 72/RESY gives the point size of one dot.  */
-  real_pt = pixel * 72 / resy;
+  /* 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;
@@ -2070,9 +2209,7 @@ pixel_point_size (f, pixel)
    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 `-'.  (The XLFD specification allows
-   forms of font names where certain field contents are enclosed in
-   square brackets.  We don't support that, for now.  */
+   XLFD_LAST fields separated by `-'.  */
 
 static int
 split_font_name (f, font, numeric_p)
@@ -2091,13 +2228,40 @@ split_font_name (f, font, numeric_p)
        {
          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;
        }
     }
@@ -2113,15 +2277,20 @@ split_font_name (f, font, numeric_p)
       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]);
     }
 
+  /* 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;
@@ -2192,109 +2361,76 @@ sort_fonts (f, fonts, nfonts, cmpfn)
    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.  SCALABLE_FONTS_P non-zero means include
-   scalable fonts.
+   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.
-   
-   This is similar to x_list_fonts.  The differences are:
-
-   1. It avoids consing.
-   2. It never calls XLoadQueryFont.  */
+   fonts that we can't parse.  Value is the number of fonts found.  */
 
 static int
-x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
-                  scalable_fonts_p)
+x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p)
      struct frame *f;
      char *pattern;
      struct font_name *fonts;
      int nfonts, try_alternatives_p;
-     int scalable_fonts_p;
 {
-  int n, i, j;
-  char **names;
-#ifdef HAVE_X_WINDOWS
-  Display *dpy = f ? FRAME_X_DISPLAY (f) : x_display_list->display;
+  int n, nignored;
 
-  /* Get the list of fonts matching PATTERN from the X server.  */
-  BLOCK_INPUT;
-  names = XListFonts (dpy, pattern, nfonts, &n);
-  UNBLOCK_INPUT;
-#endif
-#ifdef WINDOWSNT
   /* 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;
 
-  n = 0;
-  names = NULL;
-
   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;
-
-  /* Count fonts returned */
-  for (tem = lfonts; CONSP (tem); tem = XCDR (tem))
-    n++;
-
-  /* Allocate array.  */
-  if (n)
-    names = (char **) xmalloc (n * sizeof (char *));
-
-  /* Extract font names into char * array.  */
-  tem = lfonts;
-  for (i = 0; i < n; i++)
-    {
-      names[i] = XSTRING (XCAR (tem))->data;
-      tem = XCDR (tem);
-    }
+#else
+  lfonts = x_list_fonts (f, lpattern, -1, nfonts);
 #endif
 
-  if (names)
+  /* 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 < nfonts; tem = XCDR (tem))
     {
-      /* Make a copy of the font names we got from X, and
-        split them into fields.  */
-      for (i = j = 0; i < n; ++i)
+      Lisp_Object elt, tail;
+      char *name = XSTRING (XCAR (tem))->data;
+
+      /* 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))
        {
-         /* Make a copy of the font name.  */
-         fonts[j].name = xstrdup (names[i]);
+         ++nignored;
+         continue;
+       }
 
-         /* Ignore fonts having a name that we can't parse.  */
-         if (!split_font_name (f, fonts + j, 1))
-           xfree (fonts[j].name);
-         else if (font_scalable_p (fonts + j))
+      /* 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))
            {
-#if SCALABLE_FONTS
-             if (!scalable_fonts_p
-                 || !may_use_scalable_font_p (fonts + j, names[i]))
-               xfree (fonts[j].name);
-             else
-               ++j;
-#else /* !SCALABLE_FONTS */
-             /* Always ignore scalable fonts.  */
-             xfree (fonts[j].name);
-#endif /* !SCALABLE_FONTS */
+             ++nignored;
+             xfree (fonts[n].name);
            }
          else
-           ++j;
+           ++n;
        }
-
-      n = j;
-
-#ifdef HAVE_X_WINDOWS
-      /* Free font names.  */
-      BLOCK_INPUT;
-      XFreeFontNames (names);
-      UNBLOCK_INPUT;
-#endif
+      else
+       xfree (fonts[n].name);
     }
-  
 
   /* If no fonts found, try patterns from Valternate_fontname_alist.  */
   if (n == 0 && try_alternatives_p)
@@ -2315,7 +2451,7 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
        {
          Lisp_Object patterns = XCAR (list);
          Lisp_Object name;
-      
+
          while (CONSP (patterns)
                 /* If list is screwed up, give up.  */
                 && (name = XCAR (patterns),
@@ -2324,42 +2460,13 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
                    already with no success.  */
                 && (strcmp (XSTRING (name)->data, pattern) == 0
                     || (n = x_face_list_fonts (f, XSTRING (name)->data,
-                                               fonts, nfonts, 0,
-                                               scalable_fonts_p),
+                                               fonts, nfonts, 0),
                         n == 0)))
            patterns = XCDR (patterns);
        }
     }
-  
-  return n;
-}
-  
-
-/* Determine the first font matching PATTERN on frame F.  Return in
-   *FONT the matching font name, split into fields.  Value is non-zero
-   if a match was found.  */
-
-static int
-first_font_matching (f, pattern, font)
-     struct frame *f;
-     char *pattern;
-     struct font_name *font;
-{
-  int nfonts = 100;
-  struct font_name *fonts;
-
-  fonts = (struct font_name *) xmalloc (nfonts * sizeof *fonts);
-  nfonts = x_face_list_fonts (f, pattern, fonts, nfonts, 1, 0);
-
-  if (nfonts > 0)
-    {
-      bcopy (&fonts[0], font, sizeof *font);
-      
-      fonts[0].name = NULL;
-      free_font_names (fonts, nfonts);
-    }
 
-  return nfonts > 0;
+  return n;
 }
 
 
@@ -2379,20 +2486,16 @@ sorted_font_list (f, pattern, cmpfn, fonts)
      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) && XINT (Vfont_list_limit) > 0)
     nfonts = XFASTINT (Vfont_list_limit);
-  
+
   *fonts = (struct font_name *) xmalloc (nfonts * sizeof **fonts);
-#if SCALABLE_FONTS
-  nfonts = x_face_list_fonts (f, pattern, *fonts, nfonts, 1, 1);
-#else
-  nfonts = x_face_list_fonts (f, pattern, *fonts, nfonts, 1, 0);
-#endif
-  
-  /* Sort the resulting array and return it in *FONTS.  If no 
+  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);
@@ -2427,7 +2530,7 @@ cmp_font_names (a, b)
   if (cmp == 0)
     {
       int i;
-      
+
       for (i = 0; i < DIM (font_sort_order) && cmp == 0; ++i)
        {
          int j = font_sort_order[i];
@@ -2457,7 +2560,7 @@ cmp_font_names (a, b)
    Value is the number of fonts found.  */
 
 static int
-font_list (f, pattern, family, registry, fonts)
+font_list_1 (f, pattern, family, registry, fonts)
      struct frame *f;
      Lisp_Object pattern, family, registry;
      struct font_name **fonts;
@@ -2468,7 +2571,7 @@ font_list (f, pattern, family, registry, fonts)
     {
       family_str = (NILP (family) ? "*" : (char *) XSTRING (family)->data);
       registry_str = (NILP (registry) ? "*" : (char *) XSTRING (registry)->data);
-      
+
       pattern_str = (char *) alloca (strlen (family_str)
                                     + strlen (registry_str)
                                     + 10);
@@ -2486,21 +2589,98 @@ font_list (f, pattern, family, registry, fonts)
     }
   else
     pattern_str = (char *) XSTRING (pattern)->data;
-  
+
   return sorted_font_list (f, pattern_str, cmp_font_names, fonts);
 }
 
 
-/* Remove elements from LIST whose cars are `equal'.  Called from
-   x-family-fonts and x-font-family-list to remove duplicate font
-   entries.  */
+/* 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 void
+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, return fonts with that registry 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 = font_list_1 (f, pattern, family, registry, fonts);
+  
+  if (!NILP (registry)
+      && CONSP (Vface_alternative_font_registry_alist))
+    {
+      Lisp_Object alter;
+
+      alter = Fassoc (registry, Vface_alternative_font_registry_alist);
+      if (CONSP (alter))
+       {
+         int reg_prio, i;
+
+         for (alter = XCDR (alter), reg_prio = 1;
+              CONSP (alter);
+              alter = XCDR (alter), reg_prio++)
+           if (STRINGP (XCAR (alter)))
+             {
+               int nfonts2;
+               struct font_name *fonts2;
+
+               nfonts2 = font_list_1 (f, pattern, family, XCAR (alter),
+                                      &fonts2);
+               for (i = 0; i < nfonts2; i++)
+                 fonts2[i].registry_priority = reg_prio;
+               *fonts = (nfonts > 0
+                         ? concat_font_list (*fonts, nfonts, fonts2, nfonts2)
+                         : 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);
@@ -2539,7 +2719,7 @@ the face font sort order.")
 
   if (!NILP (family))
     CHECK_STRING (family, 1);
-  
+
   result = Qnil;
   GCPRO1 (result);
   nfonts = font_list (f, Qnil, family, Qnil, &fonts);
@@ -2548,8 +2728,6 @@ the face font sort order.")
       Lisp_Object v = Fmake_vector (make_number (8), Qnil);
       char *tem;
 
-#define ASET(VECTOR, IDX, VAL) (XVECTOR (VECTOR)->contents[IDX] = (VAL))
-      
       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)));
@@ -2562,10 +2740,8 @@ the face font sort order.")
               fonts[i].fields[XLFD_ENCODING]);
       ASET (v, 7, build_string (tem));
       xfree (tem);
-      
+
       result = Fcons (v, result);
-      
-#undef ASET
     }
 
   remove_duplicates (result);
@@ -2599,7 +2775,7 @@ are fixed-pitch.")
     {
       specbind (intern ("font-list-limit"), make_number (limit));
       nfonts = font_list (f, Qnil, Qnil, Qnil, &fonts);
-      
+
       if (nfonts == limit)
        {
          free_font_names (fonts, nfonts);
@@ -2608,7 +2784,7 @@ are fixed-pitch.")
       else
        break;
     }
-  
+
   result = Qnil;
   GCPRO1 (result);
   for (i = nfonts - 1; i >= 0; --i)
@@ -2652,7 +2828,7 @@ the WIDTH times as wide as FACE on FRAME.")
 
   check_x ();
   CHECK_STRING (pattern, 0);
-  
+
   if (NILP (maximum))
     maxnames = 2000;
   else
@@ -2683,9 +2859,11 @@ the WIDTH times as wide as FACE on FRAME.")
       /* This is of limited utility since it works with character
         widths.  Keep it for compatibility.  --gerd.  */
       int face_id = lookup_named_face (f, face, 0);
-      struct face *face = FACE_FROM_ID (f, face_id);
+      struct face *face = (face_id < 0
+                          ? NULL
+                          : FACE_FROM_ID (f, face_id));
 
-      if (face->font)
+      if (face && face->font)
        size = FONT_WIDTH (face->font);
       else
        size = FONT_WIDTH (FRAME_FONT (f));
@@ -2714,36 +2892,24 @@ the WIDTH times as wide as FACE on FRAME.")
                              Lisp Faces
  ***********************************************************************/
 
-/* Access face attributes of face FACE, a Lisp vector.  */
-
-#define LFACE_FAMILY(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_FAMILY_INDEX]
-#define LFACE_HEIGHT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_HEIGHT_INDEX]
-#define LFACE_WEIGHT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_WEIGHT_INDEX]
-#define LFACE_SLANT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_SLANT_INDEX]
-#define LFACE_UNDERLINE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_UNDERLINE_INDEX]
-#define LFACE_INVERSE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_INVERSE_INDEX]
-#define LFACE_FOREGROUND(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_FOREGROUND_INDEX]
-#define LFACE_BACKGROUND(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_BACKGROUND_INDEX]
-#define LFACE_STIPPLE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_STIPPLE_INDEX]
-#define LFACE_SWIDTH(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_SWIDTH_INDEX]
-#define LFACE_OVERLINE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_OVERLINE_INDEX]
-#define LFACE_STRIKE_THROUGH(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_STRIKE_THROUGH_INDEX]
-#define LFACE_BOX(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_BOX_INDEX]
-#define LFACE_FONT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_FONT_INDEX]
+/* Access face attributes of face LFACE, a Lisp vector.  */
+
+#define LFACE_FAMILY(LFACE)        AREF ((LFACE), LFACE_FAMILY_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)
+#define LFACE_UNDERLINE(LFACE)      AREF ((LFACE), LFACE_UNDERLINE_INDEX)
+#define LFACE_INVERSE(LFACE)       AREF ((LFACE), LFACE_INVERSE_INDEX)
+#define LFACE_FOREGROUND(LFACE)     AREF ((LFACE), LFACE_FOREGROUND_INDEX)
+#define LFACE_BACKGROUND(LFACE)     AREF ((LFACE), LFACE_BACKGROUND_INDEX)
+#define LFACE_STIPPLE(LFACE)       AREF ((LFACE), LFACE_STIPPLE_INDEX)
+#define LFACE_SWIDTH(LFACE)        AREF ((LFACE), LFACE_SWIDTH_INDEX)
+#define LFACE_OVERLINE(LFACE)      AREF ((LFACE), LFACE_OVERLINE_INDEX)
+#define LFACE_STRIKE_THROUGH(LFACE) AREF ((LFACE), LFACE_STRIKE_THROUGH_INDEX)
+#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)
 
 /* Non-zero if LFACE is a Lisp face.  A Lisp face is a vector of size
    LFACE_VECTOR_SIZE which has the symbol `face' in slot 0.  */
@@ -2751,9 +2917,9 @@ the WIDTH times as wide as FACE on FRAME.")
 #define LFACEP(LFACE)                                  \
      (VECTORP (LFACE)                                  \
       && XVECTOR (LFACE)->size == LFACE_VECTOR_SIZE    \
-      && EQ (XVECTOR (LFACE)->contents[0], Qface))
+      && EQ (AREF (LFACE, 0), Qface))
+
 
-     
 #if GLYPH_DEBUG
 
 /* Check consistency of Lisp face attribute vector ATTRS.  */
@@ -2766,8 +2932,12 @@ check_lface_attrs (attrs)
           || STRINGP (attrs[LFACE_FAMILY_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
           || SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
+  xassert (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
+          || INTEGERP (attrs[LFACE_AVGWIDTH_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
-          || INTEGERP (attrs[LFACE_HEIGHT_INDEX]));
+          || INTEGERP (attrs[LFACE_HEIGHT_INDEX])
+          || FLOATP (attrs[LFACE_HEIGHT_INDEX])
+          || FUNCTIONP (attrs[LFACE_HEIGHT_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
           || SYMBOLP (attrs[LFACE_WEIGHT_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
@@ -2792,6 +2962,10 @@ check_lface_attrs (attrs)
           || STRINGP (attrs[LFACE_FOREGROUND_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
           || STRINGP (attrs[LFACE_BACKGROUND_INDEX]));
+  xassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX])
+          || NILP (attrs[LFACE_INHERIT_INDEX])
+          || SYMBOLP (attrs[LFACE_INHERIT_INDEX])
+          || CONSP (attrs[LFACE_INHERIT_INDEX]));
 #ifdef HAVE_WINDOW_SYSTEM
   xassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
           || SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
@@ -2833,11 +3007,11 @@ resolve_face_name (face_name)
      Lisp_Object face_name;
 {
   Lisp_Object aliased;
-  
+
   if (STRINGP (face_name))
     face_name = intern (XSTRING (face_name)->data);
 
-  for (;;)
+  while (SYMBOLP (face_name))
     {
       aliased = Fget (face_name, Qface_alias);
       if (NILP (aliased))
@@ -2851,10 +3025,10 @@ resolve_face_name (face_name)
 
 
 /* Return the face definition of FACE_NAME on frame F.  F null means
-   return the global definition.  FACE_NAME may be a string or a
-   symbol (apparently Emacs 20.2 allows 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
+   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.  */
@@ -2924,8 +3098,10 @@ lface_fully_specified_p (attrs)
   int i;
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-    if (UNSPECIFIEDP (attrs[i]) && i != LFACE_FONT_INDEX)
-      break;
+    if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX
+       && i != LFACE_AVGWIDTH_INDEX)
+      if (UNSPECIFIEDP (attrs[i])) 
+        break;
 
   return i == LFACE_VECTOR_SIZE;
 }
@@ -2943,7 +3119,7 @@ lface_fully_specified_p (attrs)
        return 0 if MAY_FAIL_P is non-zero, otherwise set normal values
        in LFACE and return 1.
    Otherwise, return 1.  */
-   
+
 static int
 set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
      struct frame *f;
@@ -2986,7 +3162,7 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
   /* 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.  */
-  
+
   if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
     {
       Lisp_Object val;
@@ -3018,6 +3194,12 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
     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);
+
   if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
     LFACE_WEIGHT (lface)
       = have_xlfd_p ? xlfd_symbolic_weight (&font) : Qnormal;
@@ -3027,24 +3209,201 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
       = have_xlfd_p ? xlfd_symbolic_slant (&font) : Qnormal;
 
   LFACE_FONT (lface) = fontname;
-  
+
   return 1;
 }
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 
-/* Merge two Lisp face attribute vectors FROM and TO and store the
-   resulting attributes in TO.  Every non-nil attribute of FROM
-   overrides the corresponding attribute of TO.  */
+/* Merges the face height FROM with the face height TO, and returns the
+   merged height.  If FROM is an invalid height, then INVALID is
+   returned instead.  FROM may be a either an absolute face height or a
+   `relative' height, and TO must be an absolute height.  The returned
+   value is always an absolute height.  GCPRO is a lisp value that will
+   be protected from garbage-collection if this function makes a call
+   into lisp.  */
+
+Lisp_Object
+merge_face_heights (from, to, invalid, gcpro)
+     Lisp_Object from, to, invalid, gcpro;
+{
+  int result = 0;
+
+  if (INTEGERP (from))
+    result = XINT (from);
+  else if (NUMBERP (from))
+    result = XFLOATINT (from) * XINT (to);
+#if 0 /* Probably not so useful.  */
+  else if (CONSP (from) && CONSP (XCDR (from)))
+    {
+      if (EQ (XCAR(from), Qplus) || EQ (XCAR(from), Qminus))
+       {
+         if (INTEGERP (XCAR (XCDR (from))))
+           {
+             int inc = XINT (XCAR (XCDR (from)));
+             if (EQ (XCAR (from), Qminus))
+               inc = -inc;
+
+             result = XFASTINT (to);
+             if (result + inc > 0)
+               /* Note that `underflows' don't mean FROM is invalid, so
+                  we just pin the result at TO if it would otherwise be
+                  negative or 0.  */
+               result += inc;
+           }
+       }
+    }
+#endif
+  else if (FUNCTIONP (from))
+    {
+      /* Call function with current height as argument.
+        From is the new height.  */
+      Lisp_Object args[2], height;
+      struct gcpro gcpro1;
+
+      GCPRO1 (gcpro);
+
+      args[0] = from;
+      args[1] = to;
+      height = safe_call (2, args);
+
+      UNGCPRO;
+
+      if (NUMBERP (height))
+       result = XFLOATINT (height);
+    }
+
+  if (result > 0)
+    return make_number (result);
+  else
+    return invalid;
+}
+
+
+/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
+   store the resulting attributes in TO, which must be already be
+   completely specified and contain only absolute attributes.  Every
+   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.  CYCLE_CHECK is used internally to detect loops in
+   face inheritance; it should be Qnil when called from other places.  */
 
 static INLINE void
-merge_face_vectors (from, to)
+merge_face_vectors (f, from, to, cycle_check)
+     struct frame *f;
      Lisp_Object *from, *to;
+     Lisp_Object cycle_check;
 {
   int i;
+
+  /* If FROM inherits from some other faces, merge their attributes into
+     TO before merging FROM's direct attributes.  Note that an :inherit
+     attribute of `unspecified' is the same as one of nil; we never
+     merge :inherit attributes, so nil is more correct, but lots of
+     other code uses `unspecified' as a generic value for face attributes. */
+  if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
+      && !NILP (from[LFACE_INHERIT_INDEX]))
+    merge_face_inheritance (f, from[LFACE_INHERIT_INDEX], to, cycle_check);
+
+  /* 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;
+
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (!UNSPECIFIEDP (from[i]))
-      to[i] = from[i];
+      if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
+       to[i] = merge_face_heights (from[i], to[i], to[i], cycle_check);
+      else
+       to[i] = from[i];
+
+  /* TO is always an absolute face, which should inherit from nothing.
+     We blindly copy the :inherit attribute above and fix it up here.  */
+  to[LFACE_INHERIT_INDEX] = Qnil;
+}
+
+
+/* Checks the `cycle check' variable CHECK to see if it indicates that
+   EL is part of a cycle; CHECK must be either Qnil or a value returned
+   by an earlier use of CYCLE_CHECK.  SUSPICIOUS is the number of
+   elements after which a cycle might be suspected; after that many
+   elements, this macro begins consing in order to keep more precise
+   track of elements.
+
+   Returns NIL if a cycle was detected, otherwise a new value for CHECK
+   that includes EL.
+
+   CHECK is evaluated multiple times, EL and SUSPICIOUS 0 or 1 times, so
+   the caller should make sure that's ok.  */
+
+#define CYCLE_CHECK(check, el, suspicious)     \
+  (NILP (check)                                        \
+   ? make_number (0)                           \
+   : (INTEGERP (check)                         \
+      ? (XFASTINT (check) < (suspicious)       \
+        ? make_number (XFASTINT (check) + 1)   \
+        : Fcons (el, Qnil))                    \
+      : (!NILP (Fmemq ((el), (check)))         \
+        ? Qnil                                 \
+        : Fcons ((el), (check)))))
+
+
+/* Merge face attributes from the face on frame F whose name is
+   INHERITS, into the vector of face attributes TO; INHERITS may also be
+   a list of face names, in which case they are applied in order.
+   CYCLE_CHECK is used to detect loops in face inheritance.
+   Returns true if any of the inherited attributes are `font-related'.  */
+
+static void
+merge_face_inheritance (f, inherit, to, cycle_check)
+     struct frame *f;
+     Lisp_Object inherit;
+     Lisp_Object *to;
+     Lisp_Object cycle_check;
+{
+  if (SYMBOLP (inherit) && !EQ (inherit, Qunspecified))
+    /* Inherit from the named face INHERIT.  */
+    {
+      Lisp_Object lface;
+
+      /* Make sure we're not in an inheritance loop.  */
+      cycle_check = CYCLE_CHECK (cycle_check, inherit, 15);
+      if (NILP (cycle_check))
+       /* Cycle detected, ignore any further inheritance.  */
+       return;
+
+      lface = lface_from_face_name (f, inherit, 0);
+      if (!NILP (lface))
+       merge_face_vectors (f, XVECTOR (lface)->contents, to, cycle_check);
+    }
+  else if (CONSP (inherit))
+    /* Handle a list of inherited faces by calling ourselves recursively
+       on each element.  Note that we only do so for symbol elements, so
+       it's not possible to infinitely recurse.  */
+    {
+      while (CONSP (inherit))
+       {
+         if (SYMBOLP (XCAR (inherit)))
+           merge_face_inheritance (f, XCAR (inherit), to, cycle_check);
+
+         /* Check for a circular inheritance list.  */
+         cycle_check = CYCLE_CHECK (cycle_check, inherit, 15);
+         if (NILP (cycle_check))
+           /* Cycle detected.  */
+           break;
+
+         inherit = XCDR (inherit);
+       }
+    }
 }
 
 
@@ -3066,7 +3425,7 @@ merge_face_vectors (from, to)
 
    Face specifications earlier in lists take precedence over later
    specifications.  */
-   
+
 static void
 merge_face_vector_with_property (f, to, prop)
      struct frame *f;
@@ -3076,7 +3435,7 @@ merge_face_vector_with_property (f, to, prop)
   if (CONSP (prop))
     {
       Lisp_Object first = XCAR (prop);
-      
+
       if (EQ (first, Qforeground_color)
          || EQ (first, Qbackground_color))
        {
@@ -3109,14 +3468,18 @@ merge_face_vector_with_property (f, to, prop)
                  if (STRINGP (value))
                    to[LFACE_FAMILY_INDEX] = value;
                  else
-                   add_to_log ("Illegal face font family", value, Qnil);
+                   add_to_log ("Invalid face font family", value, Qnil);
                }
              else if (EQ (keyword, QCheight))
                {
-                 if (INTEGERP (value))
-                   to[LFACE_HEIGHT_INDEX] = value;
+                 Lisp_Object new_height =
+                   merge_face_heights (value, to[LFACE_HEIGHT_INDEX],
+                                       Qnil, Qnil);
+
+                 if (NILP (new_height))
+                   add_to_log ("Invalid face font height", value, Qnil);
                  else
-                   add_to_log ("Illegal face font height", value, Qnil);
+                   to[LFACE_HEIGHT_INDEX] = new_height;
                }
              else if (EQ (keyword, QCweight))
                {
@@ -3124,7 +3487,7 @@ merge_face_vector_with_property (f, to, prop)
                      && face_numeric_weight (value) >= 0)
                    to[LFACE_WEIGHT_INDEX] = value;
                  else
-                   add_to_log ("Illegal face weight", value, Qnil);
+                   add_to_log ("Invalid face weight", value, Qnil);
                }
              else if (EQ (keyword, QCslant))
                {
@@ -3132,7 +3495,7 @@ merge_face_vector_with_property (f, to, prop)
                      && face_numeric_slant (value) >= 0)
                    to[LFACE_SLANT_INDEX] = value;
                  else
-                   add_to_log ("Illegal face slant", value, Qnil);
+                   add_to_log ("Invalid face slant", value, Qnil);
                }
              else if (EQ (keyword, QCunderline))
                {
@@ -3141,7 +3504,7 @@ merge_face_vector_with_property (f, to, prop)
                      || STRINGP (value))
                    to[LFACE_UNDERLINE_INDEX] = value;
                  else
-                   add_to_log ("Illegal face underline", value, Qnil);
+                   add_to_log ("Invalid face underline", value, Qnil);
                }
              else if (EQ (keyword, QCoverline))
                {
@@ -3150,7 +3513,7 @@ merge_face_vector_with_property (f, to, prop)
                      || STRINGP (value))
                    to[LFACE_OVERLINE_INDEX] = value;
                  else
-                   add_to_log ("Illegal face overline", value, Qnil);
+                   add_to_log ("Invalid face overline", value, Qnil);
                }
              else if (EQ (keyword, QCstrike_through))
                {
@@ -3159,7 +3522,7 @@ merge_face_vector_with_property (f, to, prop)
                      || STRINGP (value))
                    to[LFACE_STRIKE_THROUGH_INDEX] = value;
                  else
-                   add_to_log ("Illegal face strike-through", value, Qnil);
+                   add_to_log ("Invalid face strike-through", value, Qnil);
                }
              else if (EQ (keyword, QCbox))
                {
@@ -3171,7 +3534,7 @@ merge_face_vector_with_property (f, to, prop)
                      || NILP (value))
                    to[LFACE_BOX_INDEX] = value;
                  else
-                   add_to_log ("Illegal face box", value, Qnil);
+                   add_to_log ("Invalid face box", value, Qnil);
                }
              else if (EQ (keyword, QCinverse_video)
                       || EQ (keyword, QCreverse_video))
@@ -3179,21 +3542,21 @@ merge_face_vector_with_property (f, to, prop)
                  if (EQ (value, Qt) || NILP (value))
                    to[LFACE_INVERSE_INDEX] = value;
                  else
-                   add_to_log ("Illegal face inverse-video", value, Qnil);
+                   add_to_log ("Invalid face inverse-video", value, Qnil);
                }
              else if (EQ (keyword, QCforeground))
                {
                  if (STRINGP (value))
                    to[LFACE_FOREGROUND_INDEX] = value;
                  else
-                   add_to_log ("Illegal face foreground", value, Qnil);
+                   add_to_log ("Invalid face foreground", value, Qnil);
                }
              else if (EQ (keyword, QCbackground))
                {
                  if (STRINGP (value))
                    to[LFACE_BACKGROUND_INDEX] = value;
                  else
-                   add_to_log ("Illegal face background", value, Qnil);
+                   add_to_log ("Invalid face background", value, Qnil);
                }
              else if (EQ (keyword, QCstipple))
                {
@@ -3202,7 +3565,7 @@ merge_face_vector_with_property (f, to, prop)
                  if (!NILP (pixmap_p))
                    to[LFACE_STIPPLE_INDEX] = value;
                  else
-                   add_to_log ("Illegal face stipple", value, Qnil);
+                   add_to_log ("Invalid face stipple", value, Qnil);
 #endif
                }
              else if (EQ (keyword, QCwidth))
@@ -3211,7 +3574,23 @@ merge_face_vector_with_property (f, to, prop)
                      && face_numeric_swidth (value) >= 0)
                    to[LFACE_SWIDTH_INDEX] = value;
                  else
-                   add_to_log ("Illegal face width", value, Qnil);
+                   add_to_log ("Invalid face width", value, Qnil);
+               }
+             else if (EQ (keyword, QCinherit))
+               {
+                 if (SYMBOLP (value))
+                   to[LFACE_INHERIT_INDEX] = value;
+                 else
+                   {
+                     Lisp_Object tail;
+                     for (tail = value; CONSP (tail); tail = XCDR (tail))
+                       if (!SYMBOLP (XCAR (tail)))
+                         break;
+                     if (NILP (tail))
+                       to[LFACE_INHERIT_INDEX] = value;
+                     else
+                       add_to_log ("Invalid face inherit", value, Qnil);
+                   }
                }
              else
                add_to_log ("Invalid attribute %s in face property",
@@ -3239,7 +3618,7 @@ merge_face_vector_with_property (f, to, prop)
       if (NILP (lface))
        add_to_log ("Invalid face text property value: %s", prop, Qnil);
       else
-       merge_face_vectors (XVECTOR (lface)->contents, to);
+       merge_face_vectors (f, XVECTOR (lface)->contents, to, Qnil);
     }
 }
 
@@ -3260,7 +3639,7 @@ Value is a vector of face attributes.")
 
   CHECK_SYMBOL (face, 0);
   global_lface = lface_from_face_name (NULL, face, 0);
-  
+
   if (!NILP (frame))
     {
       CHECK_LIVE_FRAME (frame, 1);
@@ -3275,10 +3654,10 @@ Value is a vector of face attributes.")
     {
       global_lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
                                   Qunspecified);
-      XVECTOR (global_lface)->contents[0] = Qface;
-      Vface_new_frame_defaults = Fcons (Fcons (face, global_lface), 
+      AREF (global_lface, 0) = Qface;
+      Vface_new_frame_defaults = Fcons (Fcons (face, global_lface),
                                        Vface_new_frame_defaults);
-      
+
       /* Assign the new Lisp face a unique ID.  The mapping from Lisp
         face id to Lisp face is given by the vector lface_id_to_name.
         The mapping from Lisp face to Lisp face id is given by the
@@ -3290,15 +3669,15 @@ Value is a vector of face attributes.")
          lface_id_to_name = (Lisp_Object *) xrealloc (lface_id_to_name, sz);
          lface_id_to_name_size = new_size;
        }
-      
+
       lface_id_to_name[next_lface_id] = face;
       Fput (face, Qface, make_number (next_lface_id));
       ++next_lface_id;
     }
   else if (f == NULL)
     for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-      XVECTOR (global_lface)->contents[i] = Qunspecified;
-    
+      AREF (global_lface, i) = Qunspecified;
+
   /* Add a frame-local definition.  */
   if (f)
     {
@@ -3306,12 +3685,12 @@ Value is a vector of face attributes.")
        {
          lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
                                Qunspecified);
-         XVECTOR (lface)->contents[0] = Qface;
+         AREF (lface, 0) = Qface;
          f->face_alist = Fcons (Fcons (face, lface), f->face_alist);
        }
       else
        for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-         XVECTOR (lface)->contents[i] = Qunspecified;
+         AREF (lface, i) = Qunspecified;
     }
   else
     lface = global_lface;
@@ -3332,7 +3711,7 @@ Otherwise check for the existence of a global face.")
      Lisp_Object face, frame;
 {
   Lisp_Object lface;
-  
+
   if (!NILP (frame))
     {
       CHECK_LIVE_FRAME (frame, 1);
@@ -3358,7 +3737,7 @@ Value is TO.")
      Lisp_Object from, to, frame, new_frame;
 {
   Lisp_Object lface, copy;
-  
+
   CHECK_SYMBOL (from, 0);
   CHECK_SYMBOL (to, 1);
   if (NILP (new_frame))
@@ -3379,10 +3758,10 @@ Value is TO.")
       lface = lface_from_face_name (XFRAME (frame), from, 1);
       copy = Finternal_make_lisp_face (to, new_frame);
     }
-  
+
   bcopy (XVECTOR (lface)->contents, XVECTOR (copy)->contents,
         LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
-  
+
   return to;
 }
 
@@ -3390,10 +3769,11 @@ Value is TO.")
 DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
        Sinternal_set_lisp_face_attribute, 3, 4, 0,
   "Set attribute ATTR of FACE to VALUE.\n\
-If optional argument FRAME is given, set the face attribute of face FACE\n\
-on that frame.  If FRAME is t, set the attribute of the default for face\n\
-FACE (for new frames).  If FRAME is omitted or nil, use the selected\n\
-frame.")
+FRAME being a frame means change the face on that frame.\n\
+FRAME nil means change the face of the selected frame.\n\
+FRAME t means change the default for new frames.\n\
+FRAME 0 means change the face on all frames, and change the default\n\
+  for new frames.")
   (face, attr, value, frame)
      Lisp_Object face, attr, value, frame;
 {
@@ -3403,12 +3783,23 @@ frame.")
   int font_attr_p = 0;
   /* Set 1 if ATTR is one of font-related attributes other than QCfont.  */
   int font_related_attr_p = 0;
-  
+
   CHECK_SYMBOL (face, 0);
   CHECK_SYMBOL (attr, 1);
 
   face = resolve_face_name (face);
 
+  /* If FRAME is 0, change face on all frames, and change the
+     default for new frames.  */
+  if (INTEGERP (frame) && XINT (frame) == 0)
+    {
+      Lisp_Object tail;
+      Finternal_set_lisp_face_attribute (face, attr, value, Qt);
+      FOR_EACH_FRAME (tail, frame)
+       Finternal_set_lisp_face_attribute (face, attr, value, frame);
+      return face;
+    }
+
   /* Set lface to the Lisp attribute vector of FACE.  */
   if (EQ (frame, Qt))
     lface = lface_from_face_name (NULL, face, 1);
@@ -3416,10 +3807,10 @@ frame.")
     {
       if (NILP (frame))
        frame = selected_frame;
-      
+
       CHECK_LIVE_FRAME (frame, 3);
       lface = lface_from_face_name (XFRAME (frame), face, 0);
-      
+
       /* If a frame-local face doesn't exist yet, create one.  */
       if (NILP (lface))
        lface = Finternal_make_lisp_face (face, frame);
@@ -3441,10 +3832,16 @@ frame.")
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_NUMBER (value, 3);
-         if (XINT (value) <= 0)
+         Lisp_Object 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, 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;
@@ -3483,7 +3880,7 @@ frame.")
            || (STRINGP (value)
                && XSTRING (value)->size == 0))
          signal_error ("Invalid face underline", value);
-      
+
       old_value = LFACE_UNDERLINE (lface);
       LFACE_UNDERLINE (lface) = value;
     }
@@ -3497,7 +3894,7 @@ frame.")
            || (STRINGP (value)
                && XSTRING (value)->size == 0))
          signal_error ("Invalid face overline", value);
-      
+
       old_value = LFACE_OVERLINE (lface);
       LFACE_OVERLINE (lface) = value;
     }
@@ -3511,14 +3908,14 @@ frame.")
            || (STRINGP (value)
                && XSTRING (value)->size == 0))
          signal_error ("Invalid face strike-through", value);
-      
+
       old_value = LFACE_STRIKE_THROUGH (lface);
       LFACE_STRIKE_THROUGH (lface) = value;
     }
   else if (EQ (attr, QCbox))
     {
       int valid_p;
-      
+
       /* Allow t meaning a simple box of width 1 in foreground color
          of the face.  */
       if (EQ (value, Qt))
@@ -3529,13 +3926,13 @@ frame.")
       else if (NILP (value))
        valid_p = 1;
       else if (INTEGERP (value))
-       valid_p = XINT (value) > 0;
+       valid_p = XINT (value) != 0;
       else if (STRINGP (value))
        valid_p = XSTRING (value)->size > 0;
       else if (CONSP (value))
        {
          Lisp_Object tem;
-         
+
          tem = value;
          while (CONSP (tem))
            {
@@ -3547,10 +3944,10 @@ frame.")
                break;
              v = XCAR (tem);
              tem = XCDR (tem);
-             
+
              if (EQ (k, QCline_width))
                {
-                 if (!INTEGERP (v) || XINT (v) <= 0)
+                 if (!INTEGERP (v) || XINT (v) == 0)
                    break;
                }
              else if (EQ (k, QCcolor))
@@ -3574,7 +3971,7 @@ frame.")
 
       if (!valid_p)
        signal_error ("Invalid face box", value);
-      
+
       old_value = LFACE_BOX (lface);
       LFACE_BOX (lface) = value;
     }
@@ -3654,7 +4051,7 @@ frame.")
        f = SELECTED_FRAME ();
       else
        f = check_x_frame (frame);
-      
+
       /* 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);
@@ -3667,6 +4064,20 @@ frame.")
       font_attr_p = 1;
 #endif /* HAVE_WINDOW_SYSTEM */
     }
+  else if (EQ (attr, QCinherit))
+    {
+      Lisp_Object tail;
+      if (SYMBOLP (value))
+       tail = Qnil;
+      else
+       for (tail = value; CONSP (tail); tail = XCDR (tail))
+         if (!SYMBOLP (XCAR (tail)))
+           break;
+      if (NILP (tail))
+       LFACE_INHERIT (lface) = value;
+      else
+       signal_error ("Invalid face inheritance", value);
+    }
   else if (EQ (attr, QCbold))
     {
       old_value = LFACE_WEIGHT (lface);
@@ -3703,28 +4114,31 @@ frame.")
       ++windows_or_buffers_changed;
     }
 
-#ifdef HAVE_WINDOW_SYSTEM
-
-  if (!EQ (frame, Qt)
-      && !UNSPECIFIEDP (value)
+  if (!UNSPECIFIEDP (value)
       && NILP (Fequal (old_value, value)))
     {
       Lisp_Object param;
 
       param = Qnil;
-      
+
       if (EQ (face, Qdefault))
        {
+#ifdef HAVE_WINDOW_SYSTEM
          /* Changed font-related attributes of the `default' face are
             reflected in changed `font' frame parameters. */
-         if ((font_related_attr_p || font_attr_p)
+         if (FRAMEP (frame)
+             && (font_related_attr_p || font_attr_p)
              && lface_fully_specified_p (XVECTOR (lface)->contents))
            set_font_frame_param (frame, lface);
-         else if (EQ (attr, QCforeground))
+         else
+#endif /* HAVE_WINDOW_SYSTEM */
+
+         if (EQ (attr, QCforeground))
            param = Qforeground_color;
          else if (EQ (attr, QCbackground))
            param = Qbackground_color;
        }
+#ifdef HAVE_WINDOW_SYSTEM
 #ifndef WINDOWSNT
       else if (EQ (face, Qscroll_bar))
        {
@@ -3735,7 +4149,7 @@ frame.")
          else if (EQ (attr, QCbackground))
            param = Qscroll_bar_background;
        }
-#endif
+#endif /* not WINDOWSNT */
       else if (EQ (face, Qborder))
        {
          /* Changing background color of `border' sets frame parameter
@@ -3757,13 +4171,41 @@ frame.")
          if (EQ (attr, QCbackground))
            param = Qmouse_color;
        }
+#endif /* HAVE_WINDOW_SYSTEM */
+      else if (EQ (face, Qmenu))
+       {
+         /* Indicate that we have to update the menu bar when
+            realizing faces on FRAME.  FRAME t change the
+            default for new frames.  We do this by setting
+            setting the flag in new face caches   */
+         if (FRAMEP (frame))
+           {
+             struct frame *f = XFRAME (frame);
+             if (FRAME_FACE_CACHE (f) == NULL)
+               FRAME_FACE_CACHE (f) = make_face_cache (f);
+             FRAME_FACE_CACHE (f)->menu_face_changed_p = 1;
+           }
+         else
+           menu_face_changed_default = 1;
+       }
 
       if (!NILP (param))
-       Fmodify_frame_parameters (frame, Fcons (Fcons (param, value), Qnil));
+       if (EQ (frame, Qt))
+         /* Update `default-frame-alist', which is used for new frames.  */
+         {
+           store_in_alist (&Vdefault_frame_alist, param, value);
+         }
+       else
+         /* Update the current frame's parameters.  */
+         {
+           Lisp_Object cons;
+           cons = XCAR (Vparam_value_alist);
+           XCAR (cons) = param;
+           XCDR (cons) = value;
+           Fmodify_frame_parameters (frame, Vparam_value_alist);
+         }
     }
 
-#endif /* HAVE_WINDOW_SYSTEM */
-  
   return face;
 }
 
@@ -3781,23 +4223,28 @@ set_font_frame_param (frame, lface)
      Lisp_Object frame, lface;
 {
   struct frame *f = XFRAME (frame);
-  Lisp_Object font_name;
-  char *font;
 
-  if (STRINGP (LFACE_FONT (lface)))
-    font_name = LFACE_FONT (lface);
-  else
+  if (FRAME_WINDOW_P (f))
     {
-      /* 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, -1, 0);
-      if (!font)
-       error ("No font matches the specified attribute");
-      font_name = build_string (font);
-      xfree (font);
+      Lisp_Object font_name;
+      char *font;
+      
+      if (STRINGP (LFACE_FONT (lface)))
+       font_name = LFACE_FONT (lface);
+      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, -1, 0);
+         if (!font)
+           error ("No font matches the specified attribute");
+         font_name = build_string (font);
+         xfree (font);
+       }
+  
+      Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font_name), Qnil));
     }
-  store_frame_param (f, Qfont, font_name);
 }
 
 
@@ -3816,7 +4263,7 @@ update_face_from_frame_parameter (f, param, new_value)
      face-set-after-frame-defaults.  */
   if (NILP (f->face_alist))
     return;
-  
+
   if (EQ (param, Qforeground_color))
     {
       lface = lface_from_face_name (f, Qdefault, 1);
@@ -3833,7 +4280,7 @@ update_face_from_frame_parameter (f, param, new_value)
         frame-update-face-colors to do that.  */
       XSETFRAME (frame, f);
       call1 (Qframe_update_face_colors, frame);
-      
+
       lface = lface_from_face_name (f, Qdefault, 1);
       LFACE_BACKGROUND (lface) = (STRINGP (new_value)
                                  ? new_value : Qunspecified);
@@ -3871,6 +4318,7 @@ DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
 {
   Lisp_Object value = Qnil;
 #ifndef WINDOWSNT
+#ifndef macintosh
   CHECK_STRING (resource, 0);
   CHECK_STRING (class, 1);
   CHECK_LIVE_FRAME (frame, 2);
@@ -3878,7 +4326,8 @@ DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
   value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
                                  resource, class, Qnil, Qnil);
   UNBLOCK_INPUT;
-#endif
+#endif /* not macintosh */
+#endif /* not WINDOWSNT */
   return value;
 }
 
@@ -3887,7 +4336,7 @@ DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
    If VALUE is "on" or "true", return t.  If VALUE is "off" or
    "false", return nil.  Otherwise, if SIGNAL_P is non-zero, signal an
    error; if SIGNAL_P is zero, return 0.  */
-   
+
 static Lisp_Object
 face_boolean_x_resource_value (value, signal_p)
      Lisp_Object value;
@@ -3896,7 +4345,7 @@ face_boolean_x_resource_value (value, signal_p)
   Lisp_Object result = make_number (0);
 
   xassert (STRINGP (value));
-  
+
   if (xstricmp (XSTRING (value)->data, "on") == 0
       || xstricmp (XSTRING (value)->data, "true") == 0)
     result = Qt;
@@ -3957,235 +4406,105 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
 #endif /* HAVE_WINDOW_SYSTEM */
 
 \f
-#ifdef HAVE_X_WINDOWS
 /***********************************************************************
                              Menu face
  ***********************************************************************/
 
-#ifdef USE_X_TOOLKIT
+#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
 
-/* Structure used to pass X resources to functions called via
-   XtApplyToWidgets.  */
+/* Make menus on frame F appear as specified by the `menu' face.  */
 
-struct x_resources
+static void
+x_update_menu_appearance (f)
+     struct frame *f;
 {
-  Arg *av;
-  int ac;
-};
-
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  XrmDatabase rdb;
 
+  if (dpyinfo
+      && (rdb = XrmGetDatabase (FRAME_X_DISPLAY (f)),
+         rdb != NULL))
+    {
+      char line[512];
+      Lisp_Object lface = lface_from_face_name (f, Qmenu, 1);
+      struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
+      char *myname = XSTRING (Vx_resource_name)->data;
+      int changed_p = 0;
 #ifdef USE_MOTIF
+      const char *popup_path = "popup_menu";
+#else
+      const char *popup_path = "menu.popup";
+#endif
+      
+      if (STRINGP (LFACE_FOREGROUND (lface)))
+       {
+         sprintf (line, "%s.%s*foreground: %s",
+                  myname, popup_path,
+                  XSTRING (LFACE_FOREGROUND (lface))->data);
+         XrmPutLineResource (&rdb, line);
+         sprintf (line, "%s.pane.menubar*foreground: %s",
+                  myname, XSTRING (LFACE_FOREGROUND (lface))->data);
+         XrmPutLineResource (&rdb, line);
+         changed_p = 1;
+       }
 
-static void xm_apply_resources P_ ((Widget, XtPointer));
-static void xm_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
-
-
-/* Set widget W's X resources from P which points to an x_resources
-   structure.  If W is a cascade button, apply resources to W's
-   submenu.  */
+      if (STRINGP (LFACE_BACKGROUND (lface)))
+       {
+         sprintf (line, "%s.%s*background: %s",
+                  myname, popup_path,
+                  XSTRING (LFACE_BACKGROUND (lface))->data);
+         XrmPutLineResource (&rdb, line);
+         sprintf (line, "%s.pane.menubar*background: %s",
+                  myname, XSTRING (LFACE_BACKGROUND (lface))->data);
+         XrmPutLineResource (&rdb, line);
+         changed_p = 1;
+       }
+         
+      if (face->font_name
+         && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
+             || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+             || !UNSPECIFIEDP (LFACE_AVGWIDTH (lface))
+             || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
+             || !UNSPECIFIEDP (LFACE_SLANT (lface))
+             || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
+       {
+#ifdef USE_MOTIF
+         const char *suffix = "List";
+#else
+         const char *suffix = "";
+#endif
+         sprintf (line, "%s.pane.menubar*font%s: %s",
+                  myname, suffix, face->font_name);
+         XrmPutLineResource (&rdb, line);
+         sprintf (line, "%s.%s*font%s: %s",
+                  myname, popup_path, suffix, face->font_name);
+         XrmPutLineResource (&rdb, line);
+         changed_p = 1;
+       }
 
-static void
-xm_apply_resources (w, p)
-     Widget w;
-     XtPointer p;
-{
-  Widget submenu = 0;
-  struct x_resources *res = (struct x_resources *) p;
-  
-  XtSetValues (w, res->av, res->ac);
-  XtVaGetValues (w, XmNsubMenuId, &submenu, NULL);
-  if (submenu)
-    {
-      XtSetValues (submenu, res->av, res->ac);
-      XtApplyToWidgets (submenu, xm_apply_resources, p);
+      if (changed_p && f->output_data.x->menubar_widget)
+       free_frame_menubar (f);
     }
 }
 
+#endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
 
-/* Set X resources of menu-widget WIDGET on frame F from face `menu'.
-   This is the LessTif/Motif version.  As of LessTif 0.88 it has the
-   following problems:
 
-   1. Setting the XmNfontList resource leads to an infinite loop
-   somewhere in LessTif.  */
 
-static void
-xm_set_menu_resources_from_menu_face (f, widget)
-     struct frame *f;
-     Widget widget;
+DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute,
+       Sinternal_get_lisp_face_attribute,
+       2, 3, 0,
+  "Return face attribute KEYWORD of face SYMBOL.\n\
+If SYMBOL does not name a valid Lisp face or KEYWORD isn't a valid\n\
+face attribute name, signal an error.\n\
+If the optional argument FRAME is given, report on face FACE in that\n\
+frame.  If FRAME is t, report on the defaults for face FACE (for new\n\
+frames).  If FRAME is omitted or nil, use the selected frame.")
+  (symbol, keyword, frame)
+     Lisp_Object symbol, keyword, frame;
 {
-  struct face *face;
-  Lisp_Object lface;
-  Arg av[3];
-  int ac = 0;
-  XmFontList fl = 0;
+  Lisp_Object lface, value = Qnil;
 
-  lface = lface_from_face_name (f, Qmenu, 1);
-  face = FACE_FROM_ID (f, MENU_FACE_ID);
-
-  if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
-    {
-      XtSetArg (av[ac], XmNforeground, face->foreground);
-      ++ac;
-    }
-
-  if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
-    {
-      XtSetArg (av[ac], XmNbackground, face->background);
-      ++ac;
-    }
-
-  /* If any font-related attribute of `menu' is set, set the font.  */
-  if (face->font
-      && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
-         || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
-         || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
-         || !UNSPECIFIEDP (LFACE_SLANT (lface))
-         || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
-    {
-#if 0 /* Setting the font leads to an infinite loop somewhere
-        in LessTif during geometry computation.  */
-      XmFontListEntry fe;
-      fe = XmFontListEntryCreate ("menu_font", XmFONT_IS_FONT, face->font);
-      fl = XmFontListAppendEntry (NULL, fe);
-      XtSetArg (av[ac], XmNfontList, fl);
-      ++ac;
-#endif
-    }
-
-  xassert (ac <= sizeof av / sizeof *av);
-  
-  if (ac)
-    {
-      struct x_resources res;
-      
-      XtSetValues (widget, av, ac);
-      res.av = av, res.ac = ac;
-      XtApplyToWidgets (widget, xm_apply_resources, &res);
-      if (fl)
-       XmFontListFree (fl);
-    }
-}
-
-
-#endif /* USE_MOTIF */
-
-#ifdef USE_LUCID
-
-static void xl_apply_resources P_ ((Widget, XtPointer));
-static void xl_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
-
-
-/* Set widget W's resources from P which points to an x_resources
-   structure.  */
-
-static void
-xl_apply_resources (widget, p)
-     Widget widget;
-     XtPointer p;
-{
-  struct x_resources *res = (struct x_resources *) p;
-  XtSetValues (widget, res->av, res->ac);
-}
-
-
-/* On frame F, set X resources of menu-widget WIDGET from face `menu'.
-   This is the Lucid version.  */
-
-static void
-xl_set_menu_resources_from_menu_face (f, widget)
-     struct frame *f;
-     Widget widget;
-{
-  struct face *face;
-  Lisp_Object lface;
-  Arg av[3];
-  int ac = 0;
-
-  lface = lface_from_face_name (f, Qmenu, 1);
-  face = FACE_FROM_ID (f, MENU_FACE_ID);
-
-  if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
-    {
-      XtSetArg (av[ac], XtNforeground, face->foreground);
-      ++ac;
-    }
-
-  if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
-    {
-      XtSetArg (av[ac], XtNbackground, face->background);
-      ++ac;
-    }
-
-  if (face->font
-      && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
-         || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
-         || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
-         || !UNSPECIFIEDP (LFACE_SLANT (lface))
-         || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
-    {
-      XtSetArg (av[ac], XtNfont, face->font);
-      ++ac;
-    }
-
-  if (ac)
-    {
-      struct x_resources res;
-      
-      XtSetValues (widget, av, ac);
-
-      /* We must do children here in case we're handling a pop-up menu
-        in which case WIDGET is a popup shell.  XtApplyToWidgets
-        is a function from lwlib.  */
-      res.av = av, res.ac = ac;
-      XtApplyToWidgets (widget, xl_apply_resources, &res);
-    }
-}
-
-#endif /* USE_LUCID */
-
-
-/* On frame F, set X resources of menu-widget WIDGET from face `menu'.  */
-
-void
-x_set_menu_resources_from_menu_face (f, widget)
-     struct frame *f;
-     Widget widget;
-{
-  /* Realized faces may have been removed on frame F, e.g. because of
-     face attribute changes.  Recompute them, if necessary, since we
-     will need the `menu' face.  */
-  if (f->face_cache->used == 0)
-    recompute_basic_faces (f);
-  
-#ifdef USE_LUCID
-  xl_set_menu_resources_from_menu_face (f, widget);
-#endif
-#ifdef USE_MOTIF
-  xm_set_menu_resources_from_menu_face (f, widget);
-#endif
-}
-
-#endif /* USE_X_TOOLKIT */
-
-#endif /* HAVE_X_WINDOWS */
-
-
-
-DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute,
-       Sinternal_get_lisp_face_attribute,
-       2, 3, 0,
-  "Return face attribute KEYWORD of face SYMBOL.\n\
-If SYMBOL does not name a valid Lisp face or KEYWORD isn't a valid\n\
-face attribute name, signal an error.\n\
-If the optional argument FRAME is given, report on face FACE in that\n\
-frame.  If FRAME is t, report on the defaults for face FACE (for new\n\
-frames).  If FRAME is omitted or nil, use the selected frame.")
-  (symbol, keyword, frame)
-     Lisp_Object symbol, keyword, frame;
-{
-  Lisp_Object lface, value = Qnil;
-  
   CHECK_SYMBOL (symbol, 0);
   CHECK_SYMBOL (keyword, 1);
 
@@ -4226,6 +4545,8 @@ frames).  If FRAME is omitted or nil, use the selected frame.")
     value = LFACE_STIPPLE (lface);
   else if (EQ (keyword, QCwidth))
     value = LFACE_SWIDTH (lface);
+  else if (EQ (keyword, QCinherit))
+    value = LFACE_INHERIT (lface);
   else if (EQ (keyword, QCfont))
     value = LFACE_FONT (lface);
   else
@@ -4244,9 +4565,9 @@ Value is nil if ATTR doesn't have a discrete set of valid values.")
      Lisp_Object attr;
 {
   Lisp_Object result = Qnil;
-  
+
   CHECK_SYMBOL (attr, 0);
-  
+
   if (EQ (attr, QCweight)
       || EQ (attr, QCslant)
       || EQ (attr, QCwidth))
@@ -4254,7 +4575,7 @@ Value is nil if ATTR doesn't have a discrete set of valid values.")
       /* 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))
@@ -4286,23 +4607,36 @@ Value is nil if ATTR doesn't have a discrete set of valid values.")
 
   return result;
 }
-  
+
 
 DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
-       Sinternal_merge_in_global_face, 2, 2, 0, 
-  "Add attributes from frame-default definition of FACE to FACE on FRAME.")
+       Sinternal_merge_in_global_face, 2, 2, 0,
+  "Add attributes from frame-default definition of FACE to FACE on FRAME.\n\
+Default face attributes override any local face attributes.")
   (face, frame)
      Lisp_Object face, frame;
 {
-  Lisp_Object global_lface, local_lface;
+  int i;
+  Lisp_Object global_lface, local_lface, *gvec, *lvec;
+
   CHECK_LIVE_FRAME (frame, 1);
   global_lface = lface_from_face_name (NULL, face, 1);
   local_lface = lface_from_face_name (XFRAME (frame), face, 0);
   if (NILP (local_lface))
     local_lface = Finternal_make_lisp_face (face, frame);
-  merge_face_vectors (XVECTOR (global_lface)->contents,
-                     XVECTOR (local_lface)->contents);
-  return face;
+
+  /* Make every specified global attribute override the local one.
+     BEWARE!! This is only used from `face-set-after-frame-default' where
+     the local frame is defined from default specs in `face-defface-spec'
+     and those should be overridden by global settings.  Hence the strange
+     "global before local" priority.  */
+  lvec = XVECTOR (local_lface)->contents;
+  gvec = XVECTOR (global_lface)->contents;
+  for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
+    if (! UNSPECIFIEDP (gvec[i]))
+      lvec[i] = gvec[i];
+
+  return Qnil;
 }
 
 
@@ -4311,7 +4645,7 @@ DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
    return fonts with the same size as the font of a face.  This is
    done in fontset.el.  */
 
-DEFUN ("face-font", Fface_font, Sface_font, 1, 2, 0, 
+DEFUN ("face-font", Fface_font, Sface_font, 1, 2, 0,
   "Return the font name of face FACE, or nil if it is unspecified.\n\
 If the optional argument FRAME is given, report on face FACE in that frame.\n\
 If FRAME is t, report on the defaults for face FACE (for new frames).\n\
@@ -4329,11 +4663,11 @@ If FRAME is omitted or nil, use the selected frame.")
       if (!UNSPECIFIEDP (LFACE_WEIGHT (lface))
          && !EQ (LFACE_WEIGHT (lface), Qnormal))
        result = Fcons (Qbold, result);
-      
+
       if (!NILP (LFACE_SLANT (lface))
          && !EQ (LFACE_SLANT (lface), Qnormal))
        result = Fcons (Qitalic, result);
-      
+
       return result;
     }
   else
@@ -4341,7 +4675,7 @@ If FRAME is omitted or nil, use the selected frame.")
       struct frame *f = frame_or_selected_frame (frame, 1);
       int face_id = lookup_named_face (f, face, 0);
       struct face *face = FACE_FROM_ID (f, face_id);
-      return build_string (face->font_name);
+      return face ? build_string (face->font_name) : Qnil;
     }
 }
 
@@ -4372,23 +4706,24 @@ lface_equal_p (v1, v2)
          switch (XTYPE (a))
            {
            case Lisp_String:
-             equal_p = (XSTRING (a)->size == XSTRING (b)->size
+             equal_p = ((STRING_BYTES (XSTRING (a))
+                         == STRING_BYTES (XSTRING (b)))
                         && bcmp (XSTRING (a)->data, XSTRING (b)->data,
-                                 XSTRING (a)->size) == 0);
+                                 STRING_BYTES (XSTRING (a))) == 0);
              break;
-         
+
            case Lisp_Int:
            case Lisp_Symbol:
              equal_p = 0;
              break;
-         
+
            default:
              equal_p = !NILP (Fequal (a, b));
              break;
            }
        }
     }
-         
+
   return equal_p;
 }
 
@@ -4405,7 +4740,7 @@ If FRAME is omitted or nil, use the selected frame.")
   int equal_p;
   struct frame *f;
   Lisp_Object lface1, lface2;
-  
+
   if (EQ (frame, Qt))
     f = NULL;
   else
@@ -4422,7 +4757,7 @@ If FRAME is omitted or nil, use the selected frame.")
   return equal_p ? Qt : Qnil;
 }
 
-  
+
 DEFUN ("internal-lisp-face-empty-p", Finternal_lisp_face_empty_p,
        Sinternal_lisp_face_empty_p, 1, 2, 0,
   "True if FACE has no attribute specified.\n\
@@ -4440,22 +4775,22 @@ If FRAME is omitted or nil, use the selected frame.")
     frame = selected_frame;
   CHECK_LIVE_FRAME (frame, 0);
   f = XFRAME (frame);
-  
+
   if (EQ (frame, Qt))
     lface = lface_from_face_name (NULL, face, 1);
   else
     lface = lface_from_face_name (f, face, 1);
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-    if (!UNSPECIFIEDP (XVECTOR (lface)->contents[i]))
+    if (!UNSPECIFIEDP (AREF (lface, i)))
       break;
-  
+
   return i == LFACE_VECTOR_SIZE ? Qt : Qnil;
 }
 
 
 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist,
-       0, 1, 0, 
+       0, 1, 0,
   "Return an alist of frame-local faces defined on FRAME.\n\
 For internal use only.")
   (frame)
@@ -4511,9 +4846,9 @@ lface_same_font_attributes_p (lface1, lface2)
           && lface_fully_specified_p (lface2));
   return (xstricmp (XSTRING (lface1[LFACE_FAMILY_INDEX])->data,
                    XSTRING (lface2[LFACE_FAMILY_INDEX])->data) == 0
-         && (XFASTINT (lface1[LFACE_HEIGHT_INDEX])
-             == XFASTINT (lface2[LFACE_HEIGHT_INDEX]))
+         && 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])
@@ -4565,7 +4900,7 @@ free_realized_face (f, face)
              x_free_gc (f, face->gc);
              face->gc = 0;
            }
-         
+
          free_face_colors (f, face);
          x_destroy_bitmap (f, face->stipple);
        }
@@ -4587,7 +4922,7 @@ prepare_face_for_display (f, face)
 {
 #ifdef HAVE_WINDOW_SYSTEM
   xassert (FRAME_WINDOW_P (f));
-  
+
   if (face->gc == 0)
     {
       XGCValues xgcv;
@@ -4606,6 +4941,9 @@ prepare_face_for_display (f, face)
 #endif
 #ifdef WINDOWSNT
          xgcv.font = face->font;
+#endif
+#ifdef macintosh
+         xgcv.font = face->font;
 #endif
          mask |= GCFont;
        }
@@ -4647,6 +4985,7 @@ make_face_cache (f)
   c->size = 50;
   c->faces_by_id = (struct face **) xmalloc (c->size * sizeof *c->faces_by_id);
   c->f = f;
+  c->menu_face_changed_p = menu_face_changed_default;
   return c;
 }
 
@@ -4701,7 +5040,7 @@ free_realized_faces (c)
          free_realized_face (f, c->faces_by_id[i]);
          c->faces_by_id[i] = NULL;
        }
-      
+
       c->used = 0;
       size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
       bzero (c->buckets, size);
@@ -4737,7 +5076,7 @@ free_realized_multibyte_face (f, fontset)
      while only some faces are freed, or when the frame's current
      matrix still references freed faces.  */
   BLOCK_INPUT;
-      
+
   for (i = 0; i < cache->used; i++)
     {
       face = cache->faces_by_id[i];
@@ -4749,7 +5088,7 @@ free_realized_multibyte_face (f, fontset)
          free_realized_face (f, face);
        }
     }
-  
+
   /* Must do a thorough redisplay the next time.  Mark current
      matrices as invalid because they will reference faces freed
      above.  This function is also called when a frame is destroyed.
@@ -4759,7 +5098,7 @@ free_realized_multibyte_face (f, fontset)
       clear_current_matrices (f);
       ++windows_or_buffers_changed;
     }
-  
+
   UNBLOCK_INPUT;
 }
 
@@ -4847,7 +5186,7 @@ cache_face (c, face, hash)
     if (c->faces_by_id[i] == NULL)
       break;
   face->id = i;
-  
+
   /* Maybe enlarge C->faces_by_id.  */
   if (i == c->used && c->used == c->size)
     {
@@ -4871,7 +5210,7 @@ cache_face (c, face, hash)
     xassert (n == 1);
   }
 #endif /* GLYPH_DEBUG */
-  
+
   c->faces_by_id[i] = face;
   if (i == c->used)
     ++c->used;
@@ -4886,15 +5225,15 @@ uncache_face (c, face)
      struct face *face;
 {
   int i = face->hash % FACE_CACHE_BUCKETS_SIZE;
-  
+
   if (face->prev)
     face->prev->next = face->next;
   else
     c->buckets[i] = face->next;
-  
+
   if (face->next)
     face->next->prev = face->prev;
-  
+
   c->faces_by_id[face->id] = NULL;
   if (face->id == c->used)
     --c->used;
@@ -4925,7 +5264,7 @@ lookup_face (f, attr, c, base_face)
   /* Look up ATTR in the face cache.  */
   hash = lface_hash (attr);
   i = hash % FACE_CACHE_BUCKETS_SIZE;
-  
+
   for (face = cache->buckets[i]; face; face = face->next)
     if (face->hash == hash
        && (!FRAME_WINDOW_P (f)
@@ -4950,13 +5289,15 @@ lookup_face (f, attr, c, base_face)
     xassert (FACE_SUITABLE_FOR_CHAR_P (face, c));
 #endif
 #endif /* GLYPH_DEBUG */
-  
+
   return face->id;
 }
 
 
 /* Return the face id of the realized face for named face SYMBOL on
-   frame F suitable for displaying character C.  */
+   frame F suitable for displaying character C.  Value is -1 if the
+   face couldn't be determined, which might happen if the default face
+   isn't realized and cannot be realized.  */
 
 int
 lookup_named_face (f, symbol, c)
@@ -4968,9 +5309,16 @@ lookup_named_face (f, symbol, c)
   Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
   struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
 
+  if (default_face == NULL)
+    {
+      if (!realize_basic_faces (f))
+       return -1;
+      default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+    }
+
   get_lface_attributes (f, symbol, symbol_attrs, 1);
   bcopy (default_face->lface, attrs, sizeof attrs);
-  merge_face_vectors (symbol_attrs, attrs);
+  merge_face_vectors (f, symbol_attrs, attrs, Qnil);
   return lookup_face (f, attrs, c, NULL);
 }
 
@@ -4984,7 +5332,7 @@ ascii_face_of_lisp_face (f, lface_id)
      int lface_id;
 {
   int face_id;
-  
+
   if (lface_id >= 0 && lface_id < lface_id_to_name_size)
     {
       Lisp_Object face_name = lface_id_to_name[lface_id];
@@ -5021,7 +5369,7 @@ smaller_face (f, face_id, steps)
   /* Try in increments of 1/2 pt.  */
   delta = steps < 0 ? 5 : -5;
   steps = abs (steps);
-  
+
   face = FACE_FROM_ID (f, face_id);
   bcopy (face->lface, attrs, sizeof attrs);
   pt = last_pt = XFASTINT (attrs[LFACE_HEIGHT_INDEX]);
@@ -5040,7 +5388,8 @@ smaller_face (f, face_id, steps)
       new_face = FACE_FROM_ID (f, new_face_id);
 
       /* If height changes, count that as one step.  */
-      if (FONT_HEIGHT (new_face->font) != last_height)
+      if ((delta < 0 && FONT_HEIGHT (new_face->font) < last_height)
+         || (delta > 0 && FONT_HEIGHT (new_face->font) > last_height))
        {
          --steps;
          last_height = FONT_HEIGHT (new_face->font);
@@ -5053,7 +5402,7 @@ smaller_face (f, face_id, steps)
 #else /* not HAVE_WINDOW_SYSTEM */
 
   return face_id;
-  
+
 #endif /* not HAVE_WINDOW_SYSTEM */
 }
 
@@ -5080,10 +5429,11 @@ face_with_height (f, face_id, height)
   attrs[LFACE_HEIGHT_INDEX] = make_number (height);
   face_id = lookup_face (f, attrs, 0, NULL);
 #endif /* HAVE_WINDOW_SYSTEM */
-  
+
   return face_id;
 }
 
+
 /* Return the face id of the realized face for named face SYMBOL on
    frame F suitable for displaying character C, and use attributes of
    the face FACE_ID for attributes that aren't completely specified by
@@ -5107,7 +5457,7 @@ lookup_derived_face (f, symbol, c, face_id)
 
   get_lface_attributes (f, symbol, symbol_attrs, 1);
   bcopy (default_face->lface, attrs, sizeof attrs);
-  merge_face_vectors (symbol_attrs, attrs);
+  merge_face_vectors (f, symbol_attrs, attrs, Qnil);
   return lookup_face (f, attrs, c, default_face);
 }
 
@@ -5132,8 +5482,8 @@ Value is ORDER.")
 {
   Lisp_Object list;
   int i;
-  int indices[4];
-  
+  int indices[DIM (font_sort_order)];
+
   CHECK_LIST (order, 0);
   bzero (indices, sizeof indices);
   i = 0;
@@ -5161,20 +5511,18 @@ Value is ORDER.")
       indices[i] = xlfd;
     }
 
-  if (!NILP (list)
-      || i != DIM (indices)
-      || indices[0] == 0
-      || indices[1] == 0
-      || indices[2] == 0
-      || indices[3] == 0)
+  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);
     }
-  
+
   return Qnil;
 }
 
@@ -5196,6 +5544,23 @@ be found.  Value is ALIST.")
 }
 
 
+DEFUN ("internal-set-alternative-font-registry-alist",
+       Finternal_set_alternative_font_registry_alist,
+       Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
+  "Define alternative font registries to try in face font selection.\n\
+ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.\n\
+Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can\n\
+be found.  Value is ALIST.")
+  (alist)
+     Lisp_Object alist;
+{
+  CHECK_LIST (alist, 0);
+  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
@@ -5220,20 +5585,25 @@ font_scalable_p (font)
 }
 
 
+/* 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.  */
+   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)
+better_font_p (values, font1, font2, compare_pt_p, avgwidth)
      int *values;
      struct font_name *font1, *font2;
-     int compare_pt_p;
+     int compare_pt_p, avgwidth;
 {
   int i;
-  
-  for (i = 0; i < 4; ++i)
+
+  for (i = 0; i < DIM (font_sort_order); ++i)
     {
       int xlfd_idx = font_sort_order[i];
 
@@ -5241,7 +5611,10 @@ better_font_p (values, font1, font2, compare_pt_p)
        {
          int delta1 = abs (values[i] - font1->numeric[xlfd_idx]);
          int delta2 = abs (values[i] - font2->numeric[xlfd_idx]);
-      
+
+         if (xlfd_idx == XLFD_POINT_SIZE
+             && abs (delta1 - delta2) < FONT_POINT_SIZE_QUANTUM)
+           continue;
          if (delta1 > delta2)
            return 0;
          else if (delta1 < delta2)
@@ -5258,29 +5631,41 @@ better_font_p (values, font1, font2, compare_pt_p)
            }
        }
     }
-  
-  return 0;
-}
 
+  if (avgwidth)
+    {
+      int delta1 = abs (avgwidth - font1->numeric[XLFD_AVGWIDTH]);
+      int delta2 = abs (avgwidth - font2->numeric[XLFD_AVGWIDTH]);
+      if (delta1 > delta2)
+       return 0;
+      else if (delta1 < delta2)
+       return 1;
+    }
+
+  return font1->registry_priority < font2->registry_priority;
+}
 
-#if SCALABLE_FONTS
 
 /* 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.  */
+   sort order.  AVGWIDTH, if non-zero, is an average width to compare
+   with.  */
 
 static int
-exact_face_match_p (specified, font)
+exact_face_match_p (specified, font, avgwidth)
      int *specified;
      struct font_name *font;
+     int avgwidth;
 {
   int i;
-  
-  for (i = 0; i < 4; ++i)
+
+  for (i = 0; i < DIM (font_sort_order); ++i)
     if (specified[i] != font->numeric[font_sort_order[i]])
       break;
 
-  return i == 4;
+  return (i == DIM (font_sort_order)
+         && (avgwidth <= 0
+             || avgwidth == font->numeric[XLFD_AVGWIDTH]));
 }
 
 
@@ -5305,24 +5690,24 @@ build_scalable_font_name (f, font, specified_pt)
   if (font->numeric[XLFD_RESY] != 0)
     {
       pt = resy / font->numeric[XLFD_RESY] * specified_pt + 0.5;
-      pixel_value = font->numeric[XLFD_RESY] / 720.0 * pt;
+      pixel_value = font->numeric[XLFD_RESY] / (PT_PER_INCH * 10.0) * pt;
     }
   else
     {
       pt = specified_pt;
-      pixel_value = resy / 720.0 * pt;
+      pixel_value = resy / (PT_PER_INCH * 10.0) * pt;
     }
-  
+
   /* Set point size of the font.  */
   sprintf (point_size, "%d", (int) pt);
   font->fields[XLFD_POINT_SIZE] = point_size;
   font->numeric[XLFD_POINT_SIZE] = pt;
-  
+
   /* 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)
@@ -5332,7 +5717,7 @@ build_scalable_font_name (f, font, specified_pt)
       font->fields[XLFD_RESY] = buffer;
       font->numeric[XLFD_RESY] = resy;
     }
-  
+
   if (strcmp (font->fields[XLFD_RESX], "0") == 0)
     {
       char buffer[20];
@@ -5351,48 +5736,50 @@ build_scalable_font_name (f, font, specified_pt)
    with input blocked.  */
 
 static int
-may_use_scalable_font_p (font, name)
-     struct font_name *font;
-     char *name;
+may_use_scalable_font_p (font)
+     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, name) >= 0)
+             && fast_c_string_match_ignore_case (regexp, font) >= 0)
            return 1;
        }
     }
-  
+
   return 0;
 }
 
-#endif /* SCALABLE_FONTS != 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.  Value is a font name which is allocated from
-   the heap.  FONTS is freed by this function.  */
+/* 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.  */
 
 static char *
-best_matching_font (f, attrs, fonts, nfonts)
+best_matching_font (f, attrs, fonts, nfonts, width_ratio)
      struct frame *f;
      Lisp_Object *attrs;
      struct font_name *fonts;
      int nfonts;
+     int width_ratio;
 {
   char *font_name;
   struct font_name *best;
-  int i, pt;
-  int specified[4];
-  int exact_p;
+  int i, pt = 0;
+  int specified[5];
+  int exact_p, avgwidth;
 
   if (nfonts == 0)
     return NULL;
@@ -5402,7 +5789,7 @@ best_matching_font (f, attrs, fonts, nfonts)
   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)
@@ -5415,11 +5802,12 @@ best_matching_font (f, attrs, fonts, nfonts)
        abort ();
     }
 
-#if SCALABLE_FONTS
+  avgwidth = (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
+             ? 0
+             : XFASTINT (attrs[LFACE_AVGWIDTH_INDEX]) * width_ratio);
 
-  /* Set to 1 */
   exact_p = 0;
-  
+
   /* Start with the first non-scalable font in the list.  */
   for (i = 0; i < nfonts; ++i)
     if (!font_scalable_p (fonts + i))
@@ -5429,18 +5817,18 @@ best_matching_font (f, attrs, fonts, nfonts)
   if (i < nfonts)
     {
       best = fonts + i;
-      
+
       for (i = 1; i < nfonts; ++i)
        if (!font_scalable_p (fonts + i)
-           && better_font_p (specified, fonts + i, best, 1))
+           && better_font_p (specified, fonts + i, best, 1, avgwidth))
          {
            best = fonts + i;
 
-           exact_p = exact_face_match_p (specified, best);
+           exact_p = exact_face_match_p (specified, best, avgwidth);
            if (exact_p)
              break;
          }
-      
+
     }
   else
     best = NULL;
@@ -5452,7 +5840,7 @@ best_matching_font (f, attrs, fonts, nfonts)
       /* A scalable font is better if
 
         1. its weight, slant, swidth attributes are better, or.
-        
+
         2. the best non-scalable font doesn't have the required
         point size, and the scalable fonts weight, slant, swidth
         isn't worse.  */
@@ -5463,14 +5851,14 @@ best_matching_font (f, attrs, fonts, nfonts)
        non_scalable_has_exact_height_p = 1;
       else
        non_scalable_has_exact_height_p = 0;
-      
+
       for (i = 0; i < nfonts; ++i)
        if (font_scalable_p (fonts + i))
          {
            if (best == NULL
-               || better_font_p (specified, fonts + i, best, 0)
+               || better_font_p (specified, fonts + i, best, 0, 0)
                || (!non_scalable_has_exact_height_p
-                   && !better_font_p (specified, best, fonts + i, 0)))
+                   && !better_font_p (specified, best, fonts + i, 0, 0)))
              best = fonts + i;
          }
     }
@@ -5479,80 +5867,107 @@ best_matching_font (f, attrs, fonts, nfonts)
     font_name = build_scalable_font_name (f, best, pt);
   else
     font_name = build_font_name (best);
-  
-#else /* !SCALABLE_FONTS */
-  
-  /* Find the best non-scalable font.  */
-  best = fonts;
-  
-  for (i = 1; i < nfonts; ++i)
-    {
-      xassert (!font_scalable_p (fonts + i));
-      if (better_font_p (specified, fonts + i, best, 1))
-       best = fonts + i;
-    }
-  
-  font_name = build_font_name (best);
-
-#endif /* !SCALABLE_FONTS */
 
   /* Free font_name structures.  */
   free_font_names (fonts, nfonts);
-  
+
   return font_name;
 }
 
 
-/* Try to get a list of fonts on frame F with font family FAMILY and
-   registry/encoding REGISTRY.  Return in *FONTS a pointer to a vector
-   of font_name structures for the fonts matched.  Value is the number
-   of fonts found.  */
+/* 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_font_list (f, attrs, pattern, family, registry, fonts)
+try_alternative_families (f, family, registry, fonts)
      struct frame *f;
-     Lisp_Object *attrs;
-     Lisp_Object pattern, family, registry;
+     Lisp_Object family, registry;
      struct font_name **fonts;
 {
-  int nfonts;
+  Lisp_Object alter;
+  int nfonts = 0;
 
-  if (NILP (family) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
-    family = attrs[LFACE_FAMILY_INDEX];
-  
-  nfonts = font_list (f, pattern, family, registry, fonts);
-  
-  if (nfonts == 0 && !NILP (family))
+  nfonts = font_list (f, Qnil, family, registry, fonts);
+  if (nfonts == 0)
     {
-      Lisp_Object alter;
-         
-      /* Try alternative font families from
-        Vface_alternative_font_family_alist.  */
+      /* 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 font family of the default face or "fixed".  */
-      if (nfonts == 0)
        {
-         struct face *dflt = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-         if (dflt)
-           family = dflt->lface[LFACE_FAMILY_INDEX];
-         else
-           family = build_string ("fixed");
-         nfonts = font_list (f, Qnil, family, registry, fonts);
+         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 scalable fonts before giving up.  */
+      if (nfonts == 0 && NILP (Vscalable_fonts_allowed))
+       {
+         int count = BINDING_STACK_SIZE ();
+         specbind (Qscalable_fonts_allowed, Qt);
+         nfonts = try_alternative_families (f, family, registry, fonts);
+         unbind_to (count, Qnil);
        }
-         
-      /* Try any family with the given registry.  */
-      if (nfonts == 0)
-       nfonts = font_list (f, Qnil, Qnil, registry, fonts);
     }
+  return nfonts;
+}
+
+
+/* Get a list of matching fonts on frame F.
+
+   FAMILY, if a string, specifies a font family derived from the fontset.
+   It is only used if the face does not specify any family in ATTRS or
+   if we cannot find any font of the face's family.
+
+   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_font_list (f, attrs, family, registry, fonts)
+     struct frame *f;
+     Lisp_Object *attrs;
+     Lisp_Object family, registry;
+     struct font_name **fonts;
+{
+  int nfonts = 0;
+  Lisp_Object face_family = attrs[LFACE_FAMILY_INDEX];
+
+  if (STRINGP (face_family))
+    nfonts = try_alternative_families (f, face_family, registry, fonts);
+
+  if (nfonts == 0 && !NILP (family))
+    nfonts = try_alternative_families (f, family, registry, fonts);
+
+  /* Try font family of the default face or "fixed".  */
+  if (nfonts == 0)
+    {
+      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 = font_list (f, Qnil, family, registry, fonts);
+    }
+      
+  /* Try any family with the given registry.  */
+  if (nfonts == 0)
+    nfonts = font_list (f, Qnil, Qnil, registry, fonts);
 
   return nfonts;
 }
@@ -5567,8 +5982,7 @@ face_fontset (attrs)
      Lisp_Object *attrs;
 {
   Lisp_Object name;
-  int fontset;
-  
+
   name = attrs[LFACE_FONT_INDEX];
   if (!STRINGP (name))
     return -1;
@@ -5594,8 +6008,8 @@ choose_face_font (f, attrs, fontset, c)
   Lisp_Object pattern;
   char *font_name = NULL;
   struct font_name *fonts;
-  int nfonts;
-  
+  int nfonts, width_ratio;
+
   /* Get (foundry and) family name and registry (and encoding) name of
      a font for C.  */
   pattern = fontset_font_pattern (f, fontset, c);
@@ -5604,22 +6018,18 @@ choose_face_font (f, attrs, fontset, c)
       xassert (!SINGLE_BYTE_CHAR_P (c));
       return NULL;
     }
+  
   /* If what we got is a name pattern, return it.  */
   if (STRINGP (pattern))
     return xstrdup (XSTRING (pattern)->data);
 
-  /* Family name may be specified both in ATTRS and car part of
-     PATTERN.  The former has higher priority if C is a single byte
-     character.  */
-  if (STRINGP (attrs[LFACE_FAMILY_INDEX])
-      && SINGLE_BYTE_CHAR_P (c))
-    XCAR (pattern) = Qnil;
-
-  /* Get a list of fonts matching that pattern and choose the 
+  /* 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, attrs, Qnil, XCAR (pattern), XCDR (pattern),
-                         &fonts);
-  font_name = best_matching_font (f, attrs, fonts, nfonts);
+  nfonts = try_font_list (f, attrs, XCAR (pattern), XCDR (pattern), &fonts);
+  width_ratio = (SINGLE_BYTE_CHAR_P (c)
+                ? 1
+                : CHARSET_WIDTH (CHAR_CHARSET (c)));
+  font_name = best_matching_font (f, attrs, fonts, nfonts, width_ratio);
   return font_name;
 }
 
@@ -5640,11 +6050,13 @@ realize_basic_faces (f)
      struct frame *f;
 {
   int success_p = 0;
+  int count = BINDING_STACK_SIZE ();
 
-  /* Block input there so that we won't be surprised by an X expose
-     event, for instance without having the faces set up.  */
+  /* Block input here so that we won't be surprised by an X expose
+     event, for instance, without having the faces set up.  */
   BLOCK_INPUT;
-  
+  specbind (Qscalable_fonts_allowed, Qt);
+
   if (realize_default_face (f))
     {
       realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
@@ -5656,9 +6068,20 @@ realize_basic_faces (f)
       realize_named_face (f, Qcursor, CURSOR_FACE_ID);
       realize_named_face (f, Qmouse, MOUSE_FACE_ID);
       realize_named_face (f, Qmenu, MENU_FACE_ID);
+
+      /* Reflect changes in the `menu' face in menu bars.  */
+      if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
+       {
+         FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
+#ifdef USE_X_TOOLKIT
+         x_update_menu_appearance (f);
+#endif
+       }
+      
       success_p = 1;
     }
 
+  unbind_to (count, Qnil);
   UNBLOCK_INPUT;
   return success_p;
 }
@@ -5677,7 +6100,6 @@ realize_default_face (f)
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   Lisp_Object frame_font;
   struct face *face;
-  int fontset;
 
   /* If the `default' face is not yet known, create it.  */
   lface = lface_from_face_name (f, Qdefault, 0);
@@ -5695,7 +6117,7 @@ realize_default_face (f)
       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, 0, 1);
+      set_lface_from_font_name (f, lface, frame_font, 1, 1);
     }
 #endif /* HAVE_WINDOW_SYSTEM */
 
@@ -5706,29 +6128,30 @@ realize_default_face (f)
       LFACE_HEIGHT (lface) = make_number (1);
       LFACE_WEIGHT (lface) = Qnormal;
       LFACE_SLANT (lface) = Qnormal;
+      LFACE_AVGWIDTH (lface) = Qunspecified;
     }
-      
+
   if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
     LFACE_UNDERLINE (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_OVERLINE (lface)))
     LFACE_OVERLINE (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_STRIKE_THROUGH (lface)))
     LFACE_STRIKE_THROUGH (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_BOX (lface)))
     LFACE_BOX (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_INVERSE (lface)))
     LFACE_INVERSE (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
     {
       /* This function is called so early that colors are not yet
         set in the frame parameter list.  */
       Lisp_Object color = Fassq (Qforeground_color, f->param_alist);
-      
+
       if (CONSP (color) && STRINGP (XCDR (color)))
        LFACE_FOREGROUND (lface) = XCDR (color);
       else if (FRAME_WINDOW_P (f))
@@ -5738,7 +6161,7 @@ realize_default_face (f)
       else
        abort ();
     }
-  
+
   if (UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
     {
       /* This function is called so early that colors are not yet
@@ -5753,7 +6176,7 @@ realize_default_face (f)
       else
        abort ();
     }
-  
+
   if (UNSPECIFIEDP (LFACE_STIPPLE (lface)))
     LFACE_STIPPLE (lface) = Qnil;
 
@@ -5797,7 +6220,7 @@ realize_named_face (f, symbol, id)
 
   /* Merge SYMBOL's face with the default face.  */
   get_lface_attributes (f, symbol, symbol_attrs, 1);
-  merge_face_vectors (symbol_attrs, attrs);
+  merge_face_vectors (f, symbol_attrs, attrs, Qnil);
 
   /* Realize the face.  */
   new_face = realize_face (c, attrs, 0, NULL, id);
@@ -5820,7 +6243,7 @@ realize_face (cache, attrs, c, base_face, former_face_id)
      int former_face_id;
 {
   struct face *face;
-  
+
   /* LFACE must be fully specified.  */
   xassert (cache != NULL);
   check_lface_attrs (attrs);
@@ -5891,11 +6314,11 @@ realize_x_face (cache, attrs, c, base_face)
       /* Don't try to free the colors copied bitwise from BASE_FACE.  */
       face->foreground_defaulted_p = 1;
       face->background_defaulted_p = 1;
-      face->underline_defaulted_p = 1; 
+      face->underline_defaulted_p = 1;
       face->overline_color_defaulted_p = 1;
       face->strike_through_color_defaulted_p = 1;
       face->box_color_defaulted_p = 1;
-      
+
       /* to force realize_face to load font */
       face->font = NULL;
       return face;
@@ -5925,18 +6348,33 @@ realize_x_face (cache, attrs, c, base_face)
   else
     {
       /* If the face attribute ATTRS specifies a fontset, use it as
-        the base of a new realized fontset.  Otherwise, use the
-        default fontset as the base.  The base determines registry
-        and encoding of a font.  It may also determine foundry and
-        family.  The other fields of font name pattern are
-        constructed from ATTRS.  */
-      face->fontset
-       = make_fontset_for_ascii_face (f, face_fontset (attrs));
+        the base of a new realized fontset.  Otherwise, use the same
+        base fontset as of the default face.  The base determines
+        registry and encoding of a font.  It may also determine
+        foundry and family.  The other fields of font name pattern
+        are constructed from ATTRS.  */
+      int fontset = face_fontset (attrs);
+
+      if ((fontset == -1) && default_face)
+       fontset = default_face->fontset;
+      face->fontset = make_fontset_for_ascii_face (f, fontset);
       face->font = NULL;       /* to force realize_face to load font */
+
+#ifdef macintosh
+      /* Load the font if it is specified in ATTRS.  This fixes
+         changing frame font on the Mac.  */
+      if (STRINGP (attrs[LFACE_FONT_INDEX]))
+        {
+          struct font_info *font_info =
+            FS_LOAD_FONT (f, 0, XSTRING (attrs[LFACE_FONT_INDEX])->data, -1);
+          if (font_info)
+            face->font = font_info->font;
+        }
+#endif
     }
 
   /* Load colors, and set remaining attributes.  */
-  
+
   load_face_colors (f, face, attrs);
 
   /* Set up box.  */
@@ -5954,9 +6392,9 @@ realize_x_face (cache, attrs, c, base_face)
     {
       /* Simple box of specified line width in foreground color of the
          face.  */
-      xassert (XINT (box) > 0);
+      xassert (XINT (box) != 0);
       face->box = FACE_SIMPLE_BOX;
-      face->box_line_width = XFASTINT (box);
+      face->box_line_width = XINT (box);
       face->box_color = face->foreground;
       face->box_color_defaulted_p = 1;
     }
@@ -5983,8 +6421,8 @@ realize_x_face (cache, attrs, c, base_face)
 
          if (EQ (keyword, QCline_width))
            {
-             if (INTEGERP (value) && XINT (value) > 0)
-               face->box_line_width = XFASTINT (value);
+             if (INTEGERP (value) && XINT (value) != 0)
+               face->box_line_width = XINT (value);
            }
          else if (EQ (keyword, QCcolor))
            {
@@ -6006,9 +6444,9 @@ realize_x_face (cache, attrs, c, base_face)
     }
 
   /* Text underline, overline, strike-through.  */
-  
+
   if (EQ (attrs[LFACE_UNDERLINE_INDEX], Qt))
-    { 
+    {
       /* Use default color (same as foreground color).  */
       face->underline_p = 1;
       face->underline_defaulted_p = 1;
@@ -6070,6 +6508,92 @@ realize_x_face (cache, attrs, c, base_face)
 }
 
 
+/* Map a specified color of face FACE on frame F to a tty color index.
+   IDX is either LFACE_FOREGROUND_INDEX or LFACE_BACKGROUND_INDEX, and
+   specifies which color to map.  Set *DEFAULTED to 1 if mapping to the
+   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;
+{
+  Lisp_Object frame, color, def;
+  int foreground_p = idx == LFACE_FOREGROUND_INDEX;
+  unsigned long default_pixel, default_other_pixel, pixel;
+
+  xassert (idx == LFACE_FOREGROUND_INDEX || idx == LFACE_BACKGROUND_INDEX);
+
+  if (foreground_p)
+    {
+      pixel = default_pixel = FACE_TTY_DEFAULT_FG_COLOR;
+      default_other_pixel = FACE_TTY_DEFAULT_BG_COLOR;
+    }
+  else
+    {
+      pixel = default_pixel = FACE_TTY_DEFAULT_BG_COLOR;
+      default_other_pixel = FACE_TTY_DEFAULT_FG_COLOR;
+    }
+  
+  XSETFRAME (frame, f);
+  color = face->lface[idx];
+  
+  if (STRINGP (color)
+      && XSTRING (color)->size
+      && CONSP (Vtty_defined_color_alist)
+      && (def = assq_no_quit (color, call1 (Qtty_color_alist, frame)),
+         CONSP (def)))
+    {
+      /* Associations in tty-defined-color-alist are of the form
+        (NAME INDEX R G B).  We need the INDEX part.  */
+      pixel = XINT (XCAR (XCDR (def)));
+    }
+
+  if (pixel == default_pixel && STRINGP (color))
+    {
+      pixel = load_color (f, face, color, idx);
+
+#if defined (MSDOS) || defined (WINDOWSNT)
+      /* If the foreground of the default face is the default color,
+        use the foreground color defined by the frame.  */
+#ifdef MSDOS
+      if (FRAME_MSDOS_P (f))
+       {
+#endif /* MSDOS */
+         if (pixel == default_pixel
+             || pixel == FACE_TTY_DEFAULT_COLOR)
+           {
+             if (foreground_p)
+               pixel = FRAME_FOREGROUND_PIXEL (f);
+             else
+               pixel = FRAME_BACKGROUND_PIXEL (f);
+             face->lface[idx] = tty_color_name (f, pixel);
+             *defaulted = 1;
+           }
+         else if (pixel == default_other_pixel)
+           {
+             if (foreground_p)
+               pixel = FRAME_BACKGROUND_PIXEL (f);
+             else
+               pixel = FRAME_FOREGROUND_PIXEL (f);
+             face->lface[idx] = tty_color_name (f, pixel);
+             *defaulted = 1;
+           }
+#ifdef MSDOS
+       }
+#endif
+#endif /* MSDOS or WINDOWSNT */
+    }
+
+  if (foreground_p)
+    face->foreground = pixel;
+  else
+    face->background = pixel;
+}
+
+
 /* Realize the fully-specified face with attributes ATTRS in face
    cache CACHE for character C.  Do it for TTY frame CACHE->f.  Value is a
    pointer to the newly created realized face.  */
@@ -6082,21 +6606,17 @@ realize_tty_face (cache, attrs, c)
 {
   struct face *face;
   int weight, slant;
-  Lisp_Object color;
-  Lisp_Object tty_defined_color_alist
-    = find_symbol_value (intern ("tty-defined-color-alist"));
-  Lisp_Object tty_color_alist = intern ("tty-color-alist");
-  Lisp_Object frame;
   int face_colors_defaulted = 0;
+  struct frame *f = cache->f;
 
   /* Frame must be a termcap frame.  */
   xassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
-  
+
   /* Allocate a new realized face.  */
   face = make_realized_face (attrs);
   face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
 
-  /* Map face attributes to TTY appearances.  We map slant to 
+  /* 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]);
@@ -6112,108 +6632,15 @@ realize_tty_face (cache, attrs, c)
     face->tty_reverse_p = 1;
 
   /* Map color names to color indices.  */
-  face->foreground = FACE_TTY_DEFAULT_FG_COLOR;
-  face->background = FACE_TTY_DEFAULT_BG_COLOR;
-
-  XSETFRAME (frame, cache->f);
-  color = attrs[LFACE_FOREGROUND_INDEX];
-  if (STRINGP (color)
-      && XSTRING (color)->size
-      && CONSP (tty_defined_color_alist)
-      && (color = Fassoc (color, call1 (tty_color_alist, frame)),
-         CONSP (color)))
-    /* Associations in tty-defined-color-alist are of the form
-       (NAME INDEX R G B).  We need the INDEX part.  */
-    face->foreground = XINT (XCAR (XCDR (color)));
-
-  if (face->foreground == FACE_TTY_DEFAULT_FG_COLOR
-      && STRINGP (attrs[LFACE_FOREGROUND_INDEX]))
-    {
-      face->foreground = load_color (cache->f, face,
-                                    attrs[LFACE_FOREGROUND_INDEX],
-                                    LFACE_FOREGROUND_INDEX);
-
-#if defined (MSDOS) || defined (WINDOWSNT)
-      /* If the foreground of the default face is the default color,
-        use the foreground color defined by the frame.  */
-#ifdef MSDOS
-      if (FRAME_MSDOS_P (cache->f))
-       {
-#endif /* MSDOS */
-
-         if (face->foreground == FACE_TTY_DEFAULT_FG_COLOR
-             || face->foreground == FACE_TTY_DEFAULT_COLOR)
-           {
-              face->foreground = FRAME_FOREGROUND_PIXEL (cache->f);
-             attrs[LFACE_FOREGROUND_INDEX] =
-               tty_color_name (cache->f, face->foreground);
-             face_colors_defaulted = 1;
-           }
-         else if (face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
-           {
-             face->foreground = FRAME_BACKGROUND_PIXEL (cache->f);
-             attrs[LFACE_FOREGROUND_INDEX] =
-               tty_color_name (cache->f, face->foreground);
-             face_colors_defaulted = 1;
-           }
-#ifdef MSDOS
-       }
-#endif
-#endif /* MSDOS or WINDOWSNT */
-    }
-
-  color = attrs[LFACE_BACKGROUND_INDEX];
-  if (STRINGP (color)
-      && XSTRING (color)->size
-      && CONSP (tty_defined_color_alist)
-      && (color = Fassoc (color, call1 (tty_color_alist, frame)),
-         CONSP (color)))
-    /* Associations in tty-defined-color-alist are of the form
-       (NAME INDEX R G B).  We need the INDEX part.  */
-    face->background = XINT (XCAR (XCDR (color)));
-
-  if (face->background == FACE_TTY_DEFAULT_BG_COLOR
-      && STRINGP (attrs[LFACE_BACKGROUND_INDEX]))
-    {
-      face->background = load_color (cache->f, face,
-                                    attrs[LFACE_BACKGROUND_INDEX],
-                                    LFACE_BACKGROUND_INDEX);
-#if defined (MSDOS) || defined (WINDOWSNT)
-      /* If the background of the default face is the default color,
-        use the background color defined by the frame.  */
-#ifdef MSDOS
-      if (FRAME_MSDOS_P (cache->f))
-       {
-#endif /* MSDOS */
-
-         if (face->background == FACE_TTY_DEFAULT_BG_COLOR
-             || face->background == FACE_TTY_DEFAULT_COLOR)
-           {
-             face->background = FRAME_BACKGROUND_PIXEL (cache->f);
-             attrs[LFACE_BACKGROUND_INDEX] =
-               tty_color_name (cache->f, face->background);
-             face_colors_defaulted = 1;
-           }
-         else if (face->background == FACE_TTY_DEFAULT_FG_COLOR)
-           {
-             face->background = FRAME_FOREGROUND_PIXEL (cache->f);
-             attrs[LFACE_BACKGROUND_INDEX] =
-               tty_color_name (cache->f, face->background);
-             face_colors_defaulted = 1;
-           }
-#ifdef MSDOS
-       }
-#endif
-#endif /* MSDOS or WINDOWSNT */
-    }
-
+  map_tty_color (f, face, LFACE_FOREGROUND_INDEX, &face_colors_defaulted);
+  map_tty_color (f, face, LFACE_BACKGROUND_INDEX, &face_colors_defaulted);
+  
   /* Swap colors if face is inverse-video.  If the colors are taken
      from the frame colors, they are already inverted, since the
      frame-creation function calls x-handle-reverse-video.  */
   if (face->tty_reverse_p && !face_colors_defaulted)
     {
       unsigned long tem = face->foreground;
-
       face->foreground = face->background;
       face->background = tem;
     }
@@ -6235,7 +6662,8 @@ DEFUN ("tty-suppress-bold-inverse-default-colors",
 SUPPRESS non-nil means suppress it.\n\
 This affects bold faces on TTYs whose foreground is the default background\n\
 color of the display and whose background is the default foreground color.\n\
-For such faces, no bold text will be displayed.")
+For such faces, the bold face attribute is ignored if this variable\n\
+is non-nil.")
   (suppress)
      Lisp_Object suppress;
 {
@@ -6262,8 +6690,8 @@ compute_char_face (f, ch, prop)
   int face_id;
 
   if (NILP (current_buffer->enable_multibyte_characters))
-    ch = -1;
-  
+    ch = 0;
+
   if (NILP (prop))
     {
       struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
@@ -6317,7 +6745,6 @@ face_at_buffer_position (w, pos, region_beg, region_end,
   Lisp_Object propname = mouse ? Qmouse_face : Qface;
   Lisp_Object limit1, end;
   struct face *default_face;
-  int multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
 
   /* W must display the current buffer.  We could write this function
      to use the frame and buffer of W, but right now it doesn't.  */
@@ -6347,7 +6774,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
     len = 40;
     overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
     noverlays = overlays_at (pos, 0, &overlay_vec, &len,
-                            &next_overlay, NULL);
+                            &next_overlay, NULL, 0);
 
     /* If there are more than 40, make enough space for all, and try
        again.  */
@@ -6356,7 +6783,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
        len = noverlays;
        overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
        noverlays = overlays_at (pos, 0, &overlay_vec, &len,
-                                &next_overlay, NULL);
+                                &next_overlay, NULL, 0);
       }
 
     if (next_overlay < endpos)
@@ -6366,7 +6793,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
   *endptr = endpos;
 
   default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-  
+
   /* Optimize common cases where we can use the default face.  */
   if (noverlays == 0
       && NILP (prop)
@@ -6401,8 +6828,8 @@ face_at_buffer_position (w, pos, region_beg, region_end,
   if (pos >= region_beg && pos < region_end)
     {
       Lisp_Object region_face = lface_from_face_name (f, Qregion, 0);
-      merge_face_vectors (XVECTOR (region_face)->contents, attrs);
+      merge_face_vectors (f, XVECTOR (region_face)->contents, attrs, Qnil);
+
       if (region_end < endpos)
        endpos = region_end;
     }
@@ -6422,11 +6849,13 @@ face_at_buffer_position (w, pos, region_beg, region_end,
    current_buffer, otherwise BUFPOS is zero to indicate that STRING is
    not an overlay string.  W must display the current buffer.
    REGION_BEG and REGION_END give the start and end positions of the
-   region; both are -1 if no region is visible.  BASE_FACE_ID is the
-   id of the basic face to merge with.  It is usually equal to
-   DEFAULT_FACE_ID but can be MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID
-   for strings displayed in the mode or top line.
-   
+   region; both are -1 if no region is visible.
+
+   BASE_FACE_ID is the id of a face to merge with.  For strings coming
+   from overlays or the `display' property it is the face at BUFPOS.
+
+   If MOUSE_P is non-zero, use the character's mouse-face, not its face.
+
    Set *ENDPTR to the next position where to check for faces in
    STRING; -1 if the face is constant from POS to the end of the
    string.
@@ -6436,24 +6865,26 @@ face_at_buffer_position (w, pos, region_beg, region_end,
 
 int
 face_at_string_position (w, string, pos, bufpos, region_beg,
-                        region_end, endptr, base_face_id)
+                        region_end, endptr, base_face_id, mouse_p)
      struct window *w;
      Lisp_Object string;
      int pos, bufpos;
      int region_beg, region_end;
      int *endptr;
      enum face_id base_face_id;
+     int mouse_p;
 {
   Lisp_Object prop, position, end, limit;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   struct face *base_face;
   int multibyte_p = STRING_MULTIBYTE (string);
+  Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface;
 
   /* Get the value of the face property at the current position within
      STRING.  Value is nil if there is no face property.  */
   XSETFASTINT (position, pos);
-  prop = Fget_text_property (position, Qface, string);
+  prop = Fget_text_property (position, prop_name, string);
 
   /* Get the next position at which to check for faces.  Value of end
      is nil if face is constant all the way to the end of the string.
@@ -6462,7 +6893,7 @@ face_at_string_position (w, string, pos, bufpos, region_beg,
      changes in Fnext_single_property_change.  Strings are usually
      short, so set the limit to the end of the string.  */
   XSETFASTINT (limit, XSTRING (string)->size);
-  end = Fnext_single_property_change (position, Qface, string, limit);
+  end = Fnext_single_property_change (position, prop_name, string, limit);
   if (INTEGERP (end))
     *endptr = XFASTINT (end);
   else
@@ -6501,7 +6932,7 @@ face_at_string_position (w, string, pos, bufpos, region_beg,
       && bufpos < region_end)
     {
       Lisp_Object region_face = lface_from_face_name (f, Qregion, 0);
-      merge_face_vectors (XVECTOR (region_face)->contents, attrs);
+      merge_face_vectors (f, XVECTOR (region_face)->contents, attrs, Qnil);
     }
 
   /* Look up a realized face with the given face attributes,
@@ -6556,7 +6987,7 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
   if (NILP (n))
     {
       int i;
-      
+
       fprintf (stderr, "font selection order: ");
       for (i = 0; i < DIM (font_sort_order); ++i)
        fprintf (stderr, "%d ", font_sort_order[i]);
@@ -6565,7 +6996,7 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
       fprintf (stderr, "alternative fonts: ");
       debug_print (Vface_alternative_font_family_alist);
       fprintf (stderr, "\n");
-       
+
       for (i = 0; i < FRAME_FACE_CACHE (SELECTED_FRAME ())->used; ++i)
        Fdump_face (make_number (i));
     }
@@ -6578,7 +7009,7 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
        error ("Not a valid face");
       dump_realized_face (face);
     }
-  
+
   return Qnil;
 }
 
@@ -6610,7 +7041,7 @@ syms_of_xfaces ()
   staticpro (&Qbitmap_spec_p);
   Qframe_update_face_colors = intern ("frame-update-face-colors");
   staticpro (&Qframe_update_face_colors);
-  
+
   /* Lisp face attribute keywords.  */
   QCfamily = intern (":family");
   staticpro (&QCfamily);
@@ -6623,7 +7054,7 @@ syms_of_xfaces ()
   QCunderline = intern (":underline");
   staticpro (&QCunderline);
   QCinverse_video = intern (":inverse-video");
-  staticpro (&QCinverse_video); 
+  staticpro (&QCinverse_video);
   QCreverse_video = intern (":reverse-video");
   staticpro (&QCreverse_video);
   QCforeground = intern (":foreground");
@@ -6646,6 +7077,8 @@ syms_of_xfaces ()
   staticpro (&QCstrike_through);
   QCbox = intern (":box");
   staticpro (&QCbox);
+  QCinherit = intern (":inherit");
+  staticpro (&QCinherit);
 
   /* Symbols used for Lisp face attribute values.  */
   QCcolor = intern (":color");
@@ -6733,6 +7166,17 @@ syms_of_xfaces ()
   staticpro (&Qtty_color_desc);
   Qtty_color_by_index = intern ("tty-color-by-index");
   staticpro (&Qtty_color_by_index);
+  Qtty_color_alist = intern ("tty-color-alist");
+  staticpro (&Qtty_color_alist);
+  Qscalable_fonts_allowed = intern ("scalable-fonts-allowed");
+  staticpro (&Qscalable_fonts_allowed);
+
+  Vparam_value_alist = Fcons (Fcons (Qnil, Qnil), Qnil);
+  staticpro (&Vparam_value_alist);
+  Vface_alternative_font_family_alist = Qnil;
+  staticpro (&Vface_alternative_font_family_alist);
+  Vface_alternative_font_registry_alist = Qnil;
+  staticpro (&Vface_alternative_font_registry_alist);
 
   defsubr (&Sinternal_make_lisp_face);
   defsubr (&Sinternal_lisp_face_p);
@@ -6752,6 +7196,7 @@ syms_of_xfaces ()
   defsubr (&Sframe_face_alist);
   defsubr (&Sinternal_set_font_selection_order);
   defsubr (&Sinternal_set_alternative_font_family_alist);
+  defsubr (&Sinternal_set_alternative_font_registry_alist);
 #if GLYPH_DEBUG
   defsubr (&Sdump_face);
   defsubr (&Sshow_face_resources);
@@ -6772,7 +7217,7 @@ that number of fonts when searching for a matching font.");
   DEFVAR_LISP ("face-new-frame-defaults", &Vface_new_frame_defaults,
     "List of global face definitions (for internal use only.)");
   Vface_new_frame_defaults = Qnil;
-  
+
   DEFVAR_LISP ("face-default-stipple", &Vface_default_stipple,
     "*Default stipple pattern used on monochrome displays.\n\
 This stipple pattern is used on monochrome displays\n\
@@ -6780,26 +7225,24 @@ instead of shades of gray for a face background color.\n\
 See `set-face-stipple' for possible values for this variable.");
   Vface_default_stipple = build_string ("gray3");
 
-  DEFVAR_LISP ("face-alternative-font-family-alist",
-              &Vface_alternative_font_family_alist, "");
-  Vface_alternative_font_family_alist = Qnil;
+  DEFVAR_LISP ("tty-defined-color-alist", &Vtty_defined_color_alist,
+   "An alist of defined terminal colors and their RGB values.");
+  Vtty_defined_color_alist = Qnil;
 
-#if SCALABLE_FONTS
-  
   DEFVAR_LISP ("scalable-fonts-allowed", &Vscalable_fonts_allowed,
     "Allowed scalable fonts.\n\
 A value of nil means don't allow any scalable fonts.\n\
 A value of t means allow any scalable font.\n\
 Otherwise, value must be a list of regular expressions.  A font may be\n\
-scaled if its name matches a regular expression in the list.");
-#ifdef WINDOWSNT
-  /* Windows uses mainly truetype fonts, so disallowing scalable fonts
-     by default limits the fonts available severely. */
-  Vscalable_fonts_allowed = Qt;
-#else
+scaled if its name matches a regular expression in the list.\n\
+Note that if value is nil, a scalable font might still be used, if no\n\
+other font of the appropriate family and registry is available.");
   Vscalable_fonts_allowed = Qnil;
-#endif
-#endif /* SCALABLE_FONTS */
+
+  DEFVAR_LISP ("face-ignored-fonts", &Vface_ignored_fonts,
+    "List of ignored fonts.\n\
+Each element is a regular expression that matches names of fonts to ignore.");
+  Vface_ignored_fonts = Qnil;
 
 #ifdef HAVE_WINDOW_SYSTEM
   defsubr (&Sbitmap_spec_p);