(menu_face_changed_default): New variable.
[bpt/emacs.git] / src / xfaces.c
index cad7c07..e39dfe2 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.
 
@@ -56,7 +57,7 @@ Boston, MA 02111-1307, USA.  */
    type, and, for simple boxes, in what color.
 
    14. Font or fontset pattern, or nil.  This is a special attribute.
-   When this attribyte is specified, the face uses a font opened by
+   When this attribute is specified, the face uses a font opened by
    that pattern as is.  In addition, all the other font-related
    attributes (1st thru 5th) are generated from the opened font name.
    On the other hand, if one of the other font-related attributes are
@@ -67,6 +68,10 @@ Boston, MA 02111-1307, USA.  */
 
    15. A face name or list of face names from which to inherit attributes.
 
+   16. A specified average font width, which is invisible from Lisp,
+   and is used to ensure that a font specified on the command line,
+   for example, can be matched exactly.
+
    Faces are frame-local by nature because Emacs allows to define the
    same named face (face names are symbols) differently for different
    frames.  Each frame has an alist of face definitions for all named
@@ -118,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.
@@ -156,12 +161,19 @@ Boston, MA 02111-1307, USA.  */
    width---tries to find a best match for the specified font height,
    etc.
 
-   2. Setting face-alternative-font-family-alist allows the user to
+   2. Setting face-font-family-alternatives allows the user to
    specify alternative font families to try if a family specified by a
    face doesn't exist.
 
+   3. Setting face-font-registry-alternatives allows the user to
+   specify all alternative font registries to try for a face
+   specifying a registry.
+
+   4. Setting face-ignored-fonts allows the user to ignore specific
+   fonts.
+
 
-   Character compositition.
+   Character composition.
 
    Usually, the realization process is already finished when Emacs
    actually reflects the desired glyph matrix on the screen.  However,
@@ -184,6 +196,7 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/stat.h>
 #include "lisp.h"
 #include "charset.h"
+#include "keyboard.h"
 #include "frame.h"
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -207,6 +220,7 @@ Boston, MA 02111-1307, USA.  */
 #include "fontset.h"
 /* Redefine X specifics to W32 equivalents to avoid cluttering the
    code with #ifdef blocks. */
+#undef FRAME_X_DISPLAY_INFO
 #define FRAME_X_DISPLAY_INFO FRAME_W32_DISPLAY_INFO
 #define x_display_info w32_display_info
 #define FRAME_X_FONT_TABLE FRAME_W32_FONT_TABLE
@@ -215,6 +229,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 */
 
@@ -272,7 +287,6 @@ x_free_gc (f, gc)
 
 #include <stdio.h>
 #include <ctype.h>
-#include "keyboard.h"
 
 #ifndef max
 #define max(A, B)      ((A) > (B) ? (A) : (B))
@@ -280,6 +294,10 @@ x_free_gc (f, gc)
 #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)
@@ -387,7 +405,11 @@ 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. */
+
+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.  */
@@ -451,10 +473,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
@@ -475,6 +493,10 @@ static int npixmaps_allocated;
 static int ngcs;
 #endif
 
+/* Non-zero means the definition of the `menu' face for new frames has
+   been changed.  */
+
+int menu_face_changed_default;
 
 \f
 /* Function prototypes.  */
@@ -485,14 +507,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));
-static int first_font_matching P_ ((struct frame *f, char *,
-                                   struct font_name *));
+                             int, int));
 static int x_face_list_fonts P_ ((struct frame *, char *,
-                                 struct font_name *, int, int, int));
+                                 struct font_name *, int, int));
 static int font_scalable_p P_ ((struct font_name *));
 static int get_lface_attributes P_ ((struct frame *, Lisp_Object, Lisp_Object *, int));
 static int load_pixmap P_ ((struct frame *, Lisp_Object, unsigned *, unsigned *));
@@ -512,8 +532,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));
@@ -549,7 +571,7 @@ static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
 static struct face *make_realized_face P_ ((Lisp_Object *));
 static void free_realized_faces P_ ((struct face_cache *));
 static char *best_matching_font P_ ((struct frame *, Lisp_Object *,
-                                    struct font_name *, int));
+                                    struct font_name *, int, int));
 static void cache_face P_ ((struct face_cache *, struct face *, unsigned));
 static void uncache_face P_ ((struct face_cache *, struct face *));
 static int xlfd_numeric_slant P_ ((struct font_name *));
@@ -575,12 +597,16 @@ static void sort_fonts P_ ((struct frame *, struct font_name *, int,
                               int (*cmpfn) P_ ((const void *, const void *))));
 static GC x_create_gc P_ ((struct frame *, unsigned long, XGCValues *));
 static void x_free_gc P_ ((struct frame *, GC));
-static void clear_font_table P_ ((struct frame *));
+static void clear_font_table P_ ((struct x_display_info *));
 
 #ifdef WINDOWSNT
 extern Lisp_Object w32_list_fonts P_ ((struct frame *, Lisp_Object, int, int));
 #endif /* WINDOWSNT */
 
+#ifdef USE_X_TOOLKIT
+static void x_update_menu_appearance P_ ((struct frame *));
+#endif /* USE_X_TOOLKIT */
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 \f
@@ -686,11 +712,11 @@ x_free_colors (f, pixels, npixels)
      necessary and some servers don't allow it.  So don't do it.  */
   if (class != StaticColor && class != StaticGray && class != TrueColor)
     {
-      XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
-                  pixels, npixels, 0);
 #ifdef DEBUG_X_COLORS
       unregister_colors (pixels, npixels);
 #endif
+      XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+                  pixels, npixels, 0);
     }
 }
 
@@ -714,10 +740,10 @@ x_free_dpy_colors (dpy, screen, cmap, pixels, npixels)
      necessary and some servers don't allow it.  So don't do it.  */
   if (class != StaticColor && class != StaticGray && class != TrueColor)
     {
-      XFreeColors (dpy, cmap, pixels, npixels, 0);
 #ifdef DEBUG_X_COLORS
       unregister_colors (pixels, npixels);
 #endif
+      XFreeColors (dpy, cmap, pixels, npixels, 0);
     }
 }
 
@@ -953,6 +979,14 @@ clear_face_cache (clear_fonts_p)
   if (clear_fonts_p
       || ++clear_font_table_count == CLEAR_FONT_TABLE_COUNT)
     {
+      struct x_display_info *dpyinfo;
+      
+      /* Fonts are common for frames on one display, i.e. on
+        one X screen.  */
+      for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+       if (dpyinfo->n_fonts > CLEAR_FONT_TABLE_NFONTS)
+         clear_font_table (dpyinfo);
+      
       /* From time to time see if we can unload some fonts.  This also
         frees all realized faces on all frames.  Fonts needed by
         faces will be loaded again when faces are realized again.  */
@@ -960,13 +994,10 @@ clear_face_cache (clear_fonts_p)
 
       FOR_EACH_FRAME (tail, frame)
        {
-         f = XFRAME (frame);
+         struct frame *f = XFRAME (frame);
          if (FRAME_WINDOW_P (f)
              && FRAME_X_DISPLAY_INFO (f)->n_fonts > CLEAR_FONT_TABLE_NFONTS)
-           {
-             free_all_realized_faces (frame);
-             clear_font_table (f);
-           }
+           free_all_realized_faces (frame);
        }
     }
   else
@@ -989,10 +1020,10 @@ clear_face_cache (clear_fonts_p)
 DEFUN ("clear-face-cache", Fclear_face_cache, Sclear_face_cache, 0, 1, 0,
   "Clear face caches on all frames.\n\
 Optional THOROUGHLY non-nil means try to free unused fonts, too.")
-  (thorougly)
-     Lisp_Object thorougly;
+  (thoroughly)
+     Lisp_Object thoroughly;
 {
-  clear_face_cache (!NILP (thorougly));
+  clear_face_cache (!NILP (thoroughly));
   ++face_change_count;
   ++windows_or_buffers_changed;
   return Qnil;
@@ -1003,26 +1034,37 @@ Optional THOROUGHLY non-nil means try to free unused fonts, too.")
 #ifdef HAVE_WINDOW_SYSTEM
 
 
-/* Remove those fonts from the font table of frame F exept for the
-   default ASCII font for the frame.  Called from clear_face_cache
+/* Remove fonts from the font table of DPYINFO except for the default
+   ASCII fonts of frames on that display.  Called from clear_face_cache
    from time to time.  */
 
 static void
-clear_font_table (f)
-     struct frame *f;
+clear_font_table (dpyinfo)
+     struct x_display_info *dpyinfo;
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   int i;
 
-  xassert (FRAME_WINDOW_P (f));
-
-  /* Free those fonts that are not used by the frame F as the default.  */
+  /* Free those fonts that are not used by frames on DPYINFO.  */
   for (i = 0; i < dpyinfo->n_fonts; ++i)
     {
       struct font_info *font_info = dpyinfo->font_table + i;
+      Lisp_Object tail, frame;
 
-      if (!font_info->name
-         || font_info->font == FRAME_FONT (f))
+      /* 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 (!NILP (tail))
        continue;
 
       /* Free names.  */
@@ -1605,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
 }
 
@@ -1843,7 +1888,9 @@ static struct frame *font_frame;
    set via set-face-font-sort-order.  */
 
 #ifdef macintosh
-static int font_sort_order[4] = { XLFD_SWIDTH, XLFD_POINT_SIZE, XLFD_WEIGHT, XLFD_SLANT };
+static int font_sort_order[4] = {
+  XLFD_SWIDTH, XLFD_POINT_SIZE, XLFD_WEIGHT, XLFD_SLANT
+};
 #else
 static int font_sort_order[4];
 #endif
@@ -2094,14 +2141,41 @@ xlfd_point_size (f, font)
      struct font_name *font;
 {
   double resy = FRAME_X_DISPLAY_INFO (f)->resy;
-  double font_resy = atoi (font->fields[XLFD_RESY]);
-  double font_pt = atoi (font->fields[XLFD_POINT_SIZE]);
+  char *pixel_field = font->fields[XLFD_PIXEL_SIZE];
+  double pixel;
   int real_pt;
 
-  if (font_resy == 0 || font_pt == 0)
+  if (*pixel_field == '[')
+    {
+      /* The pixel size field is `[A B C D]' which specifies
+        a transformation matrix.
+
+        A  B  0
+        C  D  0
+        0  0  1
+
+        by which all glyphs of the font are transformed.  The spec
+        says that s scalar value N for the pixel size is equivalent
+        to A = N * resx/resy, B = C = 0, D = N.  */
+      char *start = pixel_field + 1, *end;
+      double matrix[4];
+      int i;
+
+      for (i = 0; i < 4; ++i)
+       {
+         matrix[i] = strtod (start, &end);
+         start = end;
+       }
+
+      pixel = matrix[3];
+    }
+  else
+    pixel = atoi (pixel_field);
+  
+  if (pixel == 0)
     real_pt = 0;
   else
-    real_pt = (font_resy / resy) * font_pt + 0.5;
+    real_pt = PT_PER_INCH * 10.0 * pixel / resy + 0.5;
 
   return real_pt;
 }
@@ -2120,8 +2194,9 @@ pixel_point_size (f, pixel)
   double real_pt;
   int int_pt;
 
-  /* As one inch is 72 points, 72/RESY gives the point size of one dot.  */
-  real_pt = pixel * 72 / resy;
+  /* As one inch is PT_PER_INCH points, PT_PER_INCH/RESY gives the
+     point size of one dot.  */
+  real_pt = pixel * PT_PER_INCH / resy;
   int_pt = real_pt + 0.5;
 
   return int_pt;
@@ -2134,9 +2209,7 @@ pixel_point_size (f, pixel)
    XLFD_RESY, XLFD_SLANT, and XLFD_WEIGHT in FONT->numeric.  Value is
    zero if the font name doesn't have the format we expect.  The
    expected format is a font name that starts with a `-' and has
-   XLFD_LAST fields separated by `-'.  (The XLFD specification allows
-   forms of font names where certain field contents are enclosed in
-   square brackets.  We don't support that, for now.  */
+   XLFD_LAST fields separated by `-'.  */
 
 static int
 split_font_name (f, font, numeric_p)
@@ -2156,6 +2229,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;
 
@@ -2177,6 +2277,7 @@ split_font_name (f, font, numeric_p)
       font->numeric[XLFD_SLANT] = xlfd_numeric_slant (font);
       font->numeric[XLFD_WEIGHT] = xlfd_numeric_weight (font);
       font->numeric[XLFD_SWIDTH] = xlfd_numeric_swidth (font);
+      font->numeric[XLFD_AVGWIDTH] = atoi (font->fields[XLFD_AVGWIDTH]);
     }
 
   /* Initialize it to zero.  It will be overridden by font_list while
@@ -2260,109 +2361,77 @@ sort_fonts (f, fonts, nfonts, cmpfn)
    display in x_display_list.  FONTS is a pointer to a vector of
    NFONTS font_name structures.  TRY_ALTERNATIVES_P non-zero means try
    alternative patterns from Valternate_fontname_alist if no fonts are
-   found matching PATTERN.  SCALABLE_FONTS_P non-zero means include
-   scalable fonts.
+   found matching PATTERN.
 
    For all fonts found, set FONTS[i].name to the name of the font,
    allocated via xmalloc, and split font names into fields.  Ignore
-   fonts that we can't parse.  Value is the number of fonts found.
-
-   This is similar to x_list_fonts.  The differences are:
-
-   1. It avoids consing.
-   2. It never calls XLoadQueryFont.  */
+   fonts that we can't parse.  Value is the number of fonts found.  */
 
 static int
-x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
-                  scalable_fonts_p)
+x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p)
      struct frame *f;
      char *pattern;
      struct font_name *fonts;
      int nfonts, try_alternatives_p;
-     int scalable_fonts_p;
 {
-  int n, i, j;
-  char **names;
-#ifdef HAVE_X_WINDOWS
-  Display *dpy = f ? FRAME_X_DISPLAY (f) : x_display_list->display;
+  int n, nignored;
 
-  /* Get the list of fonts matching PATTERN from the X server.  */
-  BLOCK_INPUT;
-  names = XListFonts (dpy, pattern, nfonts, &n);
-  UNBLOCK_INPUT;
-#endif /* HAVE_X_WINDOWS */
-#if defined (WINDOWSNT) || defined (macintosh)
   /* 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.  */
-  BLOCK_INPUT;
 #ifdef WINDOWSNT
+  BLOCK_INPUT;
   lfonts = w32_list_fonts (f, lpattern, 0, nfonts);
-#else /* macintosh */
-  lfonts = x_list_fonts (f, lpattern, 0, nfonts);
-#endif
   UNBLOCK_INPUT;
+#else
+  lfonts = x_list_fonts (f, lpattern, -1, nfonts);
+#endif
 
-  /* Count fonts returned */
-  for (tem = lfonts; CONSP (tem); tem = XCDR (tem))
-    n++;
-
-  /* Allocate array.  */
-  if (n)
-    names = (char **) xmalloc (n * sizeof (char *));
-
-  /* Extract font names into char * array.  */
-  tem = lfonts;
-  for (i = 0; i < n; i++)
+  /* Make a copy of the font names we got from X, and
+     split them into fields.  */
+  n = nignored = 0;
+  for (tem = lfonts; CONSP (tem) && n < nfonts; tem = XCDR (tem))
     {
-      names[i] = XSTRING (XCAR (tem))->data;
-      tem = XCDR (tem);
-    }
-#endif /* defined (WINDOWSNT) || defined (macintosh) */
+      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)
+      /* Ignore fonts matching a pattern from face-ignored-fonts.  */
+      for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
+       {
+         elt = XCAR (tail);
+         if (STRINGP (elt)
+             && fast_c_string_match_ignore_case (elt, name) >= 0)
+           break;
+       }
+      if (!NILP (tail))
        {
-         /* Make a copy of the font name.  */
-         fonts[j].name = xstrdup (names[i]);
+         ++nignored;
+         continue;
+       }
 
-         /* Ignore fonts having a name that we can't parse.  */
-         if (!split_font_name (f, fonts + j, 1))
-           xfree (fonts[j].name);
-         else if (font_scalable_p (fonts + j))
+      /* Make a copy of the font name.  */
+      fonts[n].name = xstrdup (name);
+
+      if (split_font_name (f, fonts + n, 1))
+       {
+         if (font_scalable_p (fonts + n)
+             && !may_use_scalable_font_p (name))
            {
-             if (!scalable_fonts_p
-                 || !may_use_scalable_font_p (fonts + j, names[i]))
-               xfree (fonts[j].name);
-             else
-               ++j;
+             ++nignored;
+             xfree (fonts[n].name);
            }
          else
-           ++j;
+           ++n;
        }
-
-      n = j;
-
-#ifdef HAVE_X_WINDOWS
-      /* Free font names.  */
-      BLOCK_INPUT;
-      XFreeFontNames (names);
-      UNBLOCK_INPUT;
-#endif
+      else
+       xfree (fonts[n].name);
     }
 
-
   /* If no fonts found, try patterns from Valternate_fontname_alist.  */
   if (n == 0 && try_alternatives_p)
     {
@@ -2391,8 +2460,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);
        }
@@ -2402,34 +2470,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
@@ -2453,7 +2493,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.  */
@@ -2852,38 +2892,24 @@ the WIDTH times as wide as FACE on FRAME.")
                              Lisp Faces
  ***********************************************************************/
 
-/* Access face attributes of face FACE, a Lisp vector.  */
-
-#define LFACE_FAMILY(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_FAMILY_INDEX]
-#define LFACE_HEIGHT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_HEIGHT_INDEX]
-#define LFACE_WEIGHT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_WEIGHT_INDEX]
-#define LFACE_SLANT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_SLANT_INDEX]
-#define LFACE_UNDERLINE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_UNDERLINE_INDEX]
-#define LFACE_INVERSE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_INVERSE_INDEX]
-#define LFACE_FOREGROUND(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_FOREGROUND_INDEX]
-#define LFACE_BACKGROUND(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_BACKGROUND_INDEX]
-#define LFACE_STIPPLE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_STIPPLE_INDEX]
-#define LFACE_SWIDTH(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_SWIDTH_INDEX]
-#define LFACE_OVERLINE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_OVERLINE_INDEX]
-#define LFACE_STRIKE_THROUGH(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_STRIKE_THROUGH_INDEX]
-#define LFACE_BOX(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_BOX_INDEX]
-#define LFACE_FONT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_FONT_INDEX]
-#define LFACE_INHERIT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_INHERIT_INDEX]
+/* Access face attributes of face LFACE, a Lisp vector.  */
+
+#define LFACE_FAMILY(LFACE)        AREF ((LFACE), LFACE_FAMILY_INDEX)
+#define LFACE_HEIGHT(LFACE)        AREF ((LFACE), LFACE_HEIGHT_INDEX)
+#define LFACE_WEIGHT(LFACE)        AREF ((LFACE), LFACE_WEIGHT_INDEX)
+#define LFACE_SLANT(LFACE)         AREF ((LFACE), LFACE_SLANT_INDEX)
+#define LFACE_UNDERLINE(LFACE)      AREF ((LFACE), LFACE_UNDERLINE_INDEX)
+#define LFACE_INVERSE(LFACE)       AREF ((LFACE), LFACE_INVERSE_INDEX)
+#define LFACE_FOREGROUND(LFACE)     AREF ((LFACE), LFACE_FOREGROUND_INDEX)
+#define LFACE_BACKGROUND(LFACE)     AREF ((LFACE), LFACE_BACKGROUND_INDEX)
+#define LFACE_STIPPLE(LFACE)       AREF ((LFACE), LFACE_STIPPLE_INDEX)
+#define LFACE_SWIDTH(LFACE)        AREF ((LFACE), LFACE_SWIDTH_INDEX)
+#define LFACE_OVERLINE(LFACE)      AREF ((LFACE), LFACE_OVERLINE_INDEX)
+#define LFACE_STRIKE_THROUGH(LFACE) AREF ((LFACE), LFACE_STRIKE_THROUGH_INDEX)
+#define LFACE_BOX(LFACE)           AREF ((LFACE), LFACE_BOX_INDEX)
+#define LFACE_FONT(LFACE)          AREF ((LFACE), LFACE_FONT_INDEX)
+#define LFACE_INHERIT(LFACE)       AREF ((LFACE), LFACE_INHERIT_INDEX)
+#define LFACE_AVGWIDTH(LFACE)      AREF ((LFACE), LFACE_AVGWIDTH_INDEX)
 
 /* Non-zero if LFACE is a Lisp face.  A Lisp face is a vector of size
    LFACE_VECTOR_SIZE which has the symbol `face' in slot 0.  */
@@ -2891,7 +2917,7 @@ the WIDTH times as wide as FACE on FRAME.")
 #define LFACEP(LFACE)                                  \
      (VECTORP (LFACE)                                  \
       && XVECTOR (LFACE)->size == LFACE_VECTOR_SIZE    \
-      && EQ (XVECTOR (LFACE)->contents[0], Qface))
+      && EQ (AREF (LFACE, 0), Qface))
 
 
 #if GLYPH_DEBUG
@@ -2906,6 +2932,8 @@ check_lface_attrs (attrs)
           || STRINGP (attrs[LFACE_FAMILY_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
           || SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
+  xassert (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
+          || INTEGERP (attrs[LFACE_AVGWIDTH_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
           || INTEGERP (attrs[LFACE_HEIGHT_INDEX])
           || FLOATP (attrs[LFACE_HEIGHT_INDEX])
@@ -3070,7 +3098,8 @@ lface_fully_specified_p (attrs)
   int i;
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-    if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX)
+    if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX
+       && i != LFACE_AVGWIDTH_INDEX)
       if (UNSPECIFIEDP (attrs[i])) 
         break;
 
@@ -3165,6 +3194,12 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
     LFACE_SWIDTH (lface)
       = have_xlfd_p ? xlfd_symbolic_swidth (&font) : Qnormal;
 
+  if (force_p || UNSPECIFIEDP (LFACE_AVGWIDTH (lface)))
+    LFACE_AVGWIDTH (lface)
+      = (have_xlfd_p
+        ? make_number (font.numeric[XLFD_AVGWIDTH])
+        : Qunspecified);
+
   if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
     LFACE_WEIGHT (lface)
       = have_xlfd_p ? xlfd_symbolic_weight (&font) : Qnormal;
@@ -3280,7 +3315,8 @@ merge_face_vectors (f, from, to, cycle_check)
          || !UNSPECIFIEDP (from[LFACE_HEIGHT_INDEX])
          || !UNSPECIFIEDP (from[LFACE_WEIGHT_INDEX])
          || !UNSPECIFIEDP (from[LFACE_SLANT_INDEX])
-         || !UNSPECIFIEDP (from[LFACE_SWIDTH_INDEX])))
+         || !UNSPECIFIEDP (from[LFACE_SWIDTH_INDEX])
+         || !UNSPECIFIEDP (from[LFACE_AVGWIDTH_INDEX])))
     to[LFACE_FONT_INDEX] = Qnil;
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
@@ -3618,7 +3654,7 @@ Value is a vector of face attributes.")
     {
       global_lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
                                   Qunspecified);
-      XVECTOR (global_lface)->contents[0] = Qface;
+      AREF (global_lface, 0) = Qface;
       Vface_new_frame_defaults = Fcons (Fcons (face, global_lface),
                                        Vface_new_frame_defaults);
 
@@ -3640,7 +3676,7 @@ Value is a vector of face attributes.")
     }
   else if (f == NULL)
     for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-      XVECTOR (global_lface)->contents[i] = Qunspecified;
+      AREF (global_lface, i) = Qunspecified;
 
   /* Add a frame-local definition.  */
   if (f)
@@ -3649,12 +3685,12 @@ Value is a vector of face attributes.")
        {
          lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
                                Qunspecified);
-         XVECTOR (lface)->contents[0] = Qface;
+         AREF (lface, 0) = Qface;
          f->face_alist = Fcons (Fcons (face, lface), f->face_alist);
        }
       else
        for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-         XVECTOR (lface)->contents[i] = Qunspecified;
+         AREF (lface, i) = Qunspecified;
     }
   else
     lface = global_lface;
@@ -3734,7 +3770,7 @@ 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 nil means change the face of the selected frame.\n\
 FRAME t means change the default for new frames.\n\
 FRAME 0 means change the face on all frames, and change the default\n\
   for new frames.")
@@ -3890,7 +3926,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
       else if (NILP (value))
        valid_p = 1;
       else if (INTEGERP (value))
-       valid_p = XINT (value) > 0;
+       valid_p = XINT (value) != 0;
       else if (STRINGP (value))
        valid_p = XSTRING (value)->size > 0;
       else if (CONSP (value))
@@ -3911,7 +3947,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
 
              if (EQ (k, QCline_width))
                {
-                 if (!INTEGERP (v) || XINT (v) <= 0)
+                 if (!INTEGERP (v) || XINT (v) == 0)
                    break;
                }
              else if (EQ (k, QCcolor))
@@ -4078,10 +4114,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
       ++windows_or_buffers_changed;
     }
 
-#ifdef HAVE_WINDOW_SYSTEM
-
-  if (!EQ (frame, Qt)
-      && !UNSPECIFIEDP (value)
+  if (!UNSPECIFIEDP (value)
       && NILP (Fequal (old_value, value)))
     {
       Lisp_Object param;
@@ -4090,16 +4123,22 @@ FRAME 0 means change the face on all frames, and change the default\n\
 
       if (EQ (face, Qdefault))
        {
+#ifdef HAVE_WINDOW_SYSTEM
          /* Changed font-related attributes of the `default' face are
             reflected in changed `font' frame parameters. */
-         if ((font_related_attr_p || font_attr_p)
+         if (FRAMEP (frame)
+             && (font_related_attr_p || font_attr_p)
              && lface_fully_specified_p (XVECTOR (lface)->contents))
            set_font_frame_param (frame, lface);
-         else if (EQ (attr, QCforeground))
+         else
+#endif /* HAVE_WINDOW_SYSTEM */
+
+         if (EQ (attr, QCforeground))
            param = Qforeground_color;
          else if (EQ (attr, QCbackground))
            param = Qbackground_color;
        }
+#ifdef HAVE_WINDOW_SYSTEM
 #ifndef WINDOWSNT
       else if (EQ (face, Qscroll_bar))
        {
@@ -4132,20 +4171,40 @@ FRAME 0 means change the face on all frames, and change the default\n\
          if (EQ (attr, QCbackground))
            param = Qmouse_color;
        }
+#endif /* HAVE_WINDOW_SYSTEM */
       else if (EQ (face, Qmenu))
-       ++menu_face_change_count;
-
-      if (!NILP (param))
        {
-         Lisp_Object cons;
-         cons = XCAR (Vparam_value_alist);
-         XCAR (cons) = param;
-         XCDR (cons) = value;
-         Fmodify_frame_parameters (frame, Vparam_value_alist);
+         /* 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;
        }
-    }
 
-#endif /* HAVE_WINDOW_SYSTEM */
+      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);
+         }
+    }
 
   return face;
 }
@@ -4164,24 +4223,28 @@ set_font_frame_param (frame, lface)
      Lisp_Object frame, lface;
 {
   struct frame *f = XFRAME (frame);
-  Lisp_Object font_name;
-  char *font;
 
-  if (STRINGP (LFACE_FONT (lface)))
-    font_name = LFACE_FONT (lface);
-  else
+  if (FRAME_WINDOW_P (f))
     {
-      /* Choose a font name that reflects LFACE's attributes and has
-        the registry and encoding pattern specified in the default
-        fontset (3rd arg: -1) for ASCII characters (4th arg: 0).  */
-      font = choose_face_font (f, XVECTOR (lface)->contents, -1, 0);
-      if (!font)
-       error ("No font matches the specified attribute");
-      font_name = build_string (font);
-      xfree (font);
-    }
+      Lisp_Object font_name;
+      char *font;
+      
+      if (STRINGP (LFACE_FONT (lface)))
+       font_name = LFACE_FONT (lface);
+      else
+       {
+         /* Choose a font name that reflects LFACE's attributes and has
+            the registry and encoding pattern specified in the default
+            fontset (3rd arg: -1) for ASCII characters (4th arg: 0).  */
+         font = choose_face_font (f, XVECTOR (lface)->contents, -1, 0);
+         if (!font)
+           error ("No font matches the specified attribute");
+         font_name = build_string (font);
+         xfree (font);
+       }
   
-  Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font_name), Qnil));
+      Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font_name), Qnil));
+    }
 }
 
 
@@ -4343,221 +4406,88 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
 #endif /* HAVE_WINDOW_SYSTEM */
 
 \f
-#ifdef HAVE_X_WINDOWS
 /***********************************************************************
                              Menu face
  ***********************************************************************/
 
-#ifdef USE_X_TOOLKIT
-
-#include "../lwlib/lwlib-utils.h"
-
-/* Structure used to pass X resources to functions called via
-   XtApplyToWidgets.  */
-
-struct x_resources
-{
-  Arg *av;
-  int ac;
-};
-
-
-#ifdef USE_MOTIF
-
-static void xm_apply_resources P_ ((Widget, XtPointer));
-static void xm_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
-
-
-/* Set widget W's X resources from P which points to an x_resources
-   structure.  If W is a cascade button, apply resources to W's
-   submenu.  */
-
-static void
-xm_apply_resources (w, p)
-     Widget w;
-     XtPointer p;
-{
-  Widget submenu = 0;
-  struct x_resources *res = (struct x_resources *) p;
-
-  XtSetValues (w, res->av, res->ac);
-  XtVaGetValues (w, XmNsubMenuId, &submenu, NULL);
-  if (submenu)
-    {
-      XtSetValues (submenu, res->av, res->ac);
-      XtApplyToWidgets (submenu, xm_apply_resources, p);
-    }
-}
-
-
-/* Set X resources of menu-widget WIDGET on frame F from face `menu'.
-   This is the LessTif/Motif version.  As of LessTif 0.88 it has the
-   following problems:
+#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
 
-   1. Setting the XmNfontList resource leads to an infinite loop
-   somewhere in LessTif.  */
+/* Make menus on frame F appear as specified by the `menu' face.  */
 
 static void
-xm_set_menu_resources_from_menu_face (f, widget)
+x_update_menu_appearance (f)
      struct frame *f;
-     Widget widget;
 {
-  struct face *face;
-  Lisp_Object lface;
-  Arg av[3];
-  int ac = 0;
-  XmFontList fl = 0;
-
-  lface = lface_from_face_name (f, Qmenu, 1);
-  face = FACE_FROM_ID (f, MENU_FACE_ID);
-
-  if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
-    {
-      XtSetArg (av[ac], XmNforeground, face->foreground);
-      ++ac;
-    }
-
-  if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
-    {
-      XtSetArg (av[ac], XmNbackground, face->background);
-      ++ac;
-    }
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  XrmDatabase rdb;
 
-  /* If any font-related attribute of `menu' is set, set the font.  */
-  if (face->font
-      && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
-         || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
-         || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
-         || !UNSPECIFIEDP (LFACE_SLANT (lface))
-         || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
+  if (dpyinfo
+      && (rdb = XrmGetDatabase (FRAME_X_DISPLAY (f)),
+         rdb != NULL))
     {
-#if 0 /* Setting the font leads to an infinite loop somewhere
-        in LessTif during geometry computation.  */
-      XmFontListEntry fe;
-      fe = XmFontListEntryCreate ("menu_font", XmFONT_IS_FONT, face->font);
-      fl = XmFontListAppendEntry (NULL, fe);
-      XtSetArg (av[ac], XmNfontList, fl);
-      ++ac;
+      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
-    }
-
-  xassert (ac <= sizeof av / sizeof *av);
-
-  if (ac)
-    {
-      struct x_resources res;
-
-      XtSetValues (widget, av, ac);
-      res.av = av, res.ac = ac;
-      XtApplyToWidgets (widget, xm_apply_resources, &res);
-      if (fl)
-       XmFontListFree (fl);
-    }
-}
-
-#endif /* USE_MOTIF */
-
-#ifdef USE_LUCID
-
-static void xl_apply_resources P_ ((Widget, XtPointer));
-static void xl_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
-
-
-/* Set widget W's resources from P which points to an x_resources
-   structure.  */
-
-static void
-xl_apply_resources (widget, p)
-     Widget widget;
-     XtPointer p;
-{
-  struct x_resources *res = (struct x_resources *) p;
-  XtSetValues (widget, res->av, res->ac);
-}
-
-
-/* On frame F, set X resources of menu-widget WIDGET from face `menu'.
-   This is the Lucid version.  */
-
-static void
-xl_set_menu_resources_from_menu_face (f, widget)
-     struct frame *f;
-     Widget widget;
-{
-  struct face *face;
-  Lisp_Object lface;
-  Arg av[3];
-  int ac = 0;
-
-  lface = lface_from_face_name (f, Qmenu, 1);
-  face = FACE_FROM_ID (f, MENU_FACE_ID);
-
-  if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
-    {
-      XtSetArg (av[ac], XtNforeground, face->foreground);
-      ++ac;
-    }
-
-  if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
-    {
-      XtSetArg (av[ac], XtNbackground, face->background);
-      ++ac;
-    }
-
-  if (face->font
-      && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
-         || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
-         || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
-         || !UNSPECIFIEDP (LFACE_SLANT (lface))
-         || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
-    {
-      XtSetArg (av[ac], XtNfont, face->font);
-      ++ac;
-    }
-
-  if (ac)
-    {
-      struct x_resources res;
-
-      XtSetValues (widget, av, ac);
-
-      /* We must do children here in case we're handling a pop-up menu
-        in which case WIDGET is a popup shell.  XtApplyToWidgets
-        is a function from lwlib.  */
-      res.av = av, res.ac = ac;
-      XtApplyToWidgets (widget, xl_apply_resources, &res);
-    }
-}
-
-#endif /* USE_LUCID */
-
-
-/* On frame F, set X resources of menu-widget WIDGET from face `menu'.  */
-
-void
-x_set_menu_resources_from_menu_face (f, widget)
-     struct frame *f;
-     Widget widget;
-{
-  /* Realized faces may have been removed on frame F, e.g. because of
-     face attribute changes.  Recompute them, if necessary, since we
-     will need the `menu' face.  */
-  if (f->face_cache->used == 0)
-    recompute_basic_faces (f);
+      
+      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;
+       }
 
-  BLOCK_INPUT;
-#ifdef USE_LUCID
-  xl_set_menu_resources_from_menu_face (f, widget);
-#endif
+      if (STRINGP (LFACE_BACKGROUND (lface)))
+       {
+         sprintf (line, "%s.%s*background: %s",
+                  myname, popup_path,
+                  XSTRING (LFACE_BACKGROUND (lface))->data);
+         XrmPutLineResource (&rdb, line);
+         sprintf (line, "%s.pane.menubar*background: %s",
+                  myname, XSTRING (LFACE_BACKGROUND (lface))->data);
+         XrmPutLineResource (&rdb, line);
+         changed_p = 1;
+       }
+         
+      if (face->font_name
+         && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
+             || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+             || !UNSPECIFIEDP (LFACE_AVGWIDTH (lface))
+             || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
+             || !UNSPECIFIEDP (LFACE_SLANT (lface))
+             || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
+       {
 #ifdef USE_MOTIF
-  xm_set_menu_resources_from_menu_face (f, widget);
+         const char *suffix = "List";
+#else
+         const char *suffix = "";
 #endif
-  UNBLOCK_INPUT;
-}
+         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;
+       }
 
-#endif /* USE_X_TOOLKIT */
+      if (changed_p && f->output_data.x->menubar_widget)
+       free_frame_menubar (f);
+    }
+}
 
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
 
 
 
@@ -4852,7 +4782,7 @@ If FRAME is omitted or nil, use the selected frame.")
     lface = lface_from_face_name (f, face, 1);
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-    if (!UNSPECIFIEDP (XVECTOR (lface)->contents[i]))
+    if (!UNSPECIFIEDP (AREF (lface, i)))
       break;
 
   return i == LFACE_VECTOR_SIZE ? Qt : Qnil;
@@ -4918,6 +4848,7 @@ lface_same_font_attributes_p (lface1, lface2)
                    XSTRING (lface2[LFACE_FAMILY_INDEX])->data) == 0
          && EQ (lface1[LFACE_HEIGHT_INDEX], lface2[LFACE_HEIGHT_INDEX])
          && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
+         && EQ (lface1[LFACE_AVGWIDTH_INDEX], lface2[LFACE_AVGWIDTH_INDEX])
          && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
          && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX])
          && (EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
@@ -5054,6 +4985,7 @@ make_face_cache (f)
   c->size = 50;
   c->faces_by_id = (struct face **) xmalloc (c->size * sizeof *c->faces_by_id);
   c->f = f;
+  c->menu_face_changed_p = menu_face_changed_default;
   return c;
 }
 
@@ -5550,7 +5482,7 @@ Value is ORDER.")
 {
   Lisp_Object list;
   int i;
-  int indices[4];
+  int indices[DIM (font_sort_order)];
 
   CHECK_LIST (order, 0);
   bzero (indices, sizeof indices);
@@ -5579,13 +5511,11 @@ Value is ORDER.")
       indices[i] = xlfd;
     }
 
-  if (!NILP (list)
-      || i != DIM (indices)
-      || indices[0] == 0
-      || indices[1] == 0
-      || indices[2] == 0
-      || indices[3] == 0)
+  if (!NILP (list) || i != DIM (indices))
     signal_error ("Invalid font sort order", order);
+  for (i = 0; i < DIM (font_sort_order); ++i)
+    if (indices[i] == 0)
+      signal_error ("Invalid font sort order", order);
 
   if (bcmp (indices, font_sort_order, sizeof indices) != 0)
     {
@@ -5662,17 +5592,18 @@ font_scalable_p (font)
 /* Value is non-zero if FONT1 is a better match for font attributes
    VALUES than FONT2.  VALUES is an array of face attribute values in
    font sort order.  COMPARE_PT_P zero means don't compare point
-   sizes.  */
+   sizes.  AVGWIDTH, if not zero, is a specified font average width
+   to compare with.  */
 
 static int
-better_font_p (values, font1, font2, compare_pt_p)
+better_font_p (values, font1, font2, compare_pt_p, avgwidth)
      int *values;
      struct font_name *font1, *font2;
-     int compare_pt_p;
+     int compare_pt_p, avgwidth;
 {
   int i;
 
-  for (i = 0; i < 4; ++i)
+  for (i = 0; i < DIM (font_sort_order); ++i)
     {
       int xlfd_idx = font_sort_order[i];
 
@@ -5701,26 +5632,40 @@ better_font_p (values, font1, font2, compare_pt_p)
        }
     }
 
-  return (font1->registry_priority < font2->registry_priority);
+  if (avgwidth)
+    {
+      int delta1 = abs (avgwidth - font1->numeric[XLFD_AVGWIDTH]);
+      int delta2 = abs (avgwidth - font2->numeric[XLFD_AVGWIDTH]);
+      if (delta1 > delta2)
+       return 0;
+      else if (delta1 < delta2)
+       return 1;
+    }
+
+  return font1->registry_priority < font2->registry_priority;
 }
 
 
 /* Value is non-zero if FONT is an exact match for face attributes in
    SPECIFIED.  SPECIFIED is an array of face attribute values in font
-   sort order.  */
+   sort order.  AVGWIDTH, if non-zero, is an average width to compare
+   with.  */
 
 static int
-exact_face_match_p (specified, font)
+exact_face_match_p (specified, font, avgwidth)
      int *specified;
      struct font_name *font;
+     int avgwidth;
 {
   int i;
 
-  for (i = 0; i < 4; ++i)
+  for (i = 0; i < DIM (font_sort_order); ++i)
     if (specified[i] != font->numeric[font_sort_order[i]])
       break;
 
-  return i == 4;
+  return (i == DIM (font_sort_order)
+         && (avgwidth <= 0
+             || avgwidth == font->numeric[XLFD_AVGWIDTH]));
 }
 
 
@@ -5745,12 +5690,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.  */
@@ -5791,9 +5736,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;
@@ -5805,7 +5749,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;
        }
     }
@@ -5815,23 +5759,27 @@ may_use_scalable_font_p (font, name)
 
 
 
-/* Return the name of the best matching font for face attributes
-   ATTRS in the array of font_name structures FONTS which contains
-   NFONTS elements.  Value is a font name which is allocated from
-   the heap.  FONTS is freed by this function.  */
+/* Return the name of the best matching font for face attributes ATTRS
+   in the array of font_name structures FONTS which contains NFONTS
+   elements.  WIDTH_RATIO is a factor with which to multiply average
+   widths if ATTRS specifies such a width.
+
+   Value is a font name which is allocated from the heap.  FONTS is
+   freed by this function.  */
 
 static char *
-best_matching_font (f, attrs, fonts, nfonts)
+best_matching_font (f, attrs, fonts, nfonts, width_ratio)
      struct frame *f;
      Lisp_Object *attrs;
      struct font_name *fonts;
      int nfonts;
+     int width_ratio;
 {
   char *font_name;
   struct font_name *best;
   int i, pt = 0;
-  int specified[4];
-  int exact_p;
+  int specified[5];
+  int exact_p, avgwidth;
 
   if (nfonts == 0)
     return NULL;
@@ -5854,6 +5802,10 @@ best_matching_font (f, attrs, fonts, nfonts)
        abort ();
     }
 
+  avgwidth = (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
+             ? 0
+             : XFASTINT (attrs[LFACE_AVGWIDTH_INDEX]) * width_ratio);
+
   exact_p = 0;
 
   /* Start with the first non-scalable font in the list.  */
@@ -5868,11 +5820,11 @@ best_matching_font (f, attrs, fonts, nfonts)
 
       for (i = 1; i < nfonts; ++i)
        if (!font_scalable_p (fonts + i)
-           && better_font_p (specified, fonts + i, best, 1))
+           && better_font_p (specified, fonts + i, best, 1, avgwidth))
          {
            best = fonts + i;
 
-           exact_p = exact_face_match_p (specified, best);
+           exact_p = exact_face_match_p (specified, best, avgwidth);
            if (exact_p)
              break;
          }
@@ -5904,9 +5856,9 @@ best_matching_font (f, attrs, fonts, nfonts)
        if (font_scalable_p (fonts + i))
          {
            if (best == NULL
-               || better_font_p (specified, fonts + i, best, 0)
+               || better_font_p (specified, fonts + i, best, 0, 0)
                || (!non_scalable_has_exact_height_p
-                   && !better_font_p (specified, best, fonts + i, 0)))
+                   && !better_font_p (specified, best, fonts + i, 0, 0)))
              best = fonts + i;
          }
     }
@@ -5923,54 +5875,99 @@ best_matching_font (f, attrs, fonts, nfonts)
 }
 
 
-/* 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;
-
-  if (NILP (family) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
-    family = attrs[LFACE_FAMILY_INDEX];
+  Lisp_Object alter;
+  int nfonts = 0;
 
-  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.
 
-      /* Try any family with the given registry.  */
-      if (nfonts == 0)
-       nfonts = font_list (f, Qnil, Qnil, registry, fonts);
+   FAMILY, if a string, specifies a font family derived from the fontset.
+   It is only used if the face does not specify any family in ATTRS or
+   if we cannot find any font of the face's family.
+
+   REGISTRY, if a string, specifies a font registry and encoding to
+   match.  A value of nil means include fonts of any registry and
+   encoding.
+   
+   Return in *FONTS a pointer to a vector of font_name structures for
+   the fonts matched.  Value is the number of fonts found.  */
+
+static int
+try_font_list (f, attrs, family, registry, fonts)
+     struct frame *f;
+     Lisp_Object *attrs;
+     Lisp_Object family, registry;
+     struct font_name **fonts;
+{
+  int nfonts = 0;
+  Lisp_Object face_family = attrs[LFACE_FAMILY_INDEX];
+
+  if (STRINGP (face_family))
+    nfonts = try_alternative_families (f, face_family, registry, fonts);
+
+  if (nfonts == 0 && !NILP (family))
+    nfonts = try_alternative_families (f, family, registry, fonts);
+
+  /* Try font family of the default face or "fixed".  */
+  if (nfonts == 0)
+    {
+      struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+      if (default_face)
+       family = default_face->lface[LFACE_FAMILY_INDEX];
+      else
+       family = build_string ("fixed");
+      nfonts = font_list (f, Qnil, family, registry, fonts);
     }
+      
+  /* Try any family with the given registry.  */
+  if (nfonts == 0)
+    nfonts = font_list (f, Qnil, Qnil, registry, fonts);
 
   return nfonts;
 }
@@ -5985,7 +5982,6 @@ face_fontset (attrs)
      Lisp_Object *attrs;
 {
   Lisp_Object name;
-  int fontset;
 
   name = attrs[LFACE_FONT_INDEX];
   if (!STRINGP (name))
@@ -6012,7 +6008,7 @@ choose_face_font (f, attrs, fontset, c)
   Lisp_Object pattern;
   char *font_name = NULL;
   struct font_name *fonts;
-  int nfonts;
+  int nfonts, width_ratio;
 
   /* Get (foundry and) family name and registry (and encoding) name of
      a font for C.  */
@@ -6022,22 +6018,18 @@ choose_face_font (f, attrs, fontset, c)
       xassert (!SINGLE_BYTE_CHAR_P (c));
       return NULL;
     }
+  
   /* If what we got is a name pattern, return it.  */
   if (STRINGP (pattern))
     return xstrdup (XSTRING (pattern)->data);
 
-  /* Family name may be specified both in ATTRS and car part of
-     PATTERN.  The former has higher priority if C is a single byte
-     character.  */
-  if (STRINGP (attrs[LFACE_FAMILY_INDEX])
-      && SINGLE_BYTE_CHAR_P (c))
-    XCAR (pattern) = Qnil;
-
   /* Get a list of fonts matching that pattern and choose the
      best match for the specified face attributes from it.  */
-  nfonts = try_font_list (f, attrs, Qnil, XCAR (pattern), XCDR (pattern),
-                         &fonts);
-  font_name = best_matching_font (f, attrs, fonts, nfonts);
+  nfonts = try_font_list (f, attrs, XCAR (pattern), XCDR (pattern), &fonts);
+  width_ratio = (SINGLE_BYTE_CHAR_P (c)
+                ? 1
+                : CHARSET_WIDTH (CHAR_CHARSET (c)));
+  font_name = best_matching_font (f, attrs, fonts, nfonts, width_ratio);
   return font_name;
 }
 
@@ -6058,10 +6050,12 @@ 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))
     {
@@ -6076,23 +6070,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
-         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 */
+         x_update_menu_appearance (f);
+#endif
        }
       
       success_p = 1;
     }
 
+  unbind_to (count, Qnil);
   UNBLOCK_INPUT;
   return success_p;
 }
@@ -6111,7 +6100,6 @@ realize_default_face (f)
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   Lisp_Object frame_font;
   struct face *face;
-  int fontset;
 
   /* If the `default' face is not yet known, create it.  */
   lface = lface_from_face_name (f, Qdefault, 0);
@@ -6140,6 +6128,7 @@ realize_default_face (f)
       LFACE_HEIGHT (lface) = make_number (1);
       LFACE_WEIGHT (lface) = Qnormal;
       LFACE_SLANT (lface) = Qnormal;
+      LFACE_AVGWIDTH (lface) = Qunspecified;
     }
 
   if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
@@ -6403,9 +6392,9 @@ realize_x_face (cache, attrs, c, base_face)
     {
       /* Simple box of specified line width in foreground color of the
          face.  */
-      xassert (XINT (box) > 0);
+      xassert (XINT (box) != 0);
       face->box = FACE_SIMPLE_BOX;
-      face->box_line_width = XFASTINT (box);
+      face->box_line_width = XINT (box);
       face->box_color = face->foreground;
       face->box_color_defaulted_p = 1;
     }
@@ -6432,8 +6421,8 @@ realize_x_face (cache, attrs, c, base_face)
 
          if (EQ (keyword, QCline_width))
            {
-             if (INTEGERP (value) && XINT (value) > 0)
-               face->box_line_width = XFASTINT (value);
+             if (INTEGERP (value) && XINT (value) != 0)
+               face->box_line_width = XINT (value);
            }
          else if (EQ (keyword, QCcolor))
            {
@@ -6701,7 +6690,7 @@ compute_char_face (f, ch, prop)
   int face_id;
 
   if (NILP (current_buffer->enable_multibyte_characters))
-    ch = -1;
+    ch = 0;
 
   if (NILP (prop))
     {
@@ -6756,7 +6745,6 @@ face_at_buffer_position (w, pos, region_beg, region_end,
   Lisp_Object propname = mouse ? Qmouse_face : Qface;
   Lisp_Object limit1, end;
   struct face *default_face;
-  int multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
 
   /* W must display the current buffer.  We could write this function
      to use the frame and buffer of W, but right now it doesn't.  */
@@ -6861,10 +6849,12 @@ face_at_buffer_position (w, pos, region_beg, region_end,
    current_buffer, otherwise BUFPOS is zero to indicate that STRING is
    not an overlay string.  W must display the current buffer.
    REGION_BEG and REGION_END give the start and end positions of the
-   region; both are -1 if no region is visible.  BASE_FACE_ID is the
-   id of the basic face to merge with.  It is usually equal to
-   DEFAULT_FACE_ID but can be MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID
-   for strings displayed in the mode or top line.
+   region; both are -1 if no region is visible.
+
+   BASE_FACE_ID is the id of a face to merge with.  For strings coming
+   from overlays or the `display' property it is the face at BUFPOS.
+
+   If MOUSE_P is non-zero, use the character's mouse-face, not its face.
 
    Set *ENDPTR to the next position where to check for faces in
    STRING; -1 if the face is constant from POS to the end of the
@@ -6875,24 +6865,26 @@ face_at_buffer_position (w, pos, region_beg, region_end,
 
 int
 face_at_string_position (w, string, pos, bufpos, region_beg,
-                        region_end, endptr, base_face_id)
+                        region_end, endptr, base_face_id, mouse_p)
      struct window *w;
      Lisp_Object string;
      int pos, bufpos;
      int region_beg, region_end;
      int *endptr;
      enum face_id base_face_id;
+     int mouse_p;
 {
   Lisp_Object prop, position, end, limit;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   struct face *base_face;
   int multibyte_p = STRING_MULTIBYTE (string);
+  Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface;
 
   /* Get the value of the face property at the current position within
      STRING.  Value is nil if there is no face property.  */
   XSETFASTINT (position, pos);
-  prop = Fget_text_property (position, Qface, string);
+  prop = Fget_text_property (position, prop_name, string);
 
   /* Get the next position at which to check for faces.  Value of end
      is nil if face is constant all the way to the end of the string.
@@ -6901,7 +6893,7 @@ face_at_string_position (w, string, pos, bufpos, region_beg,
      changes in Fnext_single_property_change.  Strings are usually
      short, so set the limit to the end of the string.  */
   XSETFASTINT (limit, XSTRING (string)->size);
-  end = Fnext_single_property_change (position, Qface, string, limit);
+  end = Fnext_single_property_change (position, prop_name, string, limit);
   if (INTEGERP (end))
     *endptr = XFASTINT (end);
   else
@@ -7176,6 +7168,8 @@ syms_of_xfaces ()
   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);
@@ -7240,14 +7234,15 @@ See `set-face-stipple' for possible values for this variable.");
 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
+scaled if its name matches a regular expression in the list.\n\
+Note that if value is nil, a scalable font might still be used, if no\n\
+other font of the appropriate family and registry is available.");
   Vscalable_fonts_allowed = Qnil;
-#endif
+
+  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);