(xlfd_point_size): Don't divide pixel size from
[bpt/emacs.git] / src / xfaces.c
index b11a7d4..d2d88ce 100644 (file)
@@ -57,7 +57,7 @@ Boston, MA 02111-1307, USA.  */
    type, and, for simple boxes, in what color.
 
    14. Font or fontset pattern, or nil.  This is a special attribute.
-   When this attribyte is specified, the face uses a font opened by
+   When this attribute is specified, the face uses a font opened by
    that pattern as is.  In addition, all the other font-related
    attributes (1st thru 5th) are generated from the opened font name.
    On the other hand, if one of the other font-related attributes are
@@ -123,7 +123,7 @@ Boston, MA 02111-1307, USA.  */
    is realized, it inherits (thus shares) a fontset of an ASCII face
    that has the same attributes other than font-related ones.
 
-   Thus, all realzied face have a realized fontset.
+   Thus, all realized face have a realized fontset.
 
 
    Unibyte text.
@@ -173,7 +173,7 @@ Boston, MA 02111-1307, USA.  */
    fonts.
 
 
-   Character compositition.
+   Character composition.
 
    Usually, the realization process is already finished when Emacs
    actually reflects the desired glyph matrix on the screen.  However,
@@ -196,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
@@ -219,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
@@ -227,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 */
 
@@ -284,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))
@@ -403,7 +405,7 @@ Lisp_Object Vface_alternative_font_registry_alist;
    font may be scaled if its name matches a regular expression in the
    list.  */
 
-Lisp_Object Vscalable_fonts_allowed;
+Lisp_Object Vscalable_fonts_allowed, Qscalable_fonts_allowed;
 
 /* List of regular expressions that matches names of fonts to ignore. */
 
@@ -505,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, int));
-static int first_font_matching P_ ((struct frame *f, char *,
-                                   struct font_name *));
 static int x_face_list_fonts P_ ((struct frame *, char *,
-                                 struct font_name *, int, int, int));
+                                 struct font_name *, int, int));
 static int font_scalable_p P_ ((struct font_name *));
 static int get_lface_attributes P_ ((struct frame *, Lisp_Object, Lisp_Object *, int));
 static int load_pixmap P_ ((struct frame *, Lisp_Object, unsigned *, unsigned *));
@@ -532,8 +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));
@@ -601,6 +603,10 @@ static void clear_font_table P_ ((struct frame *));
 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
@@ -2116,13 +2122,41 @@ xlfd_point_size (f, font)
      struct font_name *font;
 {
   double resy = FRAME_X_DISPLAY_INFO (f)->resy;
-  double font_pixel = atoi (font->fields[XLFD_PIXEL_SIZE]);
+  char *pixel_field = font->fields[XLFD_PIXEL_SIZE];
+  double pixel;
   int real_pt;
 
-  if (font_pixel == 0)
+  if (*pixel_field == '[')
+    {
+      /* The pixel size field is `[A B C D]' which specifies
+        a transformation matrix.
+
+        A  B  0
+        C  D  0
+        0  0  1
+
+        by which all glyphs of the font are transformed.  The spec
+        says that s scalar value N for the pixel size is equivalent
+        to A = N * resx/resy, B = C = 0, D = N.  */
+      char *start = pixel_field + 1, *end;
+      double matrix[4];
+      int i;
+
+      for (i = 0; i < 4; ++i)
+       {
+         matrix[i] = strtod (start, &end);
+         start = end;
+       }
+
+      pixel = matrix[3];
+    }
+  else
+    pixel = atoi (pixel_field);
+  
+  if (pixel == 0)
     real_pt = 0;
   else
-    real_pt = PT_PER_INCH * 10.0 * font_pixel / resy + 0.5;
+    real_pt = PT_PER_INCH * 10.0 * pixel / resy + 0.5;
 
   return real_pt;
 }
@@ -2156,9 +2190,7 @@ pixel_point_size (f, pixel)
    XLFD_RESY, XLFD_SLANT, and XLFD_WEIGHT in FONT->numeric.  Value is
    zero if the font name doesn't have the format we expect.  The
    expected format is a font name that starts with a `-' and has
-   XLFD_LAST fields separated by `-'.  (The XLFD specification allows
-   forms of font names where certain field contents are enclosed in
-   square brackets.  We don't support that, for now.  */
+   XLFD_LAST fields separated by `-'.  */
 
 static int
 split_font_name (f, font, numeric_p)
@@ -2178,6 +2210,33 @@ split_font_name (f, font, numeric_p)
          font->fields[i] = p;
          ++i;
 
+         /* Pixel and point size may be of the form `[....]'.  For
+            BNF, see XLFD spec, chapter 4.  Negative values are
+            indicated by tilde characters which we replace with
+            `-' characters, here.  */
+         if (*p == '['
+             && (i - 1 == XLFD_PIXEL_SIZE
+                 || i - 1 == XLFD_POINT_SIZE))
+           {
+             char *start, *end;
+             int j;
+             
+             for (++p; *p && *p != ']'; ++p)
+               if (*p == '~')
+                 *p = '-';
+
+             /* Check that the matrix contains 4 floating point
+                numbers.  */
+             for (j = 0, start = font->fields[i - 1] + 1;
+                  j < 4;
+                  ++j, start = end)
+               if (strtod (start, &end) == 0 && start == end)
+                 break;
+
+             if (j < 4)
+               break;
+           }
+
          while (*p && *p != '-')
            ++p;
 
@@ -2283,23 +2342,20 @@ sort_fonts (f, fonts, nfonts, cmpfn)
    display in x_display_list.  FONTS is a pointer to a vector of
    NFONTS font_name structures.  TRY_ALTERNATIVES_P non-zero means try
    alternative patterns from Valternate_fontname_alist if no fonts are
-   found matching PATTERN.  SCALABLE_FONTS_P non-zero means include
-   scalable fonts.
+   found matching PATTERN.
 
    For all fonts found, set FONTS[i].name to the name of the font,
    allocated via xmalloc, and split font names into fields.  Ignore
    fonts that we can't parse.  Value is the number of fonts found.  */
 
 static int
-x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
-                  scalable_fonts_p)
+x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p)
      struct frame *f;
      char *pattern;
      struct font_name *fonts;
      int nfonts, try_alternatives_p;
-     int scalable_fonts_p;
 {
-  int n;
+  int n, nignored;
 
   /* NTEMACS_TODO : currently this uses w32_list_fonts, but it may be
      better to do it the other way around. */
@@ -2314,17 +2370,18 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
   lfonts = w32_list_fonts (f, lpattern, 0, nfonts);
   UNBLOCK_INPUT;
 #else
-  lfonts = x_list_fonts (f, lpattern, scalable_fonts_p ? -1 : 0, nfonts);
+  lfonts = x_list_fonts (f, lpattern, -1, nfonts);
 #endif
 
   /* Make a copy of the font names we got from X, and
      split them into fields.  */
-  n = 0;
-  for (tem = lfonts; CONSP (tem); tem = XCDR (tem))
+  n = nignored = 0;
+  for (tem = lfonts; CONSP (tem) && n < nfonts; tem = XCDR (tem))
     {
       Lisp_Object elt, tail;
       char *name = XSTRING (XCAR (tem))->data;
 
+      /* Ignore fonts matching a pattern from face-ignored-fonts.  */
       for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
        {
          elt = XCAR (tail);
@@ -2333,24 +2390,27 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
            break;
        }
       if (!NILP (tail))
-       continue;
+       {
+         ++nignored;
+         continue;
+       }
 
       /* Make a copy of the font name.  */
       fonts[n].name = xstrdup (name);
 
-      /* Ignore fonts having a name that we can't parse.  */
-      if (!split_font_name (f, fonts + n, 1))
-       xfree (fonts[n].name);
-      else if (font_scalable_p (fonts + n))
+      if (split_font_name (f, fonts + n, 1))
        {
-         if (!scalable_fonts_p
-             || !may_use_scalable_font_p (fonts + n, name))
-           xfree (fonts[n].name);
+         if (font_scalable_p (fonts + n)
+             && !may_use_scalable_font_p (name))
+           {
+             ++nignored;
+             xfree (fonts[n].name);
+           }
          else
            ++n;
        }
       else
-       ++n;
+       xfree (fonts[n].name);
     }
 
   /* If no fonts found, try patterns from Valternate_fontname_alist.  */
@@ -2381,8 +2441,7 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
                    already with no success.  */
                 && (strcmp (XSTRING (name)->data, pattern) == 0
                     || (n = x_face_list_fonts (f, XSTRING (name)->data,
-                                               fonts, nfonts, 0,
-                                               scalable_fonts_p),
+                                               fonts, nfonts, 0),
                         n == 0)))
            patterns = XCDR (patterns);
        }
@@ -2392,34 +2451,6 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
 }
 
 
-/* Determine the first font matching PATTERN on frame F.  Return in
-   *FONT the matching font name, split into fields.  Value is non-zero
-   if a match was found.  */
-
-static int
-first_font_matching (f, pattern, font)
-     struct frame *f;
-     char *pattern;
-     struct font_name *font;
-{
-  int nfonts = 100;
-  struct font_name *fonts;
-
-  fonts = (struct font_name *) xmalloc (nfonts * sizeof *fonts);
-  nfonts = x_face_list_fonts (f, pattern, fonts, nfonts, 1, 0);
-
-  if (nfonts > 0)
-    {
-      bcopy (&fonts[0], font, sizeof *font);
-
-      fonts[0].name = NULL;
-      free_font_names (fonts, nfonts);
-    }
-
-  return nfonts > 0;
-}
-
-
 /* Determine fonts matching PATTERN on frame F.  Sort resulting fonts
    using comparison function CMPFN.  Value is the number of fonts
    found.  If value is non-zero, *FONTS is set to a vector of
@@ -2443,7 +2474,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.  */
@@ -4341,223 +4372,91 @@ 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
+#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
 
-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.  */
+/* Make menus on frame F appear as specified by the `menu' face.  */
 
 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:
-
-   1. Setting the XmNfontList resource leads to an infinite loop
-   somewhere in LessTif.  */
-
-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_AVGWIDTH (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_AVGWIDTH (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);
+         set_frame_menubar (f, 1, 1);
+       }
+    }
+}
 
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
 
 
 
@@ -5805,9 +5704,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;
@@ -5819,7 +5717,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;
        }
     }
@@ -5945,54 +5843,99 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio)
 }
 
 
-/* Try to get a list of fonts on frame F with font family FAMILY and
-   registry/encoding REGISTRY.  Return in *FONTS a pointer to a vector
-   of font_name structures for the fonts matched.  Value is the number
-   of fonts found.  */
+/* Get a list of matching fonts on frame F, considering FAMILY
+   and alternative font families from Vface_alternative_font_registry_alist.
+
+   FAMILY is the font family whose alternatives are considered.
+
+   REGISTRY, if a string, specifies a font registry and encoding to
+   match.  A value of nil means include fonts of any registry and
+   encoding.
+   
+   Return in *FONTS a pointer to a vector of font_name structures for
+   the fonts matched.  Value is the number of fonts found.  */
 
 static int
-try_font_list (f, attrs, pattern, family, registry, fonts)
+try_alternative_families (f, family, registry, fonts)
      struct frame *f;
-     Lisp_Object *attrs;
-     Lisp_Object pattern, family, registry;
+     Lisp_Object family, registry;
      struct font_name **fonts;
 {
-  int nfonts;
+  Lisp_Object alter;
+  int nfonts = 0;
 
-  if (NILP (family) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
-    family = attrs[LFACE_FAMILY_INDEX];
-
-  nfonts = font_list (f, pattern, family, registry, fonts);
-  if (nfonts == 0 && !NILP (family))
+  nfonts = font_list (f, Qnil, family, registry, fonts);
+  if (nfonts == 0)
     {
-      Lisp_Object alter;
-
       /* Try alternative font families.  */
       alter = Fassoc (family, Vface_alternative_font_family_alist);
       if (CONSP (alter))
-       for (alter = XCDR (alter);
-            CONSP (alter) && nfonts == 0;
-            alter = XCDR (alter))
-         {
-           if (STRINGP (XCAR (alter)))
-             nfonts = font_list (f, Qnil, XCAR (alter), registry, fonts);
-         }
-
-      /* Try font family of the default face or "fixed".  */
-      if (nfonts == 0)
        {
-         struct face *dflt = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-         if (dflt)
-           family = dflt->lface[LFACE_FAMILY_INDEX];
-         else
-           family = build_string ("fixed");
-         nfonts = font_list (f, Qnil, family, registry, fonts);
+         for (alter = XCDR (alter);
+              CONSP (alter) && nfonts == 0;
+              alter = XCDR (alter))
+           {
+             if (STRINGP (XCAR (alter)))
+               nfonts = font_list (f, Qnil, XCAR (alter), registry, fonts);
+           }
+       }
+      
+      /* Try scalable fonts before giving up.  */
+      if (nfonts == 0 && NILP (Vscalable_fonts_allowed))
+       {
+         int count = BINDING_STACK_SIZE ();
+         specbind (Qscalable_fonts_allowed, Qt);
+         nfonts = try_alternative_families (f, family, registry, fonts);
+         unbind_to (count, Qnil);
        }
+    }
+  return nfonts;
+}
+
+
+/* Get a list of matching fonts on frame F.
+
+   FAMILY, if a string, specifies a font family derived from the fontset.
+   It is only used if the face does not specify any family in ATTRS or
+   if we cannot find any font of the face's family.
+
+   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.  */
 
-      /* Try any family with the given registry.  */
-      if (nfonts == 0)
-       nfonts = font_list (f, Qnil, Qnil, registry, fonts);
+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;
 }
@@ -6043,21 +5986,14 @@ 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);
+  nfonts = try_font_list (f, attrs, XCAR (pattern), XCDR (pattern), &fonts);
   width_ratio = (SINGLE_BYTE_CHAR_P (c)
                 ? 1
                 : CHARSET_WIDTH (CHAR_CHARSET (c)));
@@ -6082,10 +6018,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;
+  specbind (Qscalable_fonts_allowed, Qt);
 
   if (realize_default_face (f))
     {
@@ -6102,21 +6040,16 @@ realize_basic_faces (f)
       /* Reflect changes in the `menu' face in menu bars.  */
       if (menu_face_change_count)
        {
-         menu_face_change_count = 0;
-         
+         --menu_face_change_count;
 #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;
 }
@@ -6725,7 +6658,7 @@ compute_char_face (f, ch, prop)
   int face_id;
 
   if (NILP (current_buffer->enable_multibyte_characters))
-    ch = -1;
+    ch = 0;
 
   if (NILP (prop))
     {
@@ -6889,6 +6822,8 @@ face_at_buffer_position (w, pos, region_beg, region_end,
    BASE_FACE_ID is the id of a face to merge with.  For strings coming
    from overlays or the `display' property it is the face at BUFPOS.
 
+   If MOUSE_P is non-zero, use the character's mouse-face, not its face.
+
    Set *ENDPTR to the next position where to check for faces in
    STRING; -1 if the face is constant from POS to the end of the
    string.
@@ -6898,24 +6833,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.
@@ -6924,7 +6861,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
@@ -7199,6 +7136,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);
@@ -7263,14 +7202,10 @@ 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\