*** empty log message ***
[bpt/emacs.git] / src / xfaces.c
index 17f9c59..51cb455 100644 (file)
@@ -1,5 +1,6 @@
 /* xfaces.c -- "Face" primitives.
-   Copyright (C) 1993, 1994, 1998, 1999, 2000 Free Software Foundation.
+   Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001
+   Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -156,10 +157,17 @@ 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.
 
@@ -179,15 +187,6 @@ 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>
@@ -197,14 +196,15 @@ Boston, MA 02111-1307, USA.  */
 
 #ifdef HAVE_WINDOW_SYSTEM
 #include "fontset.h"
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
+
 #ifdef HAVE_X_WINDOWS
 #include "xterm.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"
@@ -224,6 +224,33 @@ Boston, MA 02111-1307, USA.  */
 /* For historic reasons, FONT_WIDTH refers to average width on W32,
    not maximum as on X. Redefine here. */
 #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"
@@ -261,6 +288,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)
@@ -356,15 +387,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
+
+/* 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.  */
@@ -428,6 +467,10 @@ 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
@@ -435,6 +478,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
@@ -476,6 +524,8 @@ 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,
@@ -633,9 +683,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.  */
@@ -652,11 +702,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);
     }
 }
 
@@ -680,10 +730,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);
     }
 }
 
@@ -1309,7 +1359,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
@@ -1740,6 +1789,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},
@@ -1793,6 +1843,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
@@ -1805,8 +1858,11 @@ 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
@@ -2054,14 +2110,13 @@ 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]);
+  double font_pixel = atoi (font->fields[XLFD_PIXEL_SIZE]);
   int real_pt;
 
-  if (font_resy == 0 || font_pt == 0)
+  if (font_pixel == 0)
     real_pt = 0;
   else
-    real_pt = (font_resy / resy) * font_pt + 0.5;
+    real_pt = PT_PER_INCH * 10.0 * font_pixel / resy + 0.5;
 
   return real_pt;
 }
@@ -2080,8 +2135,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;
@@ -2139,6 +2195,10 @@ split_font_name (f, font, numeric_p)
       font->numeric[XLFD_SWIDTH] = xlfd_numeric_swidth (font);
     }
 
+  /* Initialize it to zero.  It will be overridden by font_list while
+     trying alternate registries.  */
+  font->registry_priority = 0;
+
   return success_p;
 }
 
@@ -2221,12 +2281,7 @@ sort_fonts (f, fonts, nfonts, cmpfn)
 
    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,
@@ -2237,89 +2292,60 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
      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;
 
-  /* 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;
+#else
+  lfonts = x_list_fonts (f, lpattern, scalable_fonts_p ? -1 : 0, nfonts);
+#endif
 
-  /* Count fonts returned */
+  /* 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++;
-
-  /* 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);
-    }
-#endif
+      Lisp_Object elt, tail;
+      char *name = XSTRING (XCAR (tem))->data;
 
-  if (names)
-    {
-      /* Make a copy of the font names we got from X, and
-        split them into fields.  */
-      for (i = j = 0; i < n; ++i)
+      for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
        {
-         /* Make a copy of the font name.  */
-         fonts[j].name = xstrdup (names[i]);
-
-         /* 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))
-           {
-#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 */
-           }
-         else
-           ++j;
+         elt = XCAR (tail);
+         if (STRINGP (elt)
+             && fast_c_string_match_ignore_case (elt, name) >= 0)
+           break;
        }
+      if (!NILP (tail))
+       continue;
 
-      n = j;
+      /* Make a copy of the font name.  */
+      fonts[n].name = xstrdup (name);
 
-#ifdef HAVE_X_WINDOWS
-      /* Free font names.  */
-      BLOCK_INPUT;
-      XFreeFontNames (names);
-      UNBLOCK_INPUT;
-#endif
+      /* 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 (!scalable_fonts_p
+             || !may_use_scalable_font_p (fonts + n, name))
+           xfree (fonts[n].name);
+         else
+           ++n;
+       }
+      else
+       ++n;
     }
 
-
   /* If no fonts found, try patterns from Valternate_fontname_alist.  */
   if (n == 0 && try_alternatives_p)
     {
@@ -2410,11 +2436,7 @@ sorted_font_list (f, pattern, cmpfn, fonts)
     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
      fonts were found, make sure to set *FONTS to null.  */
@@ -2481,7 +2503,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;
@@ -2515,6 +2537,83 @@ font_list (f, pattern, family, registry, fonts)
 }
 
 
+/* Concatenate font list FONTS1 and FONTS2.  FONTS1 and FONTS2
+   contains NFONTS1 fonts and NFONTS2 fonts respectively.  Return a
+   pointer to a newly allocated font list.  FONTS1 and FONTS2 are
+   freed.  */
+
+static struct font_name *
+concat_font_list (fonts1, nfonts1, fonts2, nfonts2)
+     struct font_name *fonts1, *fonts2;
+     int nfonts1, nfonts2;
+{
+  int new_nfonts = nfonts1 + nfonts2;
+  struct font_name *new_fonts;
+
+  new_fonts = (struct font_name *) xmalloc (sizeof *new_fonts * new_nfonts);
+  bcopy (fonts1, new_fonts, sizeof *new_fonts * nfonts1);
+  bcopy (fonts2, new_fonts + nfonts1, sizeof *new_fonts * nfonts2);
+  xfree (fonts1);
+  xfree (fonts2);
+  return new_fonts;
+}
+
+
+/* Get a sorted list of fonts of family FAMILY on frame F.
+
+   If PATTERN is non-nil list fonts matching that pattern.
+
+   If REGISTRY is non-nil, 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.  */
@@ -2703,9 +2802,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));
@@ -2865,7 +2966,7 @@ resolve_face_name (face_name)
   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))
@@ -2879,10 +2980,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.  */
@@ -3059,6 +3160,7 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
 
   return 1;
 }
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 
@@ -3112,7 +3214,7 @@ merge_face_heights (from, to, invalid, gcpro)
 
       args[0] = from;
       args[1] = to;
-      height = call_function (2, args);
+      height = safe_call (2, args);
 
       UNGCPRO;
 
@@ -3128,10 +3230,12 @@ merge_face_heights (from, to, invalid, gcpro)
 
 
 /* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
-   store the resulting attributes in TO.  Every non-nil attribute of
-   FROM overrides the corresponding attribute of TO.  CYCLE_CHECK is
-   used internally to detect loops in face inheritance; it should be
-   Qnil when called from other places.  */
+   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 (f, from, to, cycle_check)
@@ -3150,6 +3254,18 @@ merge_face_vectors (f, from, to, cycle_check)
       && !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])))
+    to[LFACE_FONT_INDEX] = Qnil;
+
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (!UNSPECIFIEDP (from[i]))
       if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
@@ -3176,16 +3292,23 @@ merge_face_vectors (f, from, to, cycle_check)
    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))                                                    \
-   : Fmemq ((el), (check))                                                   \
-   ? Qnil                                                                    \
-   : Fcons ((el), (check)))
+#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)
@@ -3593,10 +3716,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 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;
 {
@@ -3612,6 +3736,17 @@ frame.")
 
   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);
@@ -3644,12 +3779,11 @@ frame.")
     {
       if (!UNSPECIFIEDP (value))
        {
-         Lisp_Object test = Qnil;
-
-         if (!EQ (face, Qdefault))
-           /* The default face must have an absolute size, otherwise, we do
-              a test merge with a random height to see if VALUE's ok. */
-           test = merge_face_heights (value, make_number(10), Qnil, Qnil);
+         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);
@@ -3929,8 +4063,7 @@ frame.")
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-  if (!EQ (frame, Qt)
-      && !UNSPECIFIEDP (value)
+  if (!UNSPECIFIEDP (value)
       && NILP (Fequal (old_value, value)))
     {
       Lisp_Object param;
@@ -3959,7 +4092,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
@@ -3981,9 +4114,24 @@ frame.")
          if (EQ (attr, QCbackground))
            param = Qmouse_color;
        }
+      else if (EQ (face, Qmenu))
+       ++menu_face_change_count;
 
       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 */
@@ -4005,23 +4153,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);
 }
 
 
@@ -4095,6 +4248,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);
@@ -4102,7 +4256,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;
 }
 
@@ -4293,7 +4448,6 @@ xm_set_menu_resources_from_menu_face (f, widget)
     }
 }
 
-
 #endif /* USE_MOTIF */
 
 #ifdef USE_LUCID
@@ -4384,12 +4538,14 @@ x_set_menu_resources_from_menu_face (f, widget)
   if (f->face_cache->used == 0)
     recompute_basic_faces (f);
 
+  BLOCK_INPUT;
 #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
+  UNBLOCK_INPUT;
 }
 
 #endif /* USE_X_TOOLKIT */
@@ -4518,21 +4674,32 @@ 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.")
+  "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 (XFRAME (frame),
-                     XVECTOR (global_lface)->contents,
-                     XVECTOR (local_lface)->contents,
-                     Qnil);
-  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;
 }
 
 
@@ -4571,7 +4738,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;
     }
 }
 
@@ -4836,6 +5003,9 @@ prepare_face_for_display (f, face)
 #endif
 #ifdef WINDOWSNT
          xgcv.font = face->font;
+#endif
+#ifdef macintosh
+         xgcv.font = face->font;
 #endif
          mask |= GCFont;
        }
@@ -5186,7 +5356,9 @@ lookup_face (f, attr, c, base_face)
 
 
 /* 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)
@@ -5198,6 +5370,13 @@ 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 (f, symbol_attrs, attrs, Qnil);
@@ -5270,7 +5449,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);
@@ -5314,6 +5494,7 @@ face_with_height (f, face_id, height)
   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
@@ -5426,6 +5607,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
@@ -5450,6 +5648,10 @@ 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
@@ -5472,6 +5674,9 @@ 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)
@@ -5489,12 +5694,10 @@ better_font_p (values, font1, font2, compare_pt_p)
        }
     }
 
-  return 0;
+  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.  */
@@ -5535,12 +5738,12 @@ 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.  */
@@ -5603,7 +5806,6 @@ may_use_scalable_font_p (font, name)
   return 0;
 }
 
-#endif /* SCALABLE_FONTS != 0 */
 
 
 /* Return the name of the best matching font for face attributes
@@ -5620,7 +5822,7 @@ best_matching_font (f, attrs, fonts, nfonts)
 {
   char *font_name;
   struct font_name *best;
-  int i, pt;
+  int i, pt = 0;
   int specified[4];
   int exact_p;
 
@@ -5645,9 +5847,6 @@ best_matching_font (f, attrs, fonts, nfonts)
        abort ();
     }
 
-#if SCALABLE_FONTS
-
-  /* Set to 1 */
   exact_p = 0;
 
   /* Start with the first non-scalable font in the list.  */
@@ -5710,22 +5909,6 @@ best_matching_font (f, attrs, fonts, nfonts)
   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);
 
@@ -5751,13 +5934,11 @@ try_font_list (f, attrs, pattern, family, registry, fonts)
     family = attrs[LFACE_FAMILY_INDEX];
 
   nfonts = font_list (f, pattern, family, registry, fonts);
-
   if (nfonts == 0 && !NILP (family))
     {
       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);
@@ -5797,7 +5978,6 @@ face_fontset (attrs)
      Lisp_Object *attrs;
 {
   Lisp_Object name;
-  int fontset;
 
   name = attrs[LFACE_FONT_INDEX];
   if (!STRINGP (name))
@@ -5886,6 +6066,22 @@ 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 (menu_face_change_count)
+       {
+         menu_face_change_count = 0;
+         
+#ifdef USE_X_TOOLKIT
+         if (FRAME_X_P (f))
+           {
+             Widget menu = f->output_data.x->menubar_widget;
+             if (menu)
+               x_set_menu_resources_from_menu_face (f, menu);
+           }
+#endif /* USE_X_TOOLKIT */
+       }
+      
       success_p = 1;
     }
 
@@ -5907,7 +6103,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);
@@ -5925,7 +6120,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 */
 
@@ -5963,7 +6158,9 @@ realize_default_face (f)
        LFACE_FOREGROUND (lface) = XCDR (color);
       else if (FRAME_WINDOW_P (f))
        return 0;
-      else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+      else if (FRAME_TERMCAP_P (f)
+              || FRAME_MSDOS_P (f)
+              || FRAME_W32_CONSOLE_P (f))
        LFACE_FOREGROUND (lface) = build_string (unspecified_fg);
       else
        abort ();
@@ -5978,7 +6175,9 @@ realize_default_face (f)
        LFACE_BACKGROUND (lface) = XCDR (color);
       else if (FRAME_WINDOW_P (f))
        return 0;
-      else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+      else if (FRAME_TERMCAP_P (f)
+              || FRAME_MSDOS_P (f)
+              || FRAME_W32_CONSOLE_P (f))
        LFACE_BACKGROUND (lface) = build_string (unspecified_bg);
       else
        abort ();
@@ -6065,7 +6264,9 @@ realize_face (cache, attrs, c, base_face, former_face_id)
 
   if (FRAME_WINDOW_P (cache->f))
     face = realize_x_face (cache, attrs, c, base_face);
-  else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
+  else if (FRAME_TERMCAP_P (cache->f)
+          || FRAME_MSDOS_P (cache->f)
+          || FRAME_W32_CONSOLE_P (cache->f))
     face = realize_tty_face (cache, attrs, c);
   else
     abort ();
@@ -6166,6 +6367,18 @@ realize_x_face (cache, attrs, c, base_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.  */
@@ -6405,11 +6618,14 @@ realize_tty_face (cache, attrs, c)
   struct frame *f = cache->f;
 
   /* Frame must be a termcap frame.  */
-  xassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
+  xassert (FRAME_TERMCAP_P (cache->f)
+          || FRAME_MSDOS_P (cache->f)
+          || FRAME_W32_CONSOLE_P (cache->f));
 
   /* Allocate a new realized face.  */
   face = make_realized_face (attrs);
-  face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
+  face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" 
+    : FRAME_W32_CONSOLE_P (cache->f) ? "w32console" : "tty";
 
   /* Map face attributes to TTY appearances.  We map slant to
      dimmed text because we want italic text to appear differently
@@ -6540,7 +6756,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.  */
@@ -6645,10 +6860,10 @@ 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.
 
    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
@@ -6961,8 +7176,12 @@ syms_of_xfaces ()
   Qtty_color_alist = intern ("tty-color-alist");
   staticpro (&Qtty_color_alist);
 
+  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);
@@ -6982,6 +7201,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);
@@ -7014,22 +7234,24 @@ See `set-face-stipple' for possible values for this variable.");
    "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
+#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
   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);