*** empty log message ***
[bpt/emacs.git] / src / xfaces.c
index b9a134f..1f7c906 100644 (file)
@@ -1,5 +1,5 @@
 /* xfaces.c -- "Face" primitives.
-   Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001
+   Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation.
 
 This file is part of GNU Emacs.
@@ -57,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
@@ -123,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.
@@ -173,7 +173,7 @@ Boston, MA 02111-1307, USA.  */
    fonts.
 
 
-   Character compositition.
+   Character composition.
 
    Usually, the realization process is already finished when Emacs
    actually reflects the desired glyph matrix on the screen.  However,
@@ -194,8 +194,10 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+
 #include "lisp.h"
-#include "charset.h"
+#include "character.h"
+#include "keyboard.h"
 #include "frame.h"
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -219,6 +221,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
@@ -227,6 +230,7 @@ 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 */
 
@@ -284,13 +288,8 @@ x_free_gc (f, gc)
 
 #include <stdio.h>
 #include <ctype.h>
-#include "keyboard.h"
 
-#ifndef max
-#define max(A, B)      ((A) > (B) ? (A) : (B))
-#define min(A, B)      ((A) < (B) ? (A) : (B))
 #define abs(X)         ((X) < 0 ? -(X) : (X))
-#endif
 
 /* Number of pt per inch (from the TeXbook).  */
 
@@ -365,6 +364,7 @@ Lisp_Object Qframe_update_face_colors;
 
 Lisp_Object Qdefault, Qtool_bar, Qregion, Qfringe;
 Lisp_Object Qheader_line, Qscroll_bar, Qcursor, Qborder, Qmouse, Qmenu;
+Lisp_Object Qmode_line_inactive;
 extern Lisp_Object Qmode_line;
 
 /* The symbol `face-alias'.  A symbols having that property is an
@@ -403,7 +403,7 @@ Lisp_Object Vface_alternative_font_registry_alist;
    font may be scaled if its name matches a regular expression in the
    list.  */
 
-Lisp_Object Vscalable_fonts_allowed;
+Lisp_Object Vscalable_fonts_allowed, Qscalable_fonts_allowed;
 
 /* List of regular expressions that matches names of fonts to ignore. */
 
@@ -471,10 +471,6 @@ static int clear_font_table_count;
 
 int face_change_count;
 
-/* Incremented for every change in the `menu' face.  */
-
-int menu_face_change_count;
-
 /* Non-zero means don't display bold text if a face's foreground
    and background colors are the inverse of the default colors of the
    display.   This is a kluge to suppress `bold black' foreground text
@@ -495,6 +491,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.  */
@@ -505,14 +505,12 @@ 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, int));
-static int first_font_matching P_ ((struct frame *f, char *,
-                                   struct font_name *));
 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 *));
@@ -532,8 +530,10 @@ 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));
@@ -550,14 +550,14 @@ static unsigned hash_string_case_insensitive P_ ((Lisp_Object));
 static unsigned lface_hash P_ ((Lisp_Object *));
 static int lface_same_font_attributes_p P_ ((Lisp_Object *, Lisp_Object *));
 static struct face_cache *make_face_cache P_ ((struct frame *));
-static void free_realized_face P_ ((struct frame *, struct face *));
 static void clear_face_gcs P_ ((struct face_cache *));
 static void free_face_cache P_ ((struct face_cache *));
 static int face_numeric_weight P_ ((Lisp_Object));
 static int face_numeric_slant P_ ((Lisp_Object));
 static int face_numeric_swidth P_ ((Lisp_Object));
 static int face_fontset P_ ((Lisp_Object *));
-static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int, int));
+static char *choose_face_font P_ ((struct frame *, Lisp_Object *,
+                                  struct face *, int));
 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));
@@ -567,7 +567,6 @@ static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object,
                                         Lisp_Object, int, int));
 static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
 static struct face *make_realized_face P_ ((Lisp_Object *));
-static void free_realized_faces P_ ((struct face_cache *));
 static char *best_matching_font P_ ((struct frame *, Lisp_Object *,
                                     struct font_name *, int, int));
 static void cache_face P_ ((struct face_cache *, struct face *, unsigned));
@@ -595,12 +594,18 @@ 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 *));
+
+extern void free_frame_menubar P_ ((struct frame *));
+#endif /* USE_X_TOOLKIT */
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 \f
@@ -664,8 +669,8 @@ unregister_colors (pixels, n)
 
 
 DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
-  "Dump currently allocated colors and their reference counts to stderr.")
-  ()
+       doc: /* Dump currently allocated colors to stderr.  */)
+     ()
 {
   int i, n;
 
@@ -870,7 +875,7 @@ frame_or_selected_frame (frame, nparam)
   if (NILP (frame))
     frame = selected_frame;
 
-  CHECK_LIVE_FRAME (frame, nparam);
+  CHECK_LIVE_FRAME (frame);
   return XFRAME (frame);
 }
 
@@ -973,6 +978,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.  */
@@ -980,13 +993,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
@@ -1007,9 +1017,9 @@ 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.")
-  (thoroughly)
+       doc: /* Clear face caches on all frames.
+Optional THOROUGHLY non-nil means try to free unused fonts, too.  */)
+     (thoroughly)
      Lisp_Object thoroughly;
 {
   clear_face_cache (!NILP (thoroughly));
@@ -1023,26 +1033,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.  */
@@ -1077,13 +1098,13 @@ clear_font_table (f)
 #ifdef HAVE_WINDOW_SYSTEM
 
 DEFUN ("bitmap-spec-p", Fbitmap_spec_p, Sbitmap_spec_p, 1, 1, 0,
-  "Value is non-nil if OBJECT is a valid bitmap specification.\n\
-A bitmap specification is either a string, a file name, or a list\n\
-(WIDTH HEIGHT DATA) where WIDTH is the pixel width of the bitmap,\n\
-HEIGHT is its height, and DATA is a string containing the bits of\n\
-the pixmap.  Bits are stored row by row, each row occupies\n\
-(WIDTH + 7)/8 bytes.")
-  (object)
+       doc: /* Value is non-nil if OBJECT is a valid bitmap specification.
+A bitmap specification is either a string, a file name, or a list
+\(WIDTH HEIGHT DATA) where WIDTH is the pixel width of the bitmap,
+HEIGHT is its height, and DATA is a string containing the bits of
+the pixmap.  Bits are stored row by row, each row occupies
+\(WIDTH + 7)/8 bytes.  */)
+     (object)
      Lisp_Object object;
 {
   int pixmap_p = 0;
@@ -1246,12 +1267,13 @@ load_face_font (f, face, c)
   face->font_info_id = -1;
   face->font = NULL;
 
-  font_name = choose_face_font (f, face->lface, face->fontset, c);
+  font_name = choose_face_font (f, face->lface, face, c);
+
   if (!font_name)
     return;
 
   BLOCK_INPUT;
-  font_info = FS_LOAD_FACE_FONT (f, c, font_name, face);
+  font_info = FS_LOAD_FONT (f, font_name);
   UNBLOCK_INPUT;
 
   if (font_info)
@@ -1461,16 +1483,16 @@ face_color_supported_p (f, color_name, background_p)
 
 
 DEFUN ("color-gray-p", Fcolor_gray_p, Scolor_gray_p, 1, 2, 0,
-  "Return non-nil if COLOR is a shade of gray (or white or black).\n\
-FRAME specifies the frame and thus the display for interpreting COLOR.\n\
-If FRAME is nil or omitted, use the selected frame.")
-   (color, frame)
+       doc: /* Return non-nil if COLOR is a shade of gray (or white or black).
+FRAME specifies the frame and thus the display for interpreting COLOR.
+If FRAME is nil or omitted, use the selected frame.  */)
+     (color, frame)
      Lisp_Object color, frame;
 {
   struct frame *f;
 
-  CHECK_FRAME (frame, 0);
-  CHECK_STRING (color, 0);
+  CHECK_FRAME (frame);
+  CHECK_STRING (color);
   f = XFRAME (frame);
   return face_color_gray_p (f, XSTRING (color)->data) ? Qt : Qnil;
 }
@@ -1478,17 +1500,17 @@ If FRAME is nil or omitted, use the selected frame.")
 
 DEFUN ("color-supported-p", Fcolor_supported_p,
        Scolor_supported_p, 2, 3, 0,
-  "Return non-nil if COLOR can be displayed on FRAME.\n\
-BACKGROUND-P non-nil means COLOR is used as a background.\n\
-If FRAME is nil or omitted, use the selected frame.\n\
-COLOR must be a valid color name.")
-   (color, frame, background_p)
+       doc: /* Return non-nil if COLOR can be displayed on FRAME.
+BACKGROUND-P non-nil means COLOR is used as a background.
+If FRAME is nil or omitted, use the selected frame.
+COLOR must be a valid color name.  */)
+     (color, frame, background_p)
      Lisp_Object frame, color, background_p;
 {
   struct frame *f;
 
-  CHECK_FRAME (frame, 0);
-  CHECK_STRING (color, 0);
+  CHECK_FRAME (frame);
+  CHECK_STRING (color);
   f = XFRAME (frame);
   if (face_color_supported_p (f, XSTRING (color)->data, !NILP (background_p)))
     return Qt;
@@ -1625,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
 }
 
@@ -1640,6 +1665,9 @@ free_face_colors (f, face)
      struct face *face;
 {
 #ifdef HAVE_X_WINDOWS
+  if (face->colors_copied_bitwise_p)
+    return;
+
   BLOCK_INPUT;
 
   if (!face->foreground_defaulted_p)
@@ -2084,6 +2112,61 @@ face_numeric_swidth (width)
 }
 
 
+Lisp_Object
+generate_ascii_font (name, ascii_spec)
+     Lisp_Object name, ascii_spec;
+{
+  struct font_name font;
+  char *p;
+
+  font.name = LSTRDUPA (name);
+  if (! split_font_name (NULL, &font, 0))
+    return Qnil;
+
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_FAMILY_INDEX)))
+    {
+      p = LSTRDUPA (AREF (ascii_spec, FONT_SPEC_FAMILY_INDEX));
+      font.fields[XLFD_FOUNDRY] = p;
+      while (*p != '-') p++;
+      if (*p)
+       {
+         *p++ = 0;
+         font.fields[XLFD_FAMILY] = p;
+       }
+      else
+       {
+         font.fields[XLFD_FAMILY] = font.fields[XLFD_FOUNDRY];
+         font.fields[XLFD_FOUNDRY] = "*";
+       }
+    }
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_WEIGHT_INDEX)))
+    font.fields[XLFD_WEIGHT]
+      = XSTRING (AREF (ascii_spec, FONT_SPEC_WEIGHT_INDEX))->data;
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_SLANT_INDEX)))
+    font.fields[XLFD_SLANT]
+      = XSTRING (AREF (ascii_spec, FONT_SPEC_SLANT_INDEX))->data;
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_SWIDTH_INDEX)))
+    font.fields[XLFD_SWIDTH]
+      = XSTRING (AREF (ascii_spec, FONT_SPEC_SWIDTH_INDEX))->data;
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_ADSTYLE_INDEX)))
+    font.fields[XLFD_ADSTYLE]
+      = XSTRING (AREF (ascii_spec, FONT_SPEC_ADSTYLE_INDEX))->data;
+  p = LSTRDUPA (AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX));
+  font.fields[XLFD_REGISTRY] = p;
+  while (*p != '-') p++;
+  if (*p)
+    *p++ = 0;
+  else
+    p = "*";
+  font.fields[XLFD_ENCODING] = p;
+
+  p = build_font_name (&font);
+  name = build_string (p);
+  xfree (p);
+  return name;
+}
+
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Return non-zero if FONT is the name of a fixed-pitch font.  */
@@ -2116,13 +2199,41 @@ xlfd_point_size (f, font)
      struct font_name *font;
 {
   double resy = FRAME_X_DISPLAY_INFO (f)->resy;
-  double font_pixel = atoi (font->fields[XLFD_PIXEL_SIZE]);
+  char *pixel_field = font->fields[XLFD_PIXEL_SIZE];
+  double pixel;
   int real_pt;
 
-  if (font_pixel == 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 = PT_PER_INCH * 10.0 * font_pixel / resy + 0.5;
+    real_pt = PT_PER_INCH * 10.0 * pixel / resy + 0.5;
 
   return real_pt;
 }
@@ -2156,9 +2267,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)
@@ -2178,6 +2287,33 @@ 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;
 
@@ -2283,23 +2419,20 @@ 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.  */
 
 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;
+  int n, nignored;
 
   /* NTEMACS_TODO : currently this uses w32_list_fonts, but it may be
      better to do it the other way around. */
@@ -2314,17 +2447,18 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
   lfonts = w32_list_fonts (f, lpattern, 0, nfonts);
   UNBLOCK_INPUT;
 #else
-  lfonts = x_list_fonts (f, lpattern, scalable_fonts_p ? -1 : 0, nfonts);
+  lfonts = x_list_fonts (f, lpattern, -1, nfonts);
 #endif
 
   /* Make a copy of the font names we got from X, and
      split them into fields.  */
-  n = 0;
-  for (tem = lfonts; CONSP (tem); tem = XCDR (tem))
+  n = nignored = 0;
+  for (tem = lfonts; CONSP (tem) && n < nfonts; tem = XCDR (tem))
     {
       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);
@@ -2333,24 +2467,27 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
            break;
        }
       if (!NILP (tail))
-       continue;
+       {
+         ++nignored;
+         continue;
+       }
 
       /* Make a copy of the font name.  */
       fonts[n].name = xstrdup (name);
 
-      /* Ignore fonts having a name that we can't parse.  */
-      if (!split_font_name (f, fonts + n, 1))
-       xfree (fonts[n].name);
-      else if (font_scalable_p (fonts + n))
+      if (split_font_name (f, fonts + n, 1))
        {
-         if (!scalable_fonts_p
-             || !may_use_scalable_font_p (fonts + n, name))
-           xfree (fonts[n].name);
+         if (font_scalable_p (fonts + n)
+             && !may_use_scalable_font_p (name))
+           {
+             ++nignored;
+             xfree (fonts[n].name);
+           }
          else
            ++n;
        }
       else
-       ++n;
+       xfree (fonts[n].name);
     }
 
   /* If no fonts found, try patterns from Valternate_fontname_alist.  */
@@ -2381,8 +2518,7 @@ 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);
        }
@@ -2392,34 +2528,6 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
 }
 
 
-/* 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;
-}
-
-
 /* Determine fonts matching PATTERN on frame F.  Sort resulting fonts
    using comparison function CMPFN.  Value is the number of fonts
    found.  If value is non-zero, *FONTS is set to a vector of
@@ -2443,7 +2551,7 @@ sorted_font_list (f, pattern, cmpfn, fonts)
     nfonts = XFASTINT (Vfont_list_limit);
 
   *fonts = (struct font_name *) xmalloc (nfonts * sizeof **fonts);
-  nfonts = x_face_list_fonts (f, pattern, *fonts, nfonts, 1, 1);
+  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.  */
@@ -2635,7 +2743,7 @@ remove_duplicates (list)
     {
       Lisp_Object next = XCDR (tail);
       if (!NILP (Fequal (XCAR (next), XCAR (tail))))
-       XCDR (tail) = XCDR (next);
+       XSETCDR (tail, XCDR (next));
       else
        tail = XCDR (tail);
     }
@@ -2643,22 +2751,22 @@ remove_duplicates (list)
 
 
 DEFUN ("x-family-fonts", Fx_family_fonts, Sx_family_fonts, 0, 2, 0,
-  "Return a list of available fonts of family FAMILY on FRAME.\n\
-If FAMILY is omitted or nil, list all families.\n\
-Otherwise, FAMILY must be a string, possibly containing wildcards\n\
-`?' and `*'.\n\
-If FRAME is omitted or nil, use the selected frame.\n\
-Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT\n\
-SLANT FIXED-P FULL REGISTRY-AND-ENCODING].\n\
-FAMILY is the font family name.  POINT-SIZE is the size of the\n\
-font in 1/10 pt.  WIDTH, WEIGHT, and SLANT are symbols describing the\n\
-width, weight and slant of the font.  These symbols are the same as for\n\
-face attributes.  FIXED-P is non-nil if the font is fixed-pitch.\n\
-FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string\n\
-giving the registry and encoding of the font.\n\
-The result list is sorted according to the current setting of\n\
-the face font sort order.")
-  (family, frame)
+       doc: /* Return a list of available fonts of family FAMILY on FRAME.
+If FAMILY is omitted or nil, list all families.
+Otherwise, FAMILY must be a string, possibly containing wildcards
+`?' and `*'.
+If FRAME is omitted or nil, use the selected frame.
+Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT
+SLANT FIXED-P FULL REGISTRY-AND-ENCODING].
+FAMILY is the font family name.  POINT-SIZE is the size of the
+font in 1/10 pt.  WIDTH, WEIGHT, and SLANT are symbols describing the
+width, weight and slant of the font.  These symbols are the same as for
+face attributes.  FIXED-P is non-nil if the font is fixed-pitch.
+FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string
+giving the registry and encoding of the font.
+The result list is sorted according to the current setting of
+the face font sort order.  */)
+     (family, frame)
      Lisp_Object family, frame;
 {
   struct frame *f = check_x_frame (frame);
@@ -2668,7 +2776,7 @@ the face font sort order.")
   struct gcpro gcpro1;
 
   if (!NILP (family))
-    CHECK_STRING (family, 1);
+    CHECK_STRING (family);
 
   result = Qnil;
   GCPRO1 (result);
@@ -2703,12 +2811,12 @@ the face font sort order.")
 
 DEFUN ("x-font-family-list", Fx_font_family_list, Sx_font_family_list,
        0, 1, 0,
-  "Return a list of available font families on FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.\n\
-Value is a list of conses (FAMILY . FIXED-P) where FAMILY\n\
-is a font family, and FIXED-P is non-nil if fonts of that family\n\
-are fixed-pitch.")
-  (frame)
+       doc: /* Return a list of available font families on FRAME.
+If FRAME is omitted or nil, use the selected frame.
+Value is a list of conses (FAMILY . FIXED-P) where FAMILY
+is a font family, and FIXED-P is non-nil if fonts of that family
+are fixed-pitch.  */)
+     (frame)
      Lisp_Object frame;
 {
   struct frame *f = check_x_frame (frame);
@@ -2750,26 +2858,26 @@ are fixed-pitch.")
 
 
 DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 5, 0,
-  "Return a list of the names of available fonts matching PATTERN.\n\
-If optional arguments FACE and FRAME are specified, return only fonts\n\
-the same size as FACE on FRAME.\n\
-PATTERN is a string, perhaps with wildcard characters;\n\
-  the * character matches any substring, and\n\
-  the ? character matches any single character.\n\
-  PATTERN is case-insensitive.\n\
-FACE is a face name--a symbol.\n\
-\n\
-The return value is a list of strings, suitable as arguments to\n\
-set-face-font.\n\
-\n\
-Fonts Emacs can't use may or may not be excluded\n\
-even if they match PATTERN and FACE.\n\
-The optional fourth argument MAXIMUM sets a limit on how many\n\
-fonts to match.  The first MAXIMUM fonts are reported.\n\
-The optional fifth argument WIDTH, if specified, is a number of columns\n\
-occupied by a character of a font.  In that case, return only fonts\n\
-the WIDTH times as wide as FACE on FRAME.")
-  (pattern, face, frame, maximum, width)
+       doc: /* Return a list of the names of available fonts matching PATTERN.
+If optional arguments FACE and FRAME are specified, return only fonts
+the same size as FACE on FRAME.
+PATTERN is a string, perhaps with wildcard characters;
+  the * character matches any substring, and
+  the ? character matches any single character.
+  PATTERN is case-insensitive.
+FACE is a face name--a symbol.
+
+The return value is a list of strings, suitable as arguments to
+set-face-font.
+
+Fonts Emacs can't use may or may not be excluded
+even if they match PATTERN and FACE.
+The optional fourth argument MAXIMUM sets a limit on how many
+fonts to match.  The first MAXIMUM fonts are reported.
+The optional fifth argument WIDTH, if specified, is a number of columns
+occupied by a character of a font.  In that case, return only fonts
+the WIDTH times as wide as FACE on FRAME.  */)
+     (pattern, face, frame, maximum, width)
     Lisp_Object pattern, face, frame, maximum, width;
 {
   struct frame *f;
@@ -2777,18 +2885,18 @@ the WIDTH times as wide as FACE on FRAME.")
   int maxnames;
 
   check_x ();
-  CHECK_STRING (pattern, 0);
+  CHECK_STRING (pattern);
 
   if (NILP (maximum))
     maxnames = 2000;
   else
     {
-      CHECK_NATNUM (maximum, 0);
+      CHECK_NATNUM (maximum);
       maxnames = XINT (maximum);
     }
 
   if (!NILP (width))
-    CHECK_NUMBER (width, 4);
+    CHECK_NUMBER (width);
 
   /* We can't simply call check_x_frame because this function may be
      called before any frame is created.  */
@@ -3096,7 +3204,7 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
      caching it now is not futail because we anyway load the font
      later.  */
   BLOCK_INPUT;
-  font_info = FS_LOAD_FONT (f, 0, font_name, -1);
+  font_info = FS_LOAD_FONT (f, font_name);
   UNBLOCK_INPUT;
 
   if (!font_info)
@@ -3168,66 +3276,53 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
 
 /* 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.  */
+   returned instead.  FROM and TO may be either absolute face heights or
+   `relative' heights; the returned value is always an absolute height
+   unless both FROM and TO are relative.  GCPRO is a lisp value that
+   will be protected from garbage-collection if this function makes a
+   call into lisp.  */
 
 Lisp_Object
 merge_face_heights (from, to, invalid, gcpro)
      Lisp_Object from, to, invalid, gcpro;
 {
-  int result = 0;
+  Lisp_Object result = invalid;
 
   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;
-           }
-       }
+    /* FROM is absolute, just use it as is.  */
+    result = from;
+  else if (FLOATP (from))
+    /* FROM is a scale, use it to adjust TO.  */
+    {
+      if (INTEGERP (to))
+       /* relative X absolute => absolute */
+       result = make_number ((EMACS_INT)(XFLOAT_DATA (from) * XINT (to)));
+      else if (FLOATP (to))
+       /* relative X relative => relative */
+       result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to));
     }
-#endif
   else if (FUNCTIONP (from))
+    /* FROM is a function, which use to adjust TO.  */
     {
       /* Call function with current height as argument.
         From is the new height.  */
-      Lisp_Object args[2], height;
+      Lisp_Object args[2];
       struct gcpro gcpro1;
 
       GCPRO1 (gcpro);
 
       args[0] = from;
       args[1] = to;
-      height = safe_call (2, args);
+      result = safe_call (2, args);
 
       UNGCPRO;
 
-      if (NUMBERP (height))
-       result = XFLOATINT (height);
+      /* Ensure that if TO was absolute, so is the result.  */
+      if (INTEGERP (to) && !INTEGERP (result))
+       result = invalid;
     }
 
-  if (result > 0)
-    return make_number (result);
-  else
-    return invalid;
+  return result;
 }
 
 
@@ -3271,10 +3366,12 @@ merge_face_vectors (f, from, to, cycle_check)
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (!UNSPECIFIEDP (from[i]))
-      if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
-       to[i] = merge_face_heights (from[i], to[i], to[i], cycle_check);
-      else
-       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.  */
@@ -3289,7 +3386,7 @@ merge_face_vectors (f, from, to, cycle_check)
    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
+   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
@@ -3575,24 +3672,24 @@ merge_face_vector_with_property (f, to, prop)
 
 DEFUN ("internal-make-lisp-face", Finternal_make_lisp_face,
        Sinternal_make_lisp_face, 1, 2, 0,
-  "Make FACE, a symbol, a Lisp face with all attributes nil.\n\
-If FACE was not known as a face before, create a new one.\n\
-If optional argument FRAME is specified, make a frame-local face\n\
-for that frame.  Otherwise operate on the global face definition.\n\
-Value is a vector of face attributes.")
-  (face, frame)
+       doc: /* Make FACE, a symbol, a Lisp face with all attributes nil.
+If FACE was not known as a face before, create a new one.
+If optional argument FRAME is specified, make a frame-local face
+for that frame.  Otherwise operate on the global face definition.
+Value is a vector of face attributes.  */)
+     (face, frame)
      Lisp_Object face, frame;
 {
   Lisp_Object global_lface, lface;
   struct frame *f;
   int i;
 
-  CHECK_SYMBOL (face, 0);
+  CHECK_SYMBOL (face);
   global_lface = lface_from_face_name (NULL, face, 0);
 
   if (!NILP (frame))
     {
-      CHECK_LIVE_FRAME (frame, 1);
+      CHECK_LIVE_FRAME (frame);
       f = XFRAME (frame);
       lface = lface_from_face_name (f, face, 0);
     }
@@ -3645,6 +3742,14 @@ Value is a vector of face attributes.")
   else
     lface = global_lface;
 
+  /* Changing a named face means that all realized faces depending on
+     that face are invalid.  Since we cannot tell which realized faces
+     depend on the face, make sure they are all removed.  This is done
+     by incrementing face_change_count.  The next call to
+     init_iterator will then free realized faces.  */
+  ++face_change_count;
+  ++windows_or_buffers_changed;
+
   xassert (LFACEP (lface));
   check_lface (lface);
   return lface;
@@ -3653,18 +3758,18 @@ Value is a vector of face attributes.")
 
 DEFUN ("internal-lisp-face-p", Finternal_lisp_face_p,
        Sinternal_lisp_face_p, 1, 2, 0,
-  "Return non-nil if FACE names a face.\n\
-If optional second parameter FRAME is non-nil, check for the\n\
-existence of a frame-local face with name FACE on that frame.\n\
-Otherwise check for the existence of a global face.")
-  (face, frame)
+       doc: /* Return non-nil if FACE names a face.
+If optional second parameter FRAME is non-nil, check for the
+existence of a frame-local face with name FACE on that frame.
+Otherwise check for the existence of a global face.  */)
+     (face, frame)
      Lisp_Object face, frame;
 {
   Lisp_Object lface;
 
   if (!NILP (frame))
     {
-      CHECK_LIVE_FRAME (frame, 1);
+      CHECK_LIVE_FRAME (frame);
       lface = lface_from_face_name (XFRAME (frame), face, 0);
     }
   else
@@ -3676,20 +3781,20 @@ Otherwise check for the existence of a global face.")
 
 DEFUN ("internal-copy-lisp-face", Finternal_copy_lisp_face,
        Sinternal_copy_lisp_face, 4, 4, 0,
-  "Copy face FROM to TO.\n\
-If FRAME it t, copy the global face definition of FROM to the\n\
-global face definition of TO.  Otherwise, copy the frame-local\n\
-definition of FROM on FRAME to the frame-local definition of TO\n\
-on NEW-FRAME, or FRAME if NEW-FRAME is nil.\n\
-\n\
-Value is TO.")
-  (from, to, frame, new_frame)
+       doc: /* Copy face FROM to TO.
+If FRAME it t, copy the global face definition of FROM to the
+global face definition of TO.  Otherwise, copy the frame-local
+definition of FROM on FRAME to the frame-local definition of TO
+on NEW-FRAME, or FRAME if NEW-FRAME is nil.
+
+Value is TO.  */)
+     (from, to, frame, new_frame)
      Lisp_Object from, to, frame, new_frame;
 {
   Lisp_Object lface, copy;
 
-  CHECK_SYMBOL (from, 0);
-  CHECK_SYMBOL (to, 1);
+  CHECK_SYMBOL (from);
+  CHECK_SYMBOL (to);
   if (NILP (new_frame))
     new_frame = frame;
 
@@ -3703,8 +3808,8 @@ Value is TO.")
   else
     {
       /* Copy frame-local definition of FROM.  */
-      CHECK_LIVE_FRAME (frame, 2);
-      CHECK_LIVE_FRAME (new_frame, 3);
+      CHECK_LIVE_FRAME (frame);
+      CHECK_LIVE_FRAME (new_frame);
       lface = lface_from_face_name (XFRAME (frame), from, 1);
       copy = Finternal_make_lisp_face (to, new_frame);
     }
@@ -3712,19 +3817,27 @@ Value is TO.")
   bcopy (XVECTOR (lface)->contents, XVECTOR (copy)->contents,
         LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
 
+  /* Changing a named face means that all realized faces depending on
+     that face are invalid.  Since we cannot tell which realized faces
+     depend on the face, make sure they are all removed.  This is done
+     by incrementing face_change_count.  The next call to
+     init_iterator will then free realized faces.  */
+  ++face_change_count;
+  ++windows_or_buffers_changed;
+
   return 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\
-FRAME being a frame means change the face on that frame.\n\
-FRAME nil means change 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)
+       doc: /* Set attribute ATTR of FACE to VALUE.
+FRAME being a frame means change the face on that frame.
+FRAME nil means change the face of the selected frame.
+FRAME t means change the default for new frames.
+FRAME 0 means change the face on all frames, and change the default
+  for new frames.  */)
+     (face, attr, value, frame)
      Lisp_Object face, attr, value, frame;
 {
   Lisp_Object lface;
@@ -3734,8 +3847,8 @@ FRAME 0 means change the face on all frames, and change the default\n\
   /* 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);
+  CHECK_SYMBOL (face);
+  CHECK_SYMBOL (attr);
 
   face = resolve_face_name (face);
 
@@ -3758,7 +3871,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
       if (NILP (frame))
        frame = selected_frame;
 
-      CHECK_LIVE_FRAME (frame, 3);
+      CHECK_LIVE_FRAME (frame);
       lface = lface_from_face_name (XFRAME (frame), face, 0);
 
       /* If a frame-local face doesn't exist yet, create one.  */
@@ -3770,7 +3883,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_STRING (value, 3);
+         CHECK_STRING (value);
          if (XSTRING (value)->size == 0)
            signal_error ("Invalid face family", value);
        }
@@ -3782,13 +3895,16 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         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));
+         Lisp_Object test;
 
-         if (!INTEGERP(test) || XINT(test) <= 0)
+         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);
        }
 
@@ -3800,7 +3916,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_SYMBOL (value, 3);
+         CHECK_SYMBOL (value);
          if (face_numeric_weight (value) < 0)
            signal_error ("Invalid face weight", value);
        }
@@ -3812,7 +3928,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_SYMBOL (value, 3);
+         CHECK_SYMBOL (value);
          if (face_numeric_slant (value) < 0)
            signal_error ("Invalid face slant", value);
        }
@@ -3930,7 +4046,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_SYMBOL (value, 3);
+         CHECK_SYMBOL (value);
          if (!EQ (value, Qt) && !NILP (value))
            signal_error ("Invalid inverse-video face attribute value", value);
        }
@@ -3944,7 +4060,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
          /* Don't check for valid color names here because it depends
             on the frame (display) whether the color will be valid
             when the face is realized.  */
-         CHECK_STRING (value, 3);
+         CHECK_STRING (value);
          if (XSTRING (value)->size == 0)
            signal_error ("Empty foreground color value", value);
        }
@@ -3958,7 +4074,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
          /* Don't check for valid color names here because it depends
             on the frame (display) whether the color will be valid
             when the face is realized.  */
-         CHECK_STRING (value, 3);
+         CHECK_STRING (value);
          if (XSTRING (value)->size == 0)
            signal_error ("Empty background color value", value);
        }
@@ -3980,7 +4096,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_SYMBOL (value, 3);
+         CHECK_SYMBOL (value);
          if (face_numeric_swidth (value) < 0)
            signal_error ("Invalid face width", value);
        }
@@ -3991,27 +4107,30 @@ FRAME 0 means change the face on all frames, and change the default\n\
   else if (EQ (attr, QCfont))
     {
 #ifdef HAVE_WINDOW_SYSTEM
-      /* Set font-related attributes of the Lisp face from an
-        XLFD font name.  */
-      struct frame *f;
-      Lisp_Object tmp;
-
-      CHECK_STRING (value, 3);
-      if (EQ (frame, Qt))
-       f = SELECTED_FRAME ();
-      else
-       f = check_x_frame (frame);
+      if (FRAME_WINDOW_P (XFRAME (frame)))
+       {
+         /* Set font-related attributes of the Lisp face from an XLFD
+            font name.  */
+         struct frame *f;
+         Lisp_Object tmp;
+
+         CHECK_STRING (value);
+         if (EQ (frame, Qt))
+           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);
-      if (!NILP (tmp))
-       value = tmp;
+         /* VALUE may be a fontset name or an alias of fontset.  In
+            such a case, use the base fontset name.  */
+         tmp = Fquery_fontset (value, Qnil);
+         if (!NILP (tmp))
+           value = tmp;
 
-      if (!set_lface_from_font_name (f, lface, value, 1, 1))
-       signal_error ("Invalid font or fontset name", value);
+         if (!set_lface_from_font_name (f, lface, value, 1, 1))
+           signal_error ("Invalid font or fontset name", value);
 
-      font_attr_p = 1;
+         font_attr_p = 1;
+       }
 #endif /* HAVE_WINDOW_SYSTEM */
     }
   else if (EQ (attr, QCinherit))
@@ -4076,7 +4195,8 @@ FRAME 0 means change the face on all frames, and change the default\n\
 #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
@@ -4122,23 +4242,39 @@ FRAME 0 means change the face on all frames, and change the default\n\
        }
 #endif /* HAVE_WINDOW_SYSTEM */
       else if (EQ (face, Qmenu))
-       ++menu_face_change_count;
+       {
+         /* 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))
-       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);
-         }
+       {
+         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);
+             XSETCAR (cons, param);
+             XSETCDR (cons, value);
+             Fmodify_frame_parameters (frame, Vparam_value_alist);
+           }
+       }
     }
 
   return face;
@@ -4171,7 +4307,7 @@ set_font_frame_param (frame, lface)
          /* 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);
+         font = choose_face_font (f, XVECTOR (lface)->contents, NULL, 0);
          if (!font)
            error ("No font matches the specified attribute");
          font_name = build_string (font);
@@ -4199,6 +4335,14 @@ update_face_from_frame_parameter (f, param, new_value)
   if (NILP (f->face_alist))
     return;
 
+  /* Changing a named face means that all realized faces depending on
+     that face are invalid.  Since we cannot tell which realized faces
+     depend on the face, make sure they are all removed.  This is done
+     by incrementing face_change_count.  The next call to
+     init_iterator will then free realized faces.  */
+  ++face_change_count;
+  ++windows_or_buffers_changed;
+
   if (EQ (param, Qforeground_color))
     {
       lface = lface_from_face_name (f, Qdefault, 1);
@@ -4247,16 +4391,16 @@ update_face_from_frame_parameter (f, param, new_value)
    doesn't take a frame argument.  */
 
 DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
-       Sinternal_face_x_get_resource, 3, 3, 0, "")
-  (resource, class, frame)
+       Sinternal_face_x_get_resource, 3, 3, 0, doc: /* */)
+     (resource, class, frame)
      Lisp_Object resource, class, frame;
 {
   Lisp_Object value = Qnil;
 #ifndef WINDOWSNT
 #ifndef macintosh
-  CHECK_STRING (resource, 0);
-  CHECK_STRING (class, 1);
-  CHECK_LIVE_FRAME (frame, 2);
+  CHECK_STRING (resource);
+  CHECK_STRING (class);
+  CHECK_LIVE_FRAME (frame);
   BLOCK_INPUT;
   value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
                                  resource, class, Qnil, Qnil);
@@ -4299,13 +4443,13 @@ face_boolean_x_resource_value (value, signal_p)
 DEFUN ("internal-set-lisp-face-attribute-from-resource",
        Finternal_set_lisp_face_attribute_from_resource,
        Sinternal_set_lisp_face_attribute_from_resource,
-       3, 4, 0, "")
-  (face, attr, value, frame)
+       3, 4, 0, doc: /* */)
+     (face, attr, value, frame)
      Lisp_Object face, attr, value, frame;
 {
-  CHECK_SYMBOL (face, 0);
-  CHECK_SYMBOL (attr, 1);
-  CHECK_STRING (value, 2);
+  CHECK_SYMBOL (face);
+  CHECK_SYMBOL (attr);
+  CHECK_STRING (value);
 
   if (xstricmp (XSTRING (value)->data, "unspecified") == 0)
     value = Qunspecified;
@@ -4323,8 +4467,7 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
     value = face_boolean_x_resource_value (value, 1);
   else if (EQ (attr, QCunderline)
           || EQ (attr, QCoverline)
-          || EQ (attr, QCstrike_through)
-          || EQ (attr, QCbox))
+          || EQ (attr, QCstrike_through))
     {
       Lisp_Object boolean_value;
 
@@ -4334,6 +4477,8 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
       if (SYMBOLP (boolean_value))
        value = boolean_value;
     }
+  else if (EQ (attr, QCbox))
+    value = Fcar (Fread_from_string (value, Qnil, Qnil));
 
   return Finternal_set_lisp_face_attribute (face, attr, value, frame);
 }
@@ -4341,110 +4486,138 @@ 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
 
-void
-x_set_menu_face_resources (f)
+/* Make menus on frame F appear as specified by the `menu' face.  */
+
+static void
+x_update_menu_appearance (f)
      struct frame *f;
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  XrmDatabase rdb;
 
-  if (dpyinfo)
+  if (dpyinfo
+      && (rdb = XrmGetDatabase (FRAME_X_DISPLAY (f)),
+         rdb != NULL))
     {
-      Display *dpy = FRAME_X_DISPLAY (f);
-      XrmDatabase rdb = XrmGetDatabase (dpy);
-      extern Lisp_Object Vx_resource_name;
-
-      if (rdb)
-       {
-         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 changes = 0;
+      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.menu*foreground: %s",
-                      myname, XSTRING (LFACE_FOREGROUND (lface))->data);
-             XrmPutLineResource (&rdb, line);
-             sprintf (line, "%s.pane.menubar*foreground: %s",
-                      myname, XSTRING (LFACE_FOREGROUND (lface))->data);
-             XrmPutLineResource (&rdb, line);
-             ++changes;
-           }
+      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;
+       }
 
-         if (STRINGP (LFACE_BACKGROUND (lface)))
-           {
-             sprintf (line, "%s*menu*background: %s",
-                      myname, XSTRING (LFACE_BACKGROUND (lface))->data);
-             XrmPutLineResource (&rdb, line);
-             sprintf (line, "%s.pane.menubar*background: %s",
-                      myname, XSTRING (LFACE_BACKGROUND (lface))->data);
-             XrmPutLineResource (&rdb, line);
-             ++changes;
-           }
+      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))))
-           {
+      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
-             char *format1 = "%s.pane.menubar*fontList: %s";
-             char *format2 = "%s*menu*fontList: %s";
+         const char *suffix = "List";
 #else
-             char *format1 = "%s.pane.menubar*font: %s";
-             char *format2 = "%s*menu*font: %s";
-#endif       
-             sprintf (line, format1, myname, face->font_name);
-             XrmPutLineResource (&rdb, line);
-             sprintf (line, format2, myname, face->font_name);
-             XrmPutLineResource (&rdb, line);
-             ++changes;
-           }
-
-         if (changes && f->output_data.x->menubar_widget)
-           {
-             free_frame_menubar (f);
-             set_frame_menubar (f, 1, 1);
-             XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
-           }
+         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;
        }
+
+      if (changed_p && f->output_data.x->menubar_widget)
+       free_frame_menubar (f);
     }
 }
 
+#endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
 
-#endif /* USE_X_TOOLKIT */
 
-#endif /* HAVE_X_WINDOWS */
+DEFUN ("face-attribute-relative-p", Fface_attribute_relative_p, 
+       Sface_attribute_relative_p,
+       2, 2, 0,
+       doc: /* Return non-nil if face ATTRIBUTE VALUE is relative.  */)
+     (attribute, value)
+     Lisp_Object attribute, value;
+{
+  if (EQ (value, Qunspecified))
+    return Qt;
+  else if (EQ (attribute, QCheight))
+    return INTEGERP (value) ? Qnil : Qt;
+  else
+    return Qnil;
+}
 
+DEFUN ("merge-face-attribute", Fmerge_face_attribute, Smerge_face_attribute,
+       3, 3, 0,
+       doc: /* Return face ATTRIBUTE VALUE1 merged with VALUE2.
+If VALUE1 or VALUE2 are absolute (see `face-attribute-relative-p'), then
+the result will be absolute, otherwise it will be relative.  */)
+     (attribute, value1, value2)
+     Lisp_Object attribute, value1, value2;
+{
+  if (EQ (value1, Qunspecified))
+    return value2;
+  else if (EQ (attribute, QCheight))
+    return merge_face_heights (value1, value2, value1, Qnil);
+  else
+    return value1;
+}
 
 
 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)
+       doc: /* Return face attribute KEYWORD of face SYMBOL.
+If SYMBOL does not name a valid Lisp face or KEYWORD isn't a valid
+face attribute name, signal an error.
+If the optional argument FRAME is given, report on face FACE in that
+frame.  If FRAME is t, report on the defaults for face FACE (for new
+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);
+  CHECK_SYMBOL (symbol);
+  CHECK_SYMBOL (keyword);
 
   if (EQ (frame, Qt))
     lface = lface_from_face_name (NULL, symbol, 1);
@@ -4452,7 +4625,7 @@ frames).  If FRAME is omitted or nil, use the selected frame.")
     {
       if (NILP (frame))
        frame = selected_frame;
-      CHECK_LIVE_FRAME (frame, 2);
+      CHECK_LIVE_FRAME (frame);
       lface = lface_from_face_name (XFRAME (frame), symbol, 1);
     }
 
@@ -4497,14 +4670,14 @@ frames).  If FRAME is omitted or nil, use the selected frame.")
 DEFUN ("internal-lisp-face-attribute-values",
        Finternal_lisp_face_attribute_values,
        Sinternal_lisp_face_attribute_values, 1, 1, 0,
-  "Return a list of valid discrete values for face attribute ATTR.\n\
-Value is nil if ATTR doesn't have a discrete set of valid values.")
-  (attr)
+       doc: /* Return a list of valid discrete values for face attribute ATTR.
+Value is nil if ATTR doesn't have a discrete set of valid values.  */)
+     (attr)
      Lisp_Object attr;
 {
   Lisp_Object result = Qnil;
 
-  CHECK_SYMBOL (attr, 0);
+  CHECK_SYMBOL (attr);
 
   if (EQ (attr, QCweight)
       || EQ (attr, QCslant)
@@ -4549,15 +4722,15 @@ Value is nil if ATTR doesn't have a discrete set of valid values.")
 
 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.\n\
-Default face attributes override any local face attributes.")
-  (face, frame)
+       doc: /* Add attributes from frame-default definition of FACE to FACE on FRAME.
+Default face attributes override any local face attributes.  */)
+     (face, frame)
      Lisp_Object face, frame;
 {
   int i;
   Lisp_Object global_lface, local_lface, *gvec, *lvec;
 
-  CHECK_LIVE_FRAME (frame, 1);
+  CHECK_LIVE_FRAME (frame);
   global_lface = lface_from_face_name (NULL, face, 1);
   local_lface = lface_from_face_name (XFRAME (frame), face, 0);
   if (NILP (local_lface))
@@ -4584,13 +4757,13 @@ Default face attributes override any local face attributes.")
    done in fontset.el.  */
 
 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\
-  The font default for a face is either nil, or a list\n\
-  of the form (bold), (italic) or (bold italic).\n\
-If FRAME is omitted or nil, use the selected frame.")
-  (face, frame)
+       doc: /* Return the font name of face FACE, or nil if it is unspecified.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+  The font default for a face is either nil, or a list
+  of the form (bold), (italic) or (bold italic).
+If FRAME is omitted or nil, use the selected frame.  */)
+     (face, frame)
      Lisp_Object face, frame;
 {
   if (EQ (frame, Qt))
@@ -4602,7 +4775,7 @@ If FRAME is omitted or nil, use the selected frame.")
          && !EQ (LFACE_WEIGHT (lface), Qnormal))
        result = Fcons (Qbold, result);
 
-      if (!NILP (LFACE_SLANT (lface))
+      if (!UNSPECIFIEDP (LFACE_SLANT (lface))
          && !EQ (LFACE_SLANT (lface), Qnormal))
        result = Fcons (Qitalic, result);
 
@@ -4668,11 +4841,11 @@ lface_equal_p (v1, v2)
 
 DEFUN ("internal-lisp-face-equal-p", Finternal_lisp_face_equal_p,
        Sinternal_lisp_face_equal_p, 2, 3, 0,
-  "True if FACE1 and FACE2 are equal.\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\
-If FRAME is omitted or nil, use the selected frame.")
-  (face1, face2, frame)
+       doc: /* True if FACE1 and FACE2 are equal.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.  */)
+     (face1, face2, frame)
      Lisp_Object face1, face2, frame;
 {
   int equal_p;
@@ -4698,11 +4871,11 @@ If FRAME is omitted or nil, use the selected frame.")
 
 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\
-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\
-If FRAME is omitted or nil, use the selected frame.")
-  (face, frame)
+       doc: /* True if FACE has no attribute specified.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.  */)
+     (face, frame)
      Lisp_Object face, frame;
 {
   struct frame *f;
@@ -4711,7 +4884,7 @@ If FRAME is omitted or nil, use the selected frame.")
 
   if (NILP (frame))
     frame = selected_frame;
-  CHECK_LIVE_FRAME (frame, 0);
+  CHECK_LIVE_FRAME (frame);
   f = XFRAME (frame);
 
   if (EQ (frame, Qt))
@@ -4729,9 +4902,9 @@ If FRAME is omitted or nil, use the selected frame.")
 
 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist,
        0, 1, 0,
-  "Return an alist of frame-local faces defined on FRAME.\n\
-For internal use only.")
-  (frame)
+       doc: /* Return an alist of frame-local faces defined on FRAME.
+For internal use only.  */)
+     (frame)
      Lisp_Object frame;
 {
   struct frame *f = frame_or_selected_frame (frame, 0);
@@ -4820,7 +4993,7 @@ make_realized_face (attr)
 /* Free realized face FACE, including its X resources.  FACE may
    be null.  */
 
-static void
+void
 free_realized_face (f, face)
      struct frame *f;
      struct face *face;
@@ -4923,6 +5096,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;
 }
 
@@ -4997,11 +5171,10 @@ free_realized_faces (c)
 }
 
 
-/* Free all faces realized for multibyte characters on frame F that
-   has FONTSET.  */
+/* Free all realized faces that are using FONTSET on frame F.  */
 
 void
-free_realized_multibyte_face (f, fontset)
+free_realized_faces_for_fontset (f, fontset)
      struct frame *f;
      int fontset;
 {
@@ -5018,7 +5191,6 @@ free_realized_multibyte_face (f, fontset)
     {
       face = cache->faces_by_id[i];
       if (face
-         && face != face->ascii_face
          && face->fontset == fontset)
        {
          uncache_face (cache, face);
@@ -5398,6 +5570,21 @@ lookup_derived_face (f, symbol, c, face_id)
   return lookup_face (f, attrs, c, default_face);
 }
 
+DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
+       Sface_attributes_as_vector, 1, 1, 0,
+       doc: /* Return a vector of face attributes corresponding to PLIST.  */)
+     (plist)
+     Lisp_Object plist;
+{
+  Lisp_Object lface;
+  lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
+                       Qunspecified);
+  merge_face_vector_with_property (XFRAME (selected_frame),
+                                  XVECTOR (lface)->contents,
+                                  plist);
+  return lface;
+}
+
 
 \f
 /***********************************************************************
@@ -5407,21 +5594,21 @@ lookup_derived_face (f, symbol, c, face_id)
 DEFUN ("internal-set-font-selection-order",
        Finternal_set_font_selection_order,
        Sinternal_set_font_selection_order, 1, 1, 0,
-  "Set font selection order for face font selection to ORDER.\n\
-ORDER must be a list of length 4 containing the symbols `:width',\n\
-`:height', `:weight', and `:slant'.  Face attributes appearing\n\
-first in ORDER are matched first, e.g. if `:height' appears before\n\
-`:weight' in ORDER, font selection first tries to find a font with\n\
-a suitable height, and then tries to match the font weight.\n\
-Value is ORDER.")
-  (order)
-       Lisp_Object order;
+       doc: /* Set font selection order for face font selection to ORDER.
+ORDER must be a list of length 4 containing the symbols `:width',
+`:height', `:weight', and `:slant'.  Face attributes appearing
+first in ORDER are matched first, e.g. if `:height' appears before
+`:weight' in ORDER, font selection first tries to find a font with
+a suitable height, and then tries to match the font weight.
+Value is ORDER.  */)
+     (order)
+     Lisp_Object order;
 {
   Lisp_Object list;
   int i;
   int indices[DIM (font_sort_order)];
 
-  CHECK_LIST (order, 0);
+  CHECK_LIST (order);
   bzero (indices, sizeof indices);
   i = 0;
 
@@ -5467,14 +5654,14 @@ Value is ORDER.")
 DEFUN ("internal-set-alternative-font-family-alist",
        Finternal_set_alternative_font_family_alist,
        Sinternal_set_alternative_font_family_alist, 1, 1, 0,
-  "Define alternative font families to try in face font selection.\n\
-ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.\n\
-Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can\n\
-be found.  Value is ALIST.")
-  (alist)
+       doc: /* Define alternative font families to try in face font selection.
+ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
+Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can
+be found.  Value is ALIST.  */)
+     (alist)
      Lisp_Object alist;
 {
-  CHECK_LIST (alist, 0);
+  CHECK_LIST (alist);
   Vface_alternative_font_family_alist = alist;
   free_all_realized_faces (Qnil);
   return alist;
@@ -5484,14 +5671,14 @@ 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)
+       doc: /* Define alternative font registries to try in face font selection.
+ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
+Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can
+be found.  Value is ALIST.  */)
+     (alist)
      Lisp_Object alist;
 {
-  CHECK_LIST (alist, 0);
+  CHECK_LIST (alist);
   Vface_alternative_font_registry_alist = alist;
   free_all_realized_faces (Qnil);
   return alist;
@@ -5673,9 +5860,8 @@ 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;
@@ -5687,7 +5873,7 @@ may_use_scalable_font_p (font, name)
        {
          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;
        }
     }
@@ -5813,54 +5999,99 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio)
 }
 
 
-/* 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.  */
       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);
        }
+    }
+  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.
 
-      /* Try any family with the given registry.  */
-      if (nfonts == 0)
-       nfonts = font_list (f, Qnil, Qnil, registry, fonts);
+   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 (!NILP (family))
+    nfonts = try_alternative_families (f, family, registry, fonts);
+
+  if (nfonts == 0 && STRINGP (face_family))
+    nfonts = try_alternative_families (f, face_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;
 }
@@ -5886,50 +6117,66 @@ face_fontset (attrs)
 /* Choose a name of font to use on frame F to display character C with
    Lisp face attributes specified by ATTRS.  The font name is
    determined by the font-related attributes in ATTRS and the name
-   pattern for C in FONTSET.  Value is the font name which is
-   allocated from the heap and must be freed by the caller, or NULL if
-   we can get no information about the font name of C.  It is assured
-   that we always get some information for a single byte
-   character.  */
+   pattern for C in FACE->fontset (or Vdefault_fontset if FACE is
+   null).  Value is the font name which is allocated from the heap and
+   must be freed by the caller, or NULL if we can get no information
+   about the font name of C.  It is assured that we always get some
+   information for a single byte character.  */
 
 static char *
-choose_face_font (f, attrs, fontset, c)
+choose_face_font (f, attrs, face, c)
      struct frame *f;
      Lisp_Object *attrs;
-     int fontset, c;
+     struct face *face;
+     int c;
 {
-  Lisp_Object pattern;
+  Lisp_Object val;
+  Lisp_Object pattern, family, registry;
+  Lisp_Object new_attrs[LFACE_VECTOR_SIZE];
   char *font_name = NULL;
   struct font_name *fonts;
   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);
+  /* Get font spec of a font for C.  */
+  pattern = fontset_font_pattern (f, face, c);
   if (NILP (pattern))
     {
       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.  */
+  family = AREF (pattern, FONT_SPEC_FAMILY_INDEX);
+  registry = AREF (pattern, FONT_SPEC_REGISTRY_INDEX);
+
+  bcopy (attrs, new_attrs, sizeof (Lisp_Object) * LFACE_VECTOR_SIZE);
+
+#if 0
+  /* This doesn't work well for the moment.  */
+  if (! NILP (AREF (pattern, FONT_SPEC_WEIGHT_INDEX)))
+    new_attrs[LFACE_WEIGHT_INDEX] = AREF (pattern, FONT_SPEC_WEIGHT_INDEX);
+  if (! NILP (AREF (pattern, FONT_SPEC_SLANT_INDEX)))
+    new_attrs[LFACE_SLANT_INDEX] = AREF (pattern, FONT_SPEC_SLANT_INDEX);
+  if (! NILP (AREF (pattern, FONT_SPEC_SWIDTH_INDEX)))
+    new_attrs[LFACE_SWIDTH_INDEX] = AREF (pattern, FONT_SPEC_SWIDTH_INDEX);
+#endif
+
+  /* If C is an ASCII character, family name in ATTRS has higher
+     priority than what specified in the fontset.  */
   if (STRINGP (attrs[LFACE_FAMILY_INDEX])
-      && SINGLE_BYTE_CHAR_P (c))
-    XCAR (pattern) = Qnil;
+      && ASCII_CHAR_P (c))
+    family = Qnil;
 
   /* 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);
-  width_ratio = (SINGLE_BYTE_CHAR_P (c)
+  nfonts = try_font_list (f, new_attrs, family, registry, &fonts);
+  width_ratio = (ASCII_CHAR_P (c)
                 ? 1
-                : CHARSET_WIDTH (CHAR_CHARSET (c)));
-  font_name = best_matching_font (f, attrs, fonts, nfonts, width_ratio);
+                : CHAR_WIDTH (c));
+  font_name = best_matching_font (f, new_attrs, fonts, nfonts, width_ratio);
   return font_name;
 }
 
@@ -5950,16 +6197,19 @@ 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);
+      realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
       realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
-      realize_named_face (f, Qfringe, BITMAP_AREA_FACE_ID);
+      realize_named_face (f, Qfringe, FRINGE_FACE_ID);
       realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
       realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
       realize_named_face (f, Qborder, BORDER_FACE_ID);
@@ -5968,17 +6218,18 @@ realize_basic_faces (f)
       realize_named_face (f, Qmenu, MENU_FACE_ID);
 
       /* Reflect changes in the `menu' face in menu bars.  */
-      if (menu_face_change_count)
+      if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
        {
-         menu_face_change_count = 0;
+         FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
 #ifdef USE_X_TOOLKIT
-         x_set_menu_face_resources (f);
+         x_update_menu_appearance (f);
 #endif
        }
       
       success_p = 1;
     }
 
+  unbind_to (count, Qnil);
   UNBLOCK_INPUT;
   return success_p;
 }
@@ -6023,8 +6274,10 @@ realize_default_face (f)
       LFACE_FAMILY (lface) = build_string ("default");
       LFACE_SWIDTH (lface) = Qnormal;
       LFACE_HEIGHT (lface) = make_number (1);
-      LFACE_WEIGHT (lface) = Qnormal;
-      LFACE_SLANT (lface) = Qnormal;
+      if (UNSPECIFIEDP (LFACE_WEIGHT (lface)))
+       LFACE_WEIGHT (lface) = Qnormal;
+      if (UNSPECIFIEDP (LFACE_SLANT (lface)))
+       LFACE_SLANT (lface) = Qnormal;
       LFACE_AVGWIDTH (lface) = Qunspecified;
     }
 
@@ -6200,21 +6453,16 @@ realize_x_face (cache, attrs, c, base_face)
 
   f = cache->f;
 
-  /* If C is a multibyte character, we share all face attirbutes with
+  /* If C is a non-ASCII character, we share all face attirbutes with
      BASE_FACE including the realized fontset.  But, we must load a
      different font.  */
-  if (!SINGLE_BYTE_CHAR_P (c))
+  if (! ASCII_CHAR_P (c))
     {
       bcopy (base_face, face, sizeof *face);
       face->gc = 0;
 
       /* 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->overline_color_defaulted_p = 1;
-      face->strike_through_color_defaulted_p = 1;
-      face->box_color_defaulted_p = 1;
+      face->colors_copied_bitwise_p = 1;
 
       /* to force realize_face to load font */
       face->font = NULL;
@@ -6263,7 +6511,7 @@ realize_x_face (cache, attrs, c, base_face)
       if (STRINGP (attrs[LFACE_FONT_INDEX]))
         {
           struct font_info *font_info =
-            FS_LOAD_FONT (f, 0, XSTRING (attrs[LFACE_FONT_INDEX])->data, -1);
+            FS_LOAD_FONT (f, XSTRING (attrs[LFACE_FONT_INDEX])->data);
           if (font_info)
             face->font = font_info->font;
         }
@@ -6555,13 +6803,13 @@ realize_tty_face (cache, attrs, c)
 DEFUN ("tty-suppress-bold-inverse-default-colors",
        Ftty_suppress_bold_inverse_default_colors,
        Stty_suppress_bold_inverse_default_colors, 1, 1, 0,
-  "Suppress/allow boldness of faces with inverse default colors.\n\
-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, the bold face attribute is ignored if this variable\n\
-is non-nil.")
-  (suppress)
+       doc: /* Suppress/allow boldness of faces with inverse default colors.
+SUPPRESS non-nil means suppress it.
+This affects bold faces on TTYs whose foreground is the default background
+color of the display and whose background is the default foreground color.
+For such faces, the bold face attribute is ignored if this variable
+is non-nil.  */)
+     (suppress)
      Lisp_Object suppress;
 {
   tty_suppress_bold_inverse_default_colors_p = !NILP (suppress);
@@ -6587,7 +6835,7 @@ compute_char_face (f, ch, prop)
   int face_id;
 
   if (NILP (current_buffer->enable_multibyte_characters))
-    ch = -1;
+    ch = 0;
 
   if (NILP (prop))
     {
@@ -6606,7 +6854,6 @@ compute_char_face (f, ch, prop)
   return face_id;
 }
 
-
 /* Return the face ID associated with buffer position POS for
    displaying ASCII characters.  Return in *ENDPTR the position at
    which a different face is needed, as far as text properties and
@@ -6877,8 +7124,8 @@ dump_realized_face (face)
 }
 
 
-DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
-   (n)
+DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: /* */)
+     (n)
      Lisp_Object n;
 {
   if (NILP (n))
@@ -6900,7 +7147,7 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
   else
     {
       struct face *face;
-      CHECK_NUMBER (n, 0);
+      CHECK_NUMBER (n);
       face = FACE_FROM_ID (SELECTED_FRAME (), XINT (n));
       if (face == NULL)
        error ("Not a valid face");
@@ -6912,8 +7159,8 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
 
 
 DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
-       0, 0, 0, "")
-  ()
+       0, 0, 0, doc: /* */)
+     ()
 {
   fprintf (stderr, "number of colors = %d\n", ncolors_allocated);
   fprintf (stderr, "number of pixmaps = %d\n", npixmaps_allocated);
@@ -7059,12 +7306,16 @@ syms_of_xfaces ()
   staticpro (&Qborder);
   Qmouse = intern ("mouse");
   staticpro (&Qmouse);
+  Qmode_line_inactive = intern ("mode-line-inactive");
+  staticpro (&Qmode_line_inactive);
   Qtty_color_desc = intern ("tty-color-desc");
   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);
@@ -7081,6 +7332,8 @@ syms_of_xfaces ()
 #endif
   defsubr (&Scolor_gray_p);
   defsubr (&Scolor_supported_p);
+  defsubr (&Sface_attribute_relative_p);
+  defsubr (&Smerge_face_attribute);
   defsubr (&Sinternal_get_lisp_face_attribute);
   defsubr (&Sinternal_lisp_face_attribute_values);
   defsubr (&Sinternal_lisp_face_equal_p);
@@ -7092,6 +7345,7 @@ syms_of_xfaces ()
   defsubr (&Sinternal_set_font_selection_order);
   defsubr (&Sinternal_set_alternative_font_family_alist);
   defsubr (&Sinternal_set_alternative_font_registry_alist);
+  defsubr (&Sface_attributes_as_vector);
 #if GLYPH_DEBUG
   defsubr (&Sdump_face);
   defsubr (&Sshow_face_resources);
@@ -7104,43 +7358,40 @@ syms_of_xfaces ()
 #endif
 
   DEFVAR_LISP ("font-list-limit", &Vfont_list_limit,
-    "*Limit for font matching.\n\
-If an integer > 0, font matching functions won't load more than\n\
-that number of fonts when searching for a matching font.");
+              doc: /* *Limit for font matching.
+If an integer > 0, font matching functions won't load more than
+that number of fonts when searching for a matching font.  */);
   Vfont_list_limit = make_number (DEFAULT_FONT_LIST_LIMIT);
 
   DEFVAR_LISP ("face-new-frame-defaults", &Vface_new_frame_defaults,
-    "List of global face definitions (for internal use only.)");
+    doc: /* 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\
-instead of shades of gray for a face background color.\n\
-See `set-face-stipple' for possible values for this variable.");
+    doc: /* *Default stipple pattern used on monochrome displays.
+This stipple pattern is used on monochrome displays
+instead of shades of gray for a face background color.
+See `set-face-stipple' for possible values for this variable.  */);
   Vface_default_stipple = build_string ("gray3");
 
   DEFVAR_LISP ("tty-defined-color-alist", &Vtty_defined_color_alist,
-   "An alist of defined terminal colors and their RGB values.");
+   doc: /* An alist of defined terminal colors and their RGB values.  */);
   Vtty_defined_color_alist = Qnil;
 
   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.");
-#if defined (WINDOWSNT) || defined (macintosh)
-  /* Windows uses mainly truetype fonts, so disallowing scalable fonts
-     by default limits the fonts available severely. */
-  Vscalable_fonts_allowed = Qt;
-#else
+              doc: /* Allowed scalable fonts.
+A value of nil means don't allow any scalable fonts.
+A value of t means allow 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.
+Note that if value is nil, a scalable font might still be used, if no
+other font of the appropriate family and registry is available.  */);
   Vscalable_fonts_allowed = Qnil;
-#endif
 
   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.");
+              doc: /* List of ignored fonts.
+Each element is a regular expression that matches names of fonts to
+ignore.  */);
   Vface_ignored_fonts = Qnil;
 
 #ifdef HAVE_WINDOW_SYSTEM