*** empty log message ***
[bpt/emacs.git] / src / xfaces.c
index 68371ef..c588527 100644 (file)
@@ -1,5 +1,5 @@
 /* xfaces.c -- "Face" primitives.
-   Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001
+   Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation.
 
 This file is part of GNU Emacs.
@@ -56,7 +56,7 @@ Boston, MA 02111-1307, USA.  */
    13. Whether or not a box should be drawn around characters, the box
    type, and, for simple boxes, in what color.
 
-   14. Font or fontset pattern, or nil.  This is a special attribute.
+   14. Font pattern, or nil.  This is a special attribute.
    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.
@@ -72,6 +72,8 @@ Boston, MA 02111-1307, USA.  */
    and is used to ensure that a font specified on the command line,
    for example, can be matched exactly.
 
+   17. A fontset name.
+
    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
@@ -123,7 +125,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 realized face have a realized fontset.
+   Thus, all realized faces have a realized fontset.
 
 
    Unibyte text.
@@ -194,7 +196,9 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+
 #include "lisp.h"
+#include "character.h"
 #include "charset.h"
 #include "keyboard.h"
 #include "frame.h"
@@ -227,38 +231,13 @@ Boston, MA 02111-1307, USA.  */
 #define check_x check_w32
 #define x_list_fonts w32_list_fonts
 #define GCGraphicsExposures 0
-/* For historic reasons, FONT_WIDTH refers to average width on W32,
-   not maximum as on X. Redefine here. */
-#undef FONT_WIDTH
-#define FONT_WIDTH FONT_MAX_WIDTH
 #endif /* WINDOWSNT */
 
-#ifdef macintosh
+#ifdef MAC_OS
 #include "macterm.h"
 #define x_display_info mac_display_info
 #define check_x check_mac
-
-extern XGCValues *XCreateGC (void *, WindowPtr, unsigned long, XGCValues *);
-
-static INLINE GC
-x_create_gc (f, mask, xgcv)
-     struct frame *f;
-     unsigned long mask;
-     XGCValues *xgcv;
-{
-  GC gc;
-  gc = XCreateGC (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), mask, xgcv);
-  return gc;
-}
-
-static INLINE void
-x_free_gc (f, gc)
-     struct frame *f;
-     GC gc;
-{
-  XFreeGC (FRAME_MAC_DISPLAY (f), gc);
-}
-#endif
+#endif /* MAC_OS */
 
 #include "buffer.h"
 #include "dispextern.h"
@@ -288,11 +267,7 @@ x_free_gc (f, gc)
 #include <stdio.h>
 #include <ctype.h>
 
-#ifndef max
-#define max(A, B)      ((A) > (B) ? (A) : (B))
-#define min(A, B)      ((A) < (B) ? (A) : (B))
 #define abs(X)         ((X) < 0 ? -(X) : (X))
-#endif
 
 /* Number of pt per inch (from the TeXbook).  */
 
@@ -314,28 +289,13 @@ x_free_gc (f, gc)
 /* Make a copy of the contents of Lisp string S on the stack using
    alloca.  Value is a pointer to the copy.  */
 
-#define LSTRDUPA(S) STRDUPA (XSTRING ((S))->data)
+#define LSTRDUPA(S) STRDUPA (SDATA ((S)))
 
 /* Size of hash table of realized faces in face caches (should be a
    prime number).  */
 
 #define FACE_CACHE_BUCKETS_SIZE 1001
 
-/* A definition of XColor for non-X frames.  */
-
-#ifndef HAVE_X_WINDOWS
-
-typedef struct
-{
-  unsigned long pixel;
-  unsigned short red, green, blue;
-  char flags;
-  char pad;
-}
-XColor;
-
-#endif /* not HAVE_X_WINDOWS */
-
 /* Keyword symbols used for face attribute names.  */
 
 Lisp_Object QCfamily, QCheight, QCweight, QCslant, QCunderline;
@@ -343,6 +303,7 @@ Lisp_Object QCinverse_video, QCforeground, QCbackground, QCstipple;
 Lisp_Object QCwidth, QCfont, QCbold, QCitalic;
 Lisp_Object QCreverse_video;
 Lisp_Object QCoverline, QCstrike_through, QCbox, QCinherit;
+Lisp_Object QCfontset;
 
 /* Symbols used for attribute values.  */
 
@@ -367,6 +328,7 @@ Lisp_Object Qframe_update_face_colors;
 
 Lisp_Object Qdefault, Qtool_bar, Qregion, Qfringe;
 Lisp_Object Qheader_line, Qscroll_bar, Qcursor, Qborder, Qmouse, Qmenu;
+Lisp_Object Qmode_line_inactive;
 extern Lisp_Object Qmode_line;
 
 /* The symbol `face-alias'.  A symbols having that property is an
@@ -375,11 +337,6 @@ extern Lisp_Object Qmode_line;
 
 Lisp_Object Qface_alias;
 
-/* Names of frame parameters related to faces.  */
-
-extern Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
-extern Lisp_Object Qborder_color, Qcursor_color, Qmouse_color;
-
 /* Default stipple pattern used on monochrome displays.  This stipple
    pattern is used on monochrome displays instead of shades of gray
    for a face background color.  See `set-face-stipple' for possible
@@ -411,6 +368,10 @@ Lisp_Object Vscalable_fonts_allowed, Qscalable_fonts_allowed;
 
 Lisp_Object Vface_ignored_fonts;
 
+/* Alist of font name patterns vs the rescaling factor.  */
+
+Lisp_Object Vface_font_rescale_alist;
+
 /* Maximum number of fonts to consider in font_list.  If not an
    integer > 0, DEFAULT_FONT_LIST_LIMIT is used instead.  */
 
@@ -450,7 +411,7 @@ static int lface_id_to_name_size;
 
 /* TTY color-related functions (defined in tty-colors.el).  */
 
-Lisp_Object Qtty_color_desc, Qtty_color_by_index;
+Lisp_Object Qtty_color_desc, Qtty_color_by_index, Qtty_color_standard_values;
 
 /* The name of the function used to compute colors on TTYs.  */
 
@@ -473,10 +434,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
@@ -497,6 +454,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.  */
@@ -507,19 +468,19 @@ 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_ ((char *));
+static int may_use_scalable_font_p P_ ((const 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 x_face_list_fonts P_ ((struct frame *, char *,
-                                 struct font_name *, 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 *));
 static unsigned char *xstrlwr P_ ((unsigned char *));
 static void signal_error P_ ((char *, Lisp_Object));
 static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int));
-static void load_face_font P_ ((struct frame *, struct face *, int));
+static void load_face_font P_ ((struct frame *, struct face *));
 static void load_face_colors P_ ((struct frame *, struct face *, Lisp_Object *));
 static void free_face_colors P_ ((struct frame *, struct face *));
 static int face_color_gray_p P_ ((struct frame *, char *));
@@ -532,17 +493,17 @@ 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 *, 
+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));
-static struct face *realize_x_face P_ ((struct face_cache *,
-                                       Lisp_Object *, int, struct face *));
-static struct face *realize_tty_face P_ ((struct face_cache *,
-                                         Lisp_Object *, int));
+static struct face *realize_face P_ ((struct face_cache *, Lisp_Object *,
+                                     int));
+static struct face *realize_non_ascii_face P_ ((struct frame *, int,
+                                               struct face *));
+static struct face *realize_x_face P_ ((struct face_cache *, Lisp_Object *));
+static struct face *realize_tty_face P_ ((struct face_cache *, Lisp_Object *));
 static int realize_basic_faces P_ ((struct frame *));
 static int realize_default_face P_ ((struct frame *));
 static void realize_named_face P_ ((struct frame *, Lisp_Object, int));
@@ -552,14 +513,12 @@ static unsigned hash_string_case_insensitive P_ ((Lisp_Object));
 static unsigned lface_hash P_ ((Lisp_Object *));
 static int lface_same_font_attributes_p P_ ((Lisp_Object *, Lisp_Object *));
 static struct face_cache *make_face_cache P_ ((struct frame *));
-static void free_realized_face P_ ((struct frame *, struct face *));
 static void clear_face_gcs P_ ((struct face_cache *));
 static void free_face_cache P_ ((struct face_cache *));
 static int face_numeric_weight P_ ((Lisp_Object));
 static int face_numeric_slant P_ ((Lisp_Object));
 static int face_numeric_swidth P_ ((Lisp_Object));
 static int face_fontset P_ ((Lisp_Object *));
-static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int, int));
 static void merge_face_vectors P_ ((struct frame *, Lisp_Object *, Lisp_Object*, Lisp_Object));
 static void merge_face_inheritance P_ ((struct frame *f, Lisp_Object,
                                        Lisp_Object *, Lisp_Object));
@@ -569,9 +528,8 @@ static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object,
                                         Lisp_Object, int, int));
 static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
 static struct face *make_realized_face P_ ((Lisp_Object *));
-static void free_realized_faces P_ ((struct face_cache *));
 static char *best_matching_font P_ ((struct frame *, Lisp_Object *,
-                                    struct font_name *, int, int));
+                                    struct font_name *, int, 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 *));
@@ -597,7 +555,7 @@ 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));
@@ -605,6 +563,8 @@ extern Lisp_Object w32_list_fonts P_ ((struct frame *, Lisp_Object, int, int));
 
 #ifdef USE_X_TOOLKIT
 static void x_update_menu_appearance P_ ((struct frame *));
+
+extern void free_frame_menubar P_ ((struct frame *));
 #endif /* USE_X_TOOLKIT */
 
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -670,8 +630,8 @@ unregister_colors (pixels, n)
 
 
 DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
-  "Dump currently allocated colors and their reference counts to stderr.")
-  ()
+       doc: /* Dump currently allocated colors to stderr.  */)
+     ()
 {
   int i, n;
 
@@ -814,12 +774,38 @@ x_free_gc (f, gc)
 
 #endif  /* WINDOWSNT */
 
+#ifdef MAC_OS
+/* Mac OS emulation of GCs */
+
+extern XGCValues *XCreateGC (void *, Window, unsigned long, XGCValues *);
+
+static INLINE GC
+x_create_gc (f, mask, xgcv)
+     struct frame *f;
+     unsigned long mask;
+     XGCValues *xgcv;
+{
+  GC gc;
+  gc = XCreateGC (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), mask, xgcv);
+  return gc;
+}
+
+static INLINE void
+x_free_gc (f, gc)
+     struct frame *f;
+     GC gc;
+{
+  XFreeGC (FRAME_MAC_DISPLAY (f), gc);
+}
+
+#endif  /* MAC_OS */
+
 /* Like stricmp.  Used to compare parts of font names which are in
    ISO8859-1.  */
 
 int
 xstricmp (s1, s2)
-     unsigned char *s1, *s2;
+     const unsigned char *s1, *s2;
 {
   while (*s1 && *s2)
     {
@@ -876,7 +862,7 @@ frame_or_selected_frame (frame, nparam)
   if (NILP (frame))
     frame = selected_frame;
 
-  CHECK_LIVE_FRAME (frame, nparam);
+  CHECK_LIVE_FRAME (frame);
   return XFRAME (frame);
 }
 
@@ -912,6 +898,9 @@ init_frame_faces (f)
 #endif
 #ifdef WINDOWSNT
   if (!FRAME_WINDOW_P (f) || FRAME_W32_WINDOW (f))
+#endif
+#ifdef MAC_OS
+  if (!FRAME_MAC_P (f) || FRAME_MAC_WINDOW (f))
 #endif
     if (!realize_basic_faces (f))
       abort ();
@@ -979,6 +968,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.  */
@@ -986,13 +983,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
@@ -1013,9 +1007,9 @@ clear_face_cache (clear_fonts_p)
 
 
 DEFUN ("clear-face-cache", Fclear_face_cache, Sclear_face_cache, 0, 1, 0,
-  "Clear face caches on all frames.\n\
-Optional THOROUGHLY non-nil means try to free unused fonts, too.")
-  (thoroughly)
+       doc: /* Clear face caches on all frames.
+Optional THOROUGHLY non-nil means try to free unused fonts, too.  */)
+     (thoroughly)
      Lisp_Object thoroughly;
 {
   clear_face_cache (!NILP (thoroughly));
@@ -1029,26 +1023,36 @@ Optional THOROUGHLY non-nil means try to free unused fonts, too.")
 #ifdef HAVE_WINDOW_SYSTEM
 
 
-/* Remove those fonts from the font table of frame F exept for the
-   default ASCII font for the frame.  Called from clear_face_cache
+/* Remove fonts from the font table of DPYINFO except for the default
+   ASCII fonts of frames on that display.  Called from clear_face_cache
    from time to time.  */
 
 static void
-clear_font_table (f)
-     struct frame *f;
+clear_font_table (dpyinfo)
+     struct x_display_info *dpyinfo;
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   int i;
 
-  xassert (FRAME_WINDOW_P (f));
-
-  /* Free those fonts that are not used by the frame F as the default.  */
+  /* Free those fonts that are not used by frames on DPYINFO.  */
   for (i = 0; i < dpyinfo->n_fonts; ++i)
     {
       struct font_info *font_info = dpyinfo->font_table + i;
+      Lisp_Object tail, frame;
+
+      /* Check if slot is already free.  */
+      if (font_info->name == NULL)
+       continue;
+
+      /* Don't free a default font of some frame.  */
+      FOR_EACH_FRAME (tail, frame)
+       {
+         struct frame *f = XFRAME (frame);
+         if (FRAME_WINDOW_P (f)
+             && font_info->font == FRAME_FONT (f))
+           break;
+       }
 
-      if (!font_info->name
-         || font_info->font == FRAME_FONT (f))
+      if (!NILP (tail))
        continue;
 
       /* Free names.  */
@@ -1083,13 +1087,13 @@ clear_font_table (f)
 #ifdef HAVE_WINDOW_SYSTEM
 
 DEFUN ("bitmap-spec-p", Fbitmap_spec_p, Sbitmap_spec_p, 1, 1, 0,
-  "Value is non-nil if OBJECT is a valid bitmap specification.\n\
-A bitmap specification is either a string, a file name, or a list\n\
-(WIDTH HEIGHT DATA) where WIDTH is the pixel width of the bitmap,\n\
-HEIGHT is its height, and DATA is a string containing the bits of\n\
-the pixmap.  Bits are stored row by row, each row occupies\n\
-(WIDTH + 7)/8 bytes.")
-  (object)
+       doc: /* Value is non-nil if OBJECT is a valid bitmap specification.
+A bitmap specification is either a string, a file name, or a list
+\(WIDTH HEIGHT DATA) where WIDTH is the pixel width of the bitmap,
+HEIGHT is its height, and DATA is a string containing the bits of
+the pixmap.  Bits are stored row by row, each row occupies
+\(WIDTH + 7)/8 bytes.  */)
+     (object)
      Lisp_Object object;
 {
   int pixmap_p = 0;
@@ -1123,7 +1127,7 @@ the pixmap.  Bits are stored row by row, each row occupies\n\
        {
          int bytes_per_row = ((XFASTINT (width) + BITS_PER_CHAR - 1)
                               / BITS_PER_CHAR);
-         if (STRING_BYTES (XSTRING (data)) >= bytes_per_row * XINT (height))
+         if (SBYTES (data) >= bytes_per_row * XINT (height))
            pixmap_p = 1;
        }
     }
@@ -1167,7 +1171,7 @@ load_pixmap (f, name, w_ptr, h_ptr)
       h = XINT (Fcar (Fcdr (name)));
       bits = Fcar (Fcdr (Fcdr (name)));
 
-      bitmap_id = x_create_bitmap_from_data (f, XSTRING (bits)->data,
+      bitmap_id = x_create_bitmap_from_data (f, SDATA (bits),
                                             w, h);
     }
   else
@@ -1206,58 +1210,34 @@ load_pixmap (f, name, w_ptr, h_ptr)
 
 
 \f
-/***********************************************************************
-                        Minimum font bounds
- ***********************************************************************/
-
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* Update the line_height of frame F.  Return non-zero if line height
-   changes.  */
-
-int
-frame_update_line_height (f)
-     struct frame *f;
-{
-  int line_height, changed_p;
-
-  line_height = FONT_HEIGHT (FRAME_FONT (f));
-  changed_p = line_height != FRAME_LINE_HEIGHT (f);
-  FRAME_LINE_HEIGHT (f) = line_height;
-  return changed_p;
-}
-
-#endif /* HAVE_WINDOW_SYSTEM */
-
-\f
 /***********************************************************************
                                Fonts
  ***********************************************************************/
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-/* Load font of face FACE which is used on frame F to display
-   character C.  The name of the font to load is determined by lface
-   and fontset of FACE.  */
+/* Load font of face FACE which is used on frame F to display ASCII
+   characters.  The name of the font to load is determined by lface.  */
 
 static void
-load_face_font (f, face, c)
+load_face_font (f, face)
      struct frame *f;
      struct face *face;
-     int c;
 {
   struct font_info *font_info = NULL;
   char *font_name;
+  int needs_overstrike;
 
   face->font_info_id = -1;
   face->font = NULL;
+  face->font_name = NULL;
 
-  font_name = choose_face_font (f, face->lface, face->fontset, c);
+  font_name = choose_face_font (f, face->lface, Qnil, &needs_overstrike);
   if (!font_name)
     return;
 
   BLOCK_INPUT;
-  font_info = FS_LOAD_FACE_FONT (f, c, font_name, face);
+  font_info = FS_LOAD_FONT (f, font_name);
   UNBLOCK_INPUT;
 
   if (font_info)
@@ -1265,6 +1245,7 @@ load_face_font (f, face, c)
       face->font_info_id = font_info->font_idx;
       face->font = font_info->font;
       face->font_name = font_info->full_name;
+      face->overstrike = needs_overstrike;
       if (face->gc)
        {
          x_free_gc (f, face->gc);
@@ -1285,6 +1266,98 @@ load_face_font (f, face, c)
                                X Colors
  ***********************************************************************/
 
+/* Parse RGB_LIST, and fill in the RGB fields of COLOR.
+   RGB_LIST should contain (at least) 3 lisp integers.
+   Return 0 if there's a problem with RGB_LIST, otherwise return 1.  */
+
+static int
+parse_rgb_list (rgb_list, color)
+     Lisp_Object rgb_list;
+     XColor *color;
+{
+#define PARSE_RGB_LIST_FIELD(field)                                    \
+  if (CONSP (rgb_list) && INTEGERP (XCAR (rgb_list)))                  \
+    {                                                                  \
+      color->field = XINT (XCAR (rgb_list));                           \
+      rgb_list = XCDR (rgb_list);                                      \
+    }                                                                  \
+  else                                                                 \
+    return 0;
+
+  PARSE_RGB_LIST_FIELD (red);
+  PARSE_RGB_LIST_FIELD (green);
+  PARSE_RGB_LIST_FIELD (blue);
+
+  return 1;
+}
+
+
+/* Lookup on frame F the color described by the lisp string COLOR.
+   The resulting tty color is returned in TTY_COLOR; if STD_COLOR is
+   non-zero, then the `standard' definition of the same color is
+   returned in it.  */
+
+static int
+tty_lookup_color (f, color, tty_color, std_color)
+     struct frame *f;
+     Lisp_Object color;
+     XColor *tty_color, *std_color;
+{
+  Lisp_Object frame, color_desc;
+
+  if (!STRINGP (color) || NILP (Ffboundp (Qtty_color_desc)))
+    return 0;
+
+  XSETFRAME (frame, f);
+
+  color_desc = call2 (Qtty_color_desc, color, frame);
+  if (CONSP (color_desc) && CONSP (XCDR (color_desc)))
+    {
+      Lisp_Object rgb;
+
+      if (! INTEGERP (XCAR (XCDR (color_desc))))
+       return 0;
+
+      tty_color->pixel = XINT (XCAR (XCDR (color_desc)));
+
+      rgb = XCDR (XCDR (color_desc));
+      if (! parse_rgb_list (rgb, tty_color))
+       return 0;
+
+      /* Should we fill in STD_COLOR too?  */
+      if (std_color)
+       {
+         /* Default STD_COLOR to the same as TTY_COLOR.  */
+         *std_color = *tty_color;
+
+         /* Do a quick check to see if the returned descriptor is
+            actually _exactly_ equal to COLOR, otherwise we have to
+            lookup STD_COLOR separately.  If it's impossible to lookup
+            a standard color, we just give up and use TTY_COLOR.  */
+         if ((!STRINGP (XCAR (color_desc))
+              || NILP (Fstring_equal (color, XCAR (color_desc))))
+             && !NILP (Ffboundp (Qtty_color_standard_values)))
+           {
+             /* Look up STD_COLOR separately.  */
+             rgb = call1 (Qtty_color_standard_values, color);
+             if (! parse_rgb_list (rgb, std_color))
+               return 0;
+           }
+       }
+
+      return 1;
+    }
+  else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist"))))
+    /* We were called early during startup, and the colors are not
+       yet set up in tty-defined-color-alist.  Don't return a failure
+       indication, since this produces the annoying "Unable to
+       load color" messages in the *Messages* buffer.  */
+    return 1;
+  else
+    /* tty-color-desc seems to have returned a bad value.  */
+    return 0;
+}
+
 /* A version of defined_color for non-X frames.  */
 
 int
@@ -1294,52 +1367,28 @@ tty_defined_color (f, color_name, color_def, alloc)
      XColor *color_def;
      int alloc;
 {
-  Lisp_Object color_desc;
-  unsigned long color_idx = FACE_TTY_DEFAULT_COLOR;
-  unsigned long red = 0, green = 0, blue = 0;
   int status = 1;
 
-  if (*color_name && !NILP (Ffboundp (Qtty_color_desc)))
-    {
-      Lisp_Object frame;
+  /* Defaults.  */
+  color_def->pixel = FACE_TTY_DEFAULT_COLOR;
+  color_def->red = 0;
+  color_def->blue = 0;
+  color_def->green = 0;
 
-      XSETFRAME (frame, f);
-      status = 0;
-      color_desc = call2 (Qtty_color_desc, build_string (color_name), frame);
-      if (CONSP (color_desc) && CONSP (XCDR (color_desc)))
-       {
-         color_idx = XINT (XCAR (XCDR (color_desc)));
-         if (CONSP (XCDR (XCDR (color_desc))))
-           {
-             red = XINT (XCAR (XCDR (XCDR (color_desc))));
-             green = XINT (XCAR (XCDR (XCDR (XCDR (color_desc)))));
-             blue = XINT (XCAR (XCDR (XCDR (XCDR (XCDR (color_desc))))));
-           }
-         status = 1;
-       }
-      else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist"))))
-       /* We were called early during startup, and the colors are not
-          yet set up in tty-defined-color-alist.  Don't return a failure
-          indication, since this produces the annoying "Unable to
-          load color" messages in the *Messages* buffer.  */
-       status = 1;
-    }
-  if (color_idx == FACE_TTY_DEFAULT_COLOR && *color_name)
+  if (*color_name)
+    status = tty_lookup_color (f, build_string (color_name), color_def, NULL);
+
+  if (color_def->pixel == FACE_TTY_DEFAULT_COLOR && *color_name)
     {
       if (strcmp (color_name, "unspecified-fg") == 0)
-       color_idx = FACE_TTY_DEFAULT_FG_COLOR;
+       color_def->pixel = FACE_TTY_DEFAULT_FG_COLOR;
       else if (strcmp (color_name, "unspecified-bg") == 0)
-       color_idx = FACE_TTY_DEFAULT_BG_COLOR;
+       color_def->pixel = FACE_TTY_DEFAULT_BG_COLOR;
     }
 
-  if (color_idx != FACE_TTY_DEFAULT_COLOR)
+  if (color_def->pixel != FACE_TTY_DEFAULT_COLOR)
     status = 1;
 
-  color_def->pixel = color_idx;
-  color_def->red = red;
-  color_def->green = green;
-  color_def->blue = blue;
-
   return status;
 }
 
@@ -1367,7 +1416,7 @@ defined_color (f, color_name, color_def, alloc)
   else if (FRAME_W32_P (f))
     return w32_defined_color (f, color_name, color_def, alloc);
 #endif
-#ifdef macintosh
+#ifdef MAC_OS
   else if (FRAME_MAC_P (f))
     return mac_defined_color (f, color_name, color_def, alloc);
 #endif
@@ -1467,36 +1516,36 @@ face_color_supported_p (f, color_name, background_p)
 
 
 DEFUN ("color-gray-p", Fcolor_gray_p, Scolor_gray_p, 1, 2, 0,
-  "Return non-nil if COLOR is a shade of gray (or white or black).\n\
-FRAME specifies the frame and thus the display for interpreting COLOR.\n\
-If FRAME is nil or omitted, use the selected frame.")
-   (color, frame)
+       doc: /* Return non-nil if COLOR is a shade of gray (or white or black).
+FRAME specifies the frame and thus the display for interpreting COLOR.
+If FRAME is nil or omitted, use the selected frame.  */)
+     (color, frame)
      Lisp_Object color, frame;
 {
   struct frame *f;
 
-  CHECK_FRAME (frame, 0);
-  CHECK_STRING (color, 0);
+  CHECK_FRAME (frame);
+  CHECK_STRING (color);
   f = XFRAME (frame);
-  return face_color_gray_p (f, XSTRING (color)->data) ? Qt : Qnil;
+  return face_color_gray_p (f, SDATA (color)) ? Qt : Qnil;
 }
 
 
 DEFUN ("color-supported-p", Fcolor_supported_p,
-       Scolor_supported_p, 2, 3, 0,
-  "Return non-nil if COLOR can be displayed on FRAME.\n\
-BACKGROUND-P non-nil means COLOR is used as a background.\n\
-If FRAME is nil or omitted, use the selected frame.\n\
-COLOR must be a valid color name.")
-   (color, frame, background_p)
+       Scolor_supported_p, 1, 3, 0,
+       doc: /* Return non-nil if COLOR can be displayed on FRAME.
+BACKGROUND-P non-nil means COLOR is used as a background.
+If FRAME is nil or omitted, use the selected frame.
+COLOR must be a valid color name.  */)
+     (color, frame, background_p)
      Lisp_Object frame, color, background_p;
 {
   struct frame *f;
 
-  CHECK_FRAME (frame, 0);
-  CHECK_STRING (color, 0);
+  CHECK_FRAME (frame);
+  CHECK_STRING (color);
   f = XFRAME (frame);
-  if (face_color_supported_p (f, XSTRING (color)->data, !NILP (background_p)))
+  if (face_color_supported_p (f, SDATA (color), !NILP (background_p)))
     return Qt;
   return Qnil;
 }
@@ -1530,7 +1579,7 @@ load_color (f, face, name, target_index)
 
   /* if the color map is full, defined_color will return a best match
      to the values in an existing cell. */
-  if (!defined_color (f, XSTRING (name)->data, &color, 1))
+  if (!defined_color (f, SDATA (name), &color, 1))
     {
       add_to_log ("Unable to load color \"%s\"", name, Qnil);
 
@@ -1610,7 +1659,7 @@ load_face_colors (f, face, attrs)
      face_color_supported_p is smart enough to know that grays are
      "supported" as background because we are supposed to use stipple
      for them.  */
-  if (!face_color_supported_p (f, XSTRING (bg)->data, 0)
+  if (!face_color_supported_p (f, SDATA (bg), 0)
       && !NILP (Fbitmap_spec_p (Vface_default_stipple)))
     {
       x_destroy_bitmap (f, face->stipple);
@@ -1631,9 +1680,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
 }
 
@@ -1646,6 +1698,9 @@ free_face_colors (f, face)
      struct face *face;
 {
 #ifdef HAVE_X_WINDOWS
+  if (face->colors_copied_bitwise_p)
+    return;
+
   BLOCK_INPUT;
 
   if (!face->foreground_defaulted_p)
@@ -1854,6 +1909,11 @@ struct font_name
      split_font_name for which these are.  */
   int numeric[XLFD_LAST];
 
+  /* If the original name matches one of Vface_font_rescale_alist,
+     the value is the corresponding rescale ratio.  Otherwise, the
+     value is 1.0.  */
+  double rescale_ratio;
+
   /* Lower value mean higher priority.  */
   int registry_priority;
 };
@@ -1868,7 +1928,7 @@ static struct frame *font_frame;
    font height, then for weight, then for slant.'  This variable can be
    set via set-face-font-sort-order.  */
 
-#ifdef macintosh
+#ifdef MAC_OS
 static int font_sort_order[4] = {
   XLFD_SWIDTH, XLFD_POINT_SIZE, XLFD_WEIGHT, XLFD_SLANT
 };
@@ -2048,7 +2108,7 @@ face_value (table, dim, symbol)
 static INLINE int
 face_numeric_value (table, dim, symbol)
      struct table_entry *table;
-     int dim;
+     size_t dim;
      Lisp_Object symbol;
 {
   struct table_entry *p = face_value (table, dim, symbol);
@@ -2089,6 +2149,62 @@ face_numeric_swidth (width)
   return face_numeric_value (swidth_table, DIM (swidth_table), width);
 }
 
+Lisp_Object
+split_font_name_into_vector (fontname)
+     Lisp_Object fontname;
+{
+  struct font_name font;
+  Lisp_Object vec;
+  int i;
+
+  font.name = LSTRDUPA (fontname);
+  if (! split_font_name (NULL, &font, 0))
+    return Qnil;
+  vec = Fmake_vector (make_number (XLFD_LAST), Qnil);
+  for (i = 0; i < XLFD_LAST; i++)
+    if (font.fields[i][0] != '*')
+      ASET (vec, i, build_string (font.fields[i]));
+  return vec;
+}
+
+Lisp_Object
+build_font_name_from_vector (vec)
+     Lisp_Object vec;
+{
+  struct font_name font;
+  Lisp_Object fontname;
+  char *p;
+  int i;
+
+  for (i = 0; i < XLFD_LAST; i++)
+    {
+      font.fields[i] = (NILP (AREF (vec, i))
+                       ? "*" : (char *) SDATA (AREF (vec, i)));
+      if ((i == XLFD_FAMILY || i == XLFD_REGISTRY)
+         && (p = strchr (font.fields[i], '-')))
+       {
+         char *p1 = STRDUPA (font.fields[i]);
+
+         p1[p - font.fields[i]] = '\0';
+         if (i == XLFD_FAMILY)
+           {
+             font.fields[XLFD_FOUNDRY] = p1;
+             font.fields[XLFD_FAMILY] = p + 1;
+           }
+         else
+           {
+             font.fields[XLFD_REGISTRY] = p1;
+             font.fields[XLFD_ENCODING] = p + 1;
+             break;
+           }
+       }
+    }
+
+  p = build_font_name (&font);
+  fontname = build_string (p);
+  xfree (p);
+  return fontname;
+}
 
 #ifdef HAVE_WINDOW_SYSTEM
 
@@ -2114,7 +2230,9 @@ xlfd_fixed_p (font)
    72dpi versions, only.)
 
    Value is the real point size of FONT on frame F, or 0 if it cannot
-   be determined.  */
+   be determined.
+
+   By side effect, set FONT->numeric[XLFD_PIXEL_SIZE].  */
 
 static INLINE int
 xlfd_point_size (f, font)
@@ -2148,11 +2266,12 @@ xlfd_point_size (f, font)
          start = end;
        }
 
-      pixel = matrix[3] / 10.0;
+      pixel = matrix[3];
     }
   else
     pixel = atoi (pixel_field);
-  
+
+  font->numeric[XLFD_PIXEL_SIZE] = pixel;
   if (pixel == 0)
     real_pt = 0;
   else
@@ -2184,6 +2303,25 @@ pixel_point_size (f, pixel)
 }
 
 
+/* Return a rescaling ratio of a font of NAME.  */
+
+static double
+font_rescale_ratio (name)
+     char *name;
+{
+  Lisp_Object tail, elt;
+
+  for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail))
+    {
+      elt = XCAR (tail);
+      if (STRINGP (XCAR (elt)) && FLOATP (XCDR (elt))
+         && fast_c_string_match_ignore_case (XCAR (elt), name) >= 0)
+       return XFLOAT_DATA (XCDR (elt));
+    }
+  return 1.0;
+}
+
+
 /* Split XLFD font name FONT->name destructively into NUL-terminated,
    lower-case fields in FONT->fields.  NUMERIC_P non-zero means
    compute numeric values for fields XLFD_POINT_SIZE, XLFD_SWIDTH,
@@ -2200,6 +2338,11 @@ split_font_name (f, font, numeric_p)
 {
   int i = 0;
   int success_p;
+  double rescale_ratio;
+
+  if (numeric_p)
+    /* This must be done before splitting the font name.  */
+    rescale_ratio = font_rescale_ratio (font->name);
 
   if (*font->name == '-')
     {
@@ -2215,19 +2358,19 @@ split_font_name (f, font, numeric_p)
             indicated by tilde characters which we replace with
             `-' characters, here.  */
          if (*p == '['
-             && (i == XLFD_PIXEL_SIZE
-                 || i == XLFD_POINT_SIZE))
+             && (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;
+             for (j = 0, start = font->fields[i - 1] + 1;
                   j < 4;
                   ++j, start = end)
                if (strtod (start, &end) == 0 && start == end)
@@ -2259,6 +2402,7 @@ split_font_name (f, font, numeric_p)
       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]);
+      font->rescale_ratio = rescale_ratio;
     }
 
   /* Initialize it to zero.  It will be overridden by font_list while
@@ -2349,10 +2493,10 @@ sort_fonts (f, fonts, nfonts, cmpfn)
    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)
+x_face_list_fonts (f, pattern, pfonts, nfonts, try_alternatives_p)
      struct frame *f;
      char *pattern;
-     struct font_name *fonts;
+     struct font_name **pfonts;
      int nfonts, try_alternatives_p;
 {
   int n, nignored;
@@ -2361,7 +2505,10 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p)
      better to do it the other way around. */
   Lisp_Object lfonts;
   Lisp_Object lpattern, tem;
+  struct font_name *fonts = 0;
+  int num_fonts = nfonts;
 
+  *pfonts = 0;
   lpattern = build_string (pattern);
 
   /* Get the list of fonts matching PATTERN.  */
@@ -2373,13 +2520,16 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p)
   lfonts = x_list_fonts (f, lpattern, -1, nfonts);
 #endif
 
+  if (nfonts < 0 && CONSP (lfonts))
+    num_fonts = XFASTINT (Flength (lfonts));
+
   /* 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))
+  for (tem = lfonts; CONSP (tem) && n < num_fonts; tem = XCDR (tem))
     {
       Lisp_Object elt, tail;
-      char *name = XSTRING (XCAR (tem))->data;
+      const char *name = SDATA (XCAR (tem));
 
       /* Ignore fonts matching a pattern from face-ignored-fonts.  */
       for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
@@ -2395,6 +2545,12 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p)
          continue;
        }
 
+      if (! fonts)
+        {
+          *pfonts = (struct font_name *) xmalloc (num_fonts * sizeof **pfonts);
+          fonts = *pfonts;
+        }
+
       /* Make a copy of the font name.  */
       fonts[n].name = xstrdup (name);
 
@@ -2418,12 +2574,18 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p)
     {
       Lisp_Object list = Valternate_fontname_alist;
 
+      if (*pfonts)
+        {
+          xfree (*pfonts);
+          *pfonts = 0;
+        }
+
       while (CONSP (list))
        {
          Lisp_Object entry = XCAR (list);
          if (CONSP (entry)
              && STRINGP (XCAR (entry))
-             && strcmp (XSTRING (XCAR (entry))->data, pattern) == 0)
+             && strcmp (SDATA (XCAR (entry)), pattern) == 0)
            break;
          list = XCDR (list);
        }
@@ -2439,9 +2601,9 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p)
                     STRINGP (name))
                 /* Ignore patterns equal to PATTERN because we tried that
                    already with no success.  */
-                && (strcmp (XSTRING (name)->data, pattern) == 0
-                    || (n = x_face_list_fonts (f, XSTRING (name)->data,
-                                               fonts, nfonts, 0),
+                && (strcmp (SDATA (name), pattern) == 0
+                    || (n = x_face_list_fonts (f, SDATA (name),
+                                               pfonts, nfonts, 0),
                         n == 0)))
            patterns = XCDR (patterns);
        }
@@ -2470,17 +2632,17 @@ sorted_font_list (f, pattern, cmpfn, fonts)
 
   /* Get the list of fonts matching pattern.  100 should suffice.  */
   nfonts = DEFAULT_FONT_LIST_LIMIT;
-  if (INTEGERP (Vfont_list_limit) && XINT (Vfont_list_limit) > 0)
-    nfonts = XFASTINT (Vfont_list_limit);
+  if (INTEGERP (Vfont_list_limit))
+    nfonts = XINT (Vfont_list_limit);
 
-  *fonts = (struct font_name *) xmalloc (nfonts * sizeof **fonts);
-  nfonts = x_face_list_fonts (f, pattern, *fonts, nfonts, 1);
+  *fonts = NULL;
+  nfonts = x_face_list_fonts (f, pattern, fonts, nfonts, 1);
 
   /* Sort the resulting array and return it in *FONTS.  If no
      fonts were found, make sure to set *FONTS to null.  */
   if (nfonts)
     sort_fonts (f, *fonts, nfonts, cmpfn);
-  else
+  else if (*fonts)
     {
       xfree (*fonts);
       *fonts = NULL;
@@ -2533,12 +2695,12 @@ cmp_font_names (a, b)
 }
 
 
-/* Get a sorted list of fonts of family FAMILY on frame F.  If PATTERN
-   is non-nil list fonts matching that pattern.  Otherwise, if
-   REGISTRY is non-nil return only fonts with that registry, otherwise
-   return fonts of any registry.  Set *FONTS to a vector of font_name
-   structures allocated from the heap containing the fonts found.
-   Value is the number of fonts found.  */
+/* Get a sorted list of fonts matching PATTERN on frame F.  If PATTERN
+   is nil, list fonts matching FAMILY and REGISTRY.  FAMILY is a
+   family name string or nil.  REGISTRY is a registry name string.
+   Set *FONTS to a vector of font_name structures allocated from the
+   heap containing the fonts found.  Value is the number of fonts
+   found.  */
 
 static int
 font_list_1 (f, pattern, family, registry, fonts)
@@ -2550,8 +2712,8 @@ font_list_1 (f, pattern, family, registry, fonts)
 
   if (NILP (pattern))
     {
-      family_str = (NILP (family) ? "*" : (char *) XSTRING (family)->data);
-      registry_str = (NILP (registry) ? "*" : (char *) XSTRING (registry)->data);
+      family_str = (NILP (family) ? "*" : (char *) SDATA (family));
+      registry_str = (NILP (registry) ? "*" : (char *) SDATA (registry));
 
       pattern_str = (char *) alloca (strlen (family_str)
                                     + strlen (registry_str)
@@ -2569,7 +2731,7 @@ font_list_1 (f, pattern, family, registry, fonts)
        }
     }
   else
-    pattern_str = (char *) XSTRING (pattern)->data;
+    pattern_str = (char *) SDATA (pattern);
 
   return sorted_font_list (f, pattern_str, cmp_font_names, fonts);
 }
@@ -2599,11 +2761,12 @@ concat_font_list (fonts1, nfonts1, fonts2, nfonts2)
 
 /* Get a sorted list of fonts of family FAMILY on frame F.
 
-   If PATTERN is non-nil list fonts matching that pattern.
+   If PATTERN is non-nil, list fonts matching that pattern.
+
+   If REGISTRY is non-nil, it is a list of registry (and encoding)
+   names.  Return fonts with those registries and the alternative
+   registries from Vface_alternative_font_registry_alist.
 
-   If REGISTRY is non-nil, return fonts with that registry and the
-   alternative registries from Vface_alternative_font_registry_alist.
-   
    If REGISTRY is nil return fonts of any registry.
 
    Set *FONTS to a vector of font_name structures allocated from the
@@ -2616,35 +2779,37 @@ font_list (f, pattern, family, registry, fonts)
      Lisp_Object pattern, family, registry;
      struct font_name **fonts;
 {
-  int nfonts = font_list_1 (f, pattern, family, registry, fonts);
-  
-  if (!NILP (registry)
-      && CONSP (Vface_alternative_font_registry_alist))
+  int nfonts;
+  int reg_prio;
+  int i;
+
+  if (NILP (registry))
+    return font_list_1 (f, pattern, family, registry, fonts);
+
+  for (reg_prio = 0, nfonts = 0; CONSP (registry); registry = XCDR (registry))
     {
-      Lisp_Object alter;
+      Lisp_Object elt, alter;
+      int nfonts2;
+      struct font_name *fonts2;
 
-      alter = Fassoc (registry, Vface_alternative_font_registry_alist);
-      if (CONSP (alter))
+      elt = XCAR (registry);
+      alter = Fassoc (elt, Vface_alternative_font_registry_alist);
+      if (NILP (alter))
+       alter = Fcons (elt, Qnil);
+      for (; CONSP (alter); alter = XCDR (alter), reg_prio++)
        {
-         int reg_prio, i;
-
-         for (alter = XCDR (alter), reg_prio = 1;
-              CONSP (alter);
-              alter = XCDR (alter), reg_prio++)
-           if (STRINGP (XCAR (alter)))
-             {
-               int nfonts2;
-               struct font_name *fonts2;
-
-               nfonts2 = font_list_1 (f, pattern, family, XCAR (alter),
-                                      &fonts2);
+         nfonts2 = font_list_1 (f, pattern, family, XCAR (alter), &fonts2);
+         if (nfonts2 > 0)
+           {
+             if (reg_prio > 0)
                for (i = 0; i < nfonts2; i++)
                  fonts2[i].registry_priority = reg_prio;
-               *fonts = (nfonts > 0
-                         ? concat_font_list (*fonts, nfonts, fonts2, nfonts2)
-                         : fonts2);
-               nfonts += nfonts2;
-             }
+             if (nfonts > 0)
+               *fonts = concat_font_list (*fonts, nfonts, fonts2, nfonts2);
+             else
+               *fonts = fonts2;
+             nfonts += nfonts2;
+           }
        }
     }
 
@@ -2666,7 +2831,7 @@ remove_duplicates (list)
     {
       Lisp_Object next = XCDR (tail);
       if (!NILP (Fequal (XCAR (next), XCAR (tail))))
-       XCDR (tail) = XCDR (next);
+       XSETCDR (tail, XCDR (next));
       else
        tail = XCDR (tail);
     }
@@ -2674,22 +2839,22 @@ remove_duplicates (list)
 
 
 DEFUN ("x-family-fonts", Fx_family_fonts, Sx_family_fonts, 0, 2, 0,
-  "Return a list of available fonts of family FAMILY on FRAME.\n\
-If FAMILY is omitted or nil, list all families.\n\
-Otherwise, FAMILY must be a string, possibly containing wildcards\n\
-`?' and `*'.\n\
-If FRAME is omitted or nil, use the selected frame.\n\
-Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT\n\
-SLANT FIXED-P FULL REGISTRY-AND-ENCODING].\n\
-FAMILY is the font family name.  POINT-SIZE is the size of the\n\
-font in 1/10 pt.  WIDTH, WEIGHT, and SLANT are symbols describing the\n\
-width, weight and slant of the font.  These symbols are the same as for\n\
-face attributes.  FIXED-P is non-nil if the font is fixed-pitch.\n\
-FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string\n\
-giving the registry and encoding of the font.\n\
-The result list is sorted according to the current setting of\n\
-the face font sort order.")
-  (family, frame)
+       doc: /* Return a list of available fonts of family FAMILY on FRAME.
+If FAMILY is omitted or nil, list all families.
+Otherwise, FAMILY must be a string, possibly containing wildcards
+`?' and `*'.
+If FRAME is omitted or nil, use the selected frame.
+Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT
+SLANT FIXED-P FULL REGISTRY-AND-ENCODING].
+FAMILY is the font family name.  POINT-SIZE is the size of the
+font in 1/10 pt.  WIDTH, WEIGHT, and SLANT are symbols describing the
+width, weight and slant of the font.  These symbols are the same as for
+face attributes.  FIXED-P is non-nil if the font is fixed-pitch.
+FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string
+giving the registry and encoding of the font.
+The result list is sorted according to the current setting of
+the face font sort order.  */)
+     (family, frame)
      Lisp_Object family, frame;
 {
   struct frame *f = check_x_frame (frame);
@@ -2699,7 +2864,7 @@ the face font sort order.")
   struct gcpro gcpro1;
 
   if (!NILP (family))
-    CHECK_STRING (family, 1);
+    CHECK_STRING (family);
 
   result = Qnil;
   GCPRO1 (result);
@@ -2734,12 +2899,12 @@ the face font sort order.")
 
 DEFUN ("x-font-family-list", Fx_font_family_list, Sx_font_family_list,
        0, 1, 0,
-  "Return a list of available font families on FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.\n\
-Value is a list of conses (FAMILY . FIXED-P) where FAMILY\n\
-is a font family, and FIXED-P is non-nil if fonts of that family\n\
-are fixed-pitch.")
-  (frame)
+       doc: /* Return a list of available font families on FRAME.
+If FRAME is omitted or nil, use the selected frame.
+Value is a list of conses (FAMILY . FIXED-P) where FAMILY
+is a font family, and FIXED-P is non-nil if fonts of that family
+are fixed-pitch.  */)
+     (frame)
      Lisp_Object frame;
 {
   struct frame *f = check_x_frame (frame);
@@ -2747,24 +2912,11 @@ are fixed-pitch.")
   struct font_name *fonts;
   Lisp_Object result;
   struct gcpro gcpro1;
-  int count = specpdl_ptr - specpdl;
-  int limit;
+  int count = SPECPDL_INDEX ();
 
-  /* Let's consider all fonts.  Increase the limit for matching
-     fonts until we have them all.  */
-  for (limit = 500;;)
-    {
-      specbind (intern ("font-list-limit"), make_number (limit));
-      nfonts = font_list (f, Qnil, Qnil, Qnil, &fonts);
-
-      if (nfonts == limit)
-       {
-         free_font_names (fonts, nfonts);
-         limit *= 2;
-       }
-      else
-       break;
-    }
+  /* Let's consider all fonts.  */
+  specbind (intern ("font-list-limit"), make_number (-1));
+  nfonts = font_list (f, Qnil, Qnil, Qnil, &fonts);
 
   result = Qnil;
   GCPRO1 (result);
@@ -2781,26 +2933,26 @@ are fixed-pitch.")
 
 
 DEFUN ("x-list-fonts", Fx_list_fonts, Sx_list_fonts, 1, 5, 0,
-  "Return a list of the names of available fonts matching PATTERN.\n\
-If optional arguments FACE and FRAME are specified, return only fonts\n\
-the same size as FACE on FRAME.\n\
-PATTERN is a string, perhaps with wildcard characters;\n\
-  the * character matches any substring, and\n\
-  the ? character matches any single character.\n\
-  PATTERN is case-insensitive.\n\
-FACE is a face name--a symbol.\n\
-\n\
-The return value is a list of strings, suitable as arguments to\n\
-set-face-font.\n\
-\n\
-Fonts Emacs can't use may or may not be excluded\n\
-even if they match PATTERN and FACE.\n\
-The optional fourth argument MAXIMUM sets a limit on how many\n\
-fonts to match.  The first MAXIMUM fonts are reported.\n\
-The optional fifth argument WIDTH, if specified, is a number of columns\n\
-occupied by a character of a font.  In that case, return only fonts\n\
-the WIDTH times as wide as FACE on FRAME.")
-  (pattern, face, frame, maximum, width)
+       doc: /* Return a list of the names of available fonts matching PATTERN.
+If optional arguments FACE and FRAME are specified, return only fonts
+the same size as FACE on FRAME.
+PATTERN is a string, perhaps with wildcard characters;
+  the * character matches any substring, and
+  the ? character matches any single character.
+  PATTERN is case-insensitive.
+FACE is a face name--a symbol.
+
+The return value is a list of strings, suitable as arguments to
+set-face-font.
+
+Fonts Emacs can't use may or may not be excluded
+even if they match PATTERN and FACE.
+The optional fourth argument MAXIMUM sets a limit on how many
+fonts to match.  The first MAXIMUM fonts are reported.
+The optional fifth argument WIDTH, if specified, is a number of columns
+occupied by a character of a font.  In that case, return only fonts
+the WIDTH times as wide as FACE on FRAME.  */)
+     (pattern, face, frame, maximum, width)
     Lisp_Object pattern, face, frame, maximum, width;
 {
   struct frame *f;
@@ -2808,18 +2960,18 @@ the WIDTH times as wide as FACE on FRAME.")
   int maxnames;
 
   check_x ();
-  CHECK_STRING (pattern, 0);
+  CHECK_STRING (pattern);
 
   if (NILP (maximum))
-    maxnames = 2000;
+    maxnames = -1;
   else
     {
-      CHECK_NATNUM (maximum, 0);
+      CHECK_NATNUM (maximum);
       maxnames = XINT (maximum);
     }
 
   if (!NILP (width))
-    CHECK_NUMBER (width, 4);
+    CHECK_NUMBER (width);
 
   /* We can't simply call check_x_frame because this function may be
      called before any frame is created.  */
@@ -2839,15 +2991,22 @@ the WIDTH times as wide as FACE on FRAME.")
     {
       /* This is of limited utility since it works with character
         widths.  Keep it for compatibility.  --gerd.  */
-      int face_id = lookup_named_face (f, face, 0);
+      int face_id = lookup_named_face (f, face);
       struct face *face = (face_id < 0
                           ? NULL
                           : FACE_FROM_ID (f, face_id));
 
+#ifdef WINDOWSNT
+/* 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
+
       if (face && face->font)
        size = FONT_WIDTH (face->font);
       else
-       size = FONT_WIDTH (FRAME_FONT (f));
+       size = FONT_WIDTH (FRAME_FONT (f));  /* FRAME_COLUMN_WIDTH (f) */
 
       if (!NILP (width))
        size *= XINT (width);
@@ -2891,6 +3050,7 @@ the WIDTH times as wide as FACE on FRAME.")
 #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)
+#define LFACE_FONTSET(LFACE)       AREF ((LFACE), LFACE_FONTSET_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.  */
@@ -2954,6 +3114,8 @@ check_lface_attrs (attrs)
   xassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
           || NILP (attrs[LFACE_FONT_INDEX])
           || STRINGP (attrs[LFACE_FONT_INDEX]));
+  xassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
+          || STRINGP (attrs[LFACE_FONTSET_INDEX]));
 #endif
 }
 
@@ -2990,7 +3152,7 @@ resolve_face_name (face_name)
   Lisp_Object aliased;
 
   if (STRINGP (face_name))
-    face_name = intern (XSTRING (face_name)->data);
+    face_name = intern (SDATA (face_name));
 
   while (SYMBOLP (face_name))
     {
@@ -3080,8 +3242,8 @@ lface_fully_specified_p (attrs)
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX
-       && i != LFACE_AVGWIDTH_INDEX)
-      if (UNSPECIFIEDP (attrs[i])) 
+       && i != LFACE_AVGWIDTH_INDEX && i != LFACE_FONTSET_INDEX)
+      if (UNSPECIFIEDP (attrs[i]))
         break;
 
   return i == LFACE_VECTOR_SIZE;
@@ -3113,13 +3275,19 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
   int pt;
   int have_xlfd_p;
   int fontset;
-  char *font_name = XSTRING (fontname)->data;
+  char *font_name = SDATA (fontname);
   struct font_info *font_info;
 
   /* If FONTNAME is actually a fontset name, get ASCII font name of it.  */
   fontset = fs_query_fontset (fontname, 0);
-  if (fontset >= 0)
-    font_name = XSTRING (fontset_ascii (fontset))->data;
+  if (fontset > 0)
+    font_name = SDATA (fontset_ascii (fontset));
+  else if (fontset == 0)
+    {
+      if (may_fail_p)
+       return 0;
+      abort ();
+    }
 
   /* Check if FONT_NAME is surely available on the system.  Usually
      FONT_NAME is already cached for the frame F and FS_LOAD_FONT
@@ -3127,7 +3295,7 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
      caching it now is not futail because we anyway load the font
      later.  */
   BLOCK_INPUT;
-  font_info = FS_LOAD_FONT (f, 0, font_name, -1);
+  font_info = FS_LOAD_FONT (f, font_name);
   UNBLOCK_INPUT;
 
   if (!font_info)
@@ -3189,8 +3357,18 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
     LFACE_SLANT (lface)
       = have_xlfd_p ? xlfd_symbolic_slant (&font) : Qnormal;
 
-  LFACE_FONT (lface) = fontname;
-
+  if (fontset > 0)
+    {
+      LFACE_FONT (lface) = build_string (font_info->full_name);
+      LFACE_FONTSET (lface) = fontset_name (fontset);
+    }
+  else
+    {
+      LFACE_FONT (lface) = fontname;
+      fontset
+       = new_fontset_from_font_name (build_string (font_info->full_name));
+      LFACE_FONTSET (lface) = fontset_name (fontset);
+    }
   return 1;
 }
 
@@ -3199,66 +3377,53 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
 
 /* Merges the face height FROM with the face height TO, and returns the
    merged height.  If FROM is an invalid height, then INVALID is
-   returned instead.  FROM may be a either an absolute face height or a
-   `relative' height, and TO must be an absolute height.  The returned
-   value is always an absolute height.  GCPRO is a lisp value that will
-   be protected from garbage-collection if this function makes a call
-   into lisp.  */
+   returned instead.  FROM and TO may be either absolute face heights or
+   `relative' heights; the returned value is always an absolute height
+   unless both FROM and TO are relative.  GCPRO is a lisp value that
+   will be protected from garbage-collection if this function makes a
+   call into lisp.  */
 
 Lisp_Object
 merge_face_heights (from, to, invalid, gcpro)
      Lisp_Object from, to, invalid, gcpro;
 {
-  int result = 0;
+  Lisp_Object result = invalid;
 
   if (INTEGERP (from))
-    result = XINT (from);
-  else if (NUMBERP (from))
-    result = XFLOATINT (from) * XINT (to);
-#if 0 /* Probably not so useful.  */
-  else if (CONSP (from) && CONSP (XCDR (from)))
-    {
-      if (EQ (XCAR(from), Qplus) || EQ (XCAR(from), Qminus))
-       {
-         if (INTEGERP (XCAR (XCDR (from))))
-           {
-             int inc = XINT (XCAR (XCDR (from)));
-             if (EQ (XCAR (from), Qminus))
-               inc = -inc;
-
-             result = XFASTINT (to);
-             if (result + inc > 0)
-               /* Note that `underflows' don't mean FROM is invalid, so
-                  we just pin the result at TO if it would otherwise be
-                  negative or 0.  */
-               result += inc;
-           }
-       }
+    /* FROM is absolute, just use it as is.  */
+    result = from;
+  else if (FLOATP (from))
+    /* FROM is a scale, use it to adjust TO.  */
+    {
+      if (INTEGERP (to))
+       /* relative X absolute => absolute */
+       result = make_number ((EMACS_INT)(XFLOAT_DATA (from) * XINT (to)));
+      else if (FLOATP (to))
+       /* relative X relative => relative */
+       result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to));
     }
-#endif
   else if (FUNCTIONP (from))
+    /* FROM is a function, which use to adjust TO.  */
     {
       /* Call function with current height as argument.
         From is the new height.  */
-      Lisp_Object args[2], height;
+      Lisp_Object args[2];
       struct gcpro gcpro1;
 
       GCPRO1 (gcpro);
 
       args[0] = from;
       args[1] = to;
-      height = safe_call (2, args);
+      result = safe_call (2, args);
 
       UNGCPRO;
 
-      if (NUMBERP (height))
-       result = XFLOATINT (height);
+      /* Ensure that if TO was absolute, so is the result.  */
+      if (INTEGERP (to) && !INTEGERP (result))
+       result = invalid;
     }
 
-  if (result > 0)
-    return make_number (result);
-  else
-    return invalid;
+  return result;
 }
 
 
@@ -3302,10 +3467,12 @@ merge_face_vectors (f, from, to, cycle_check)
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (!UNSPECIFIEDP (from[i]))
-      if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
-       to[i] = merge_face_heights (from[i], to[i], to[i], cycle_check);
-      else
-       to[i] = from[i];
+      {
+       if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
+         to[i] = merge_face_heights (from[i], to[i], to[i], cycle_check);
+       else
+         to[i] = from[i];
+      }
 
   /* TO is always an absolute face, which should inherit from nothing.
      We blindly copy the :inherit attribute above and fix it up here.  */
@@ -3320,7 +3487,7 @@ merge_face_vectors (f, from, to, cycle_check)
    elements, this macro begins consing in order to keep more precise
    track of elements.
 
-   Returns NIL if a cycle was detected, otherwise a new value for CHECK
+   Returns nil if a cycle was detected, otherwise a new value for CHECK
    that includes EL.
 
    CHECK is evaluated multiple times, EL and SUSPICIOUS 0 or 1 times, so
@@ -3436,7 +3603,7 @@ merge_face_vector_with_property (f, to, prop)
            add_to_log ("Invalid face color", color_name, Qnil);
        }
       else if (SYMBOLP (first)
-              && *XSYMBOL (first)->name->data == ':')
+              && *SDATA (SYMBOL_NAME (first)) == ':')
        {
          /* Assume this is the property list form.  */
          while (CONSP (prop) && CONSP (XCDR (prop)))
@@ -3606,24 +3773,24 @@ merge_face_vector_with_property (f, to, prop)
 
 DEFUN ("internal-make-lisp-face", Finternal_make_lisp_face,
        Sinternal_make_lisp_face, 1, 2, 0,
-  "Make FACE, a symbol, a Lisp face with all attributes nil.\n\
-If FACE was not known as a face before, create a new one.\n\
-If optional argument FRAME is specified, make a frame-local face\n\
-for that frame.  Otherwise operate on the global face definition.\n\
-Value is a vector of face attributes.")
-  (face, frame)
+       doc: /* Make FACE, a symbol, a Lisp face with all attributes nil.
+If FACE was not known as a face before, create a new one.
+If optional argument FRAME is specified, make a frame-local face
+for that frame.  Otherwise operate on the global face definition.
+Value is a vector of face attributes.  */)
+     (face, frame)
      Lisp_Object face, frame;
 {
   Lisp_Object global_lface, lface;
   struct frame *f;
   int i;
 
-  CHECK_SYMBOL (face, 0);
+  CHECK_SYMBOL (face);
   global_lface = lface_from_face_name (NULL, face, 0);
 
   if (!NILP (frame))
     {
-      CHECK_LIVE_FRAME (frame, 1);
+      CHECK_LIVE_FRAME (frame);
       f = XFRAME (frame);
       lface = lface_from_face_name (f, face, 0);
     }
@@ -3676,6 +3843,14 @@ Value is a vector of face attributes.")
   else
     lface = global_lface;
 
+  /* Changing a named face means that all realized faces depending on
+     that face are invalid.  Since we cannot tell which realized faces
+     depend on the face, make sure they are all removed.  This is done
+     by incrementing face_change_count.  The next call to
+     init_iterator will then free realized faces.  */
+  ++face_change_count;
+  ++windows_or_buffers_changed;
+
   xassert (LFACEP (lface));
   check_lface (lface);
   return lface;
@@ -3684,18 +3859,18 @@ Value is a vector of face attributes.")
 
 DEFUN ("internal-lisp-face-p", Finternal_lisp_face_p,
        Sinternal_lisp_face_p, 1, 2, 0,
-  "Return non-nil if FACE names a face.\n\
-If optional second parameter FRAME is non-nil, check for the\n\
-existence of a frame-local face with name FACE on that frame.\n\
-Otherwise check for the existence of a global face.")
-  (face, frame)
+       doc: /* Return non-nil if FACE names a face.
+If optional second parameter FRAME is non-nil, check for the
+existence of a frame-local face with name FACE on that frame.
+Otherwise check for the existence of a global face.  */)
+     (face, frame)
      Lisp_Object face, frame;
 {
   Lisp_Object lface;
 
   if (!NILP (frame))
     {
-      CHECK_LIVE_FRAME (frame, 1);
+      CHECK_LIVE_FRAME (frame);
       lface = lface_from_face_name (XFRAME (frame), face, 0);
     }
   else
@@ -3707,20 +3882,20 @@ Otherwise check for the existence of a global face.")
 
 DEFUN ("internal-copy-lisp-face", Finternal_copy_lisp_face,
        Sinternal_copy_lisp_face, 4, 4, 0,
-  "Copy face FROM to TO.\n\
-If FRAME it t, copy the global face definition of FROM to the\n\
-global face definition of TO.  Otherwise, copy the frame-local\n\
-definition of FROM on FRAME to the frame-local definition of TO\n\
-on NEW-FRAME, or FRAME if NEW-FRAME is nil.\n\
-\n\
-Value is TO.")
-  (from, to, frame, new_frame)
+       doc: /* Copy face FROM to TO.
+If FRAME it t, copy the global face definition of FROM to the
+global face definition of TO.  Otherwise, copy the frame-local
+definition of FROM on FRAME to the frame-local definition of TO
+on NEW-FRAME, or FRAME if NEW-FRAME is nil.
+
+Value is TO.  */)
+     (from, to, frame, new_frame)
      Lisp_Object from, to, frame, new_frame;
 {
   Lisp_Object lface, copy;
 
-  CHECK_SYMBOL (from, 0);
-  CHECK_SYMBOL (to, 1);
+  CHECK_SYMBOL (from);
+  CHECK_SYMBOL (to);
   if (NILP (new_frame))
     new_frame = frame;
 
@@ -3734,8 +3909,8 @@ Value is TO.")
   else
     {
       /* Copy frame-local definition of FROM.  */
-      CHECK_LIVE_FRAME (frame, 2);
-      CHECK_LIVE_FRAME (new_frame, 3);
+      CHECK_LIVE_FRAME (frame);
+      CHECK_LIVE_FRAME (new_frame);
       lface = lface_from_face_name (XFRAME (frame), from, 1);
       copy = Finternal_make_lisp_face (to, new_frame);
     }
@@ -3743,19 +3918,27 @@ Value is TO.")
   bcopy (XVECTOR (lface)->contents, XVECTOR (copy)->contents,
         LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
 
+  /* Changing a named face means that all realized faces depending on
+     that face are invalid.  Since we cannot tell which realized faces
+     depend on the face, make sure they are all removed.  This is done
+     by incrementing face_change_count.  The next call to
+     init_iterator will then free realized faces.  */
+  ++face_change_count;
+  ++windows_or_buffers_changed;
+
   return to;
 }
 
 
 DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
        Sinternal_set_lisp_face_attribute, 3, 4, 0,
-  "Set attribute ATTR of FACE to VALUE.\n\
-FRAME being a frame means change the face on that frame.\n\
-FRAME nil means change change the face of the selected frame.\n\
-FRAME t means change the default for new frames.\n\
-FRAME 0 means change the face on all frames, and change the default\n\
-  for new frames.")
-  (face, attr, value, frame)
+       doc: /* Set attribute ATTR of FACE to VALUE.
+FRAME being a frame means change the face on that frame.
+FRAME nil means change the face of the selected frame.
+FRAME t means change the default for new frames.
+FRAME 0 means change the face on all frames, and change the default
+  for new frames.  */)
+     (face, attr, value, frame)
      Lisp_Object face, attr, value, frame;
 {
   Lisp_Object lface;
@@ -3765,8 +3948,8 @@ FRAME 0 means change the face on all frames, and change the default\n\
   /* Set 1 if ATTR is one of font-related attributes other than QCfont.  */
   int font_related_attr_p = 0;
 
-  CHECK_SYMBOL (face, 0);
-  CHECK_SYMBOL (attr, 1);
+  CHECK_SYMBOL (face);
+  CHECK_SYMBOL (attr);
 
   face = resolve_face_name (face);
 
@@ -3789,7 +3972,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
       if (NILP (frame))
        frame = selected_frame;
 
-      CHECK_LIVE_FRAME (frame, 3);
+      CHECK_LIVE_FRAME (frame);
       lface = lface_from_face_name (XFRAME (frame), face, 0);
 
       /* If a frame-local face doesn't exist yet, create one.  */
@@ -3801,8 +3984,8 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_STRING (value, 3);
-         if (XSTRING (value)->size == 0)
+         CHECK_STRING (value);
+         if (SCHARS (value) == 0)
            signal_error ("Invalid face family", value);
        }
       old_value = LFACE_FAMILY (lface);
@@ -3813,13 +3996,16 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         Lisp_Object test =
-           (EQ (face, Qdefault) ? value :
-            /* The default face must have an absolute size, otherwise, we do
-               a test merge with a random height to see if VALUE's ok. */
-            merge_face_heights (value, make_number(10), Qnil, Qnil));
+         Lisp_Object test;
+
+         test = (EQ (face, Qdefault)
+                 ? value
+                 /* The default face must have an absolute size,
+                    otherwise, we do a test merge with a random
+                    height to see if VALUE's ok. */
+                 : merge_face_heights (value, make_number (10), Qnil, Qnil));
 
-         if (!INTEGERP(test) || XINT(test) <= 0)
+         if (!INTEGERP (test) || XINT (test) <= 0)
            signal_error ("Invalid face height", value);
        }
 
@@ -3831,7 +4017,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_SYMBOL (value, 3);
+         CHECK_SYMBOL (value);
          if (face_numeric_weight (value) < 0)
            signal_error ("Invalid face weight", value);
        }
@@ -3843,7 +4029,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_SYMBOL (value, 3);
+         CHECK_SYMBOL (value);
          if (face_numeric_slant (value) < 0)
            signal_error ("Invalid face slant", value);
        }
@@ -3859,7 +4045,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
             && !EQ (value, Qnil))
            /* Underline color.  */
            || (STRINGP (value)
-               && XSTRING (value)->size == 0))
+               && SCHARS (value) == 0))
          signal_error ("Invalid face underline", value);
 
       old_value = LFACE_UNDERLINE (lface);
@@ -3873,7 +4059,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
             && !EQ (value, Qnil))
            /* Overline color.  */
            || (STRINGP (value)
-               && XSTRING (value)->size == 0))
+               && SCHARS (value) == 0))
          signal_error ("Invalid face overline", value);
 
       old_value = LFACE_OVERLINE (lface);
@@ -3887,7 +4073,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
             && !EQ (value, Qnil))
            /* Strike-through color.  */
            || (STRINGP (value)
-               && XSTRING (value)->size == 0))
+               && SCHARS (value) == 0))
          signal_error ("Invalid face strike-through", value);
 
       old_value = LFACE_STRIKE_THROUGH (lface);
@@ -3909,7 +4095,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
       else if (INTEGERP (value))
        valid_p = XINT (value) != 0;
       else if (STRINGP (value))
-       valid_p = XSTRING (value)->size > 0;
+       valid_p = SCHARS (value) > 0;
       else if (CONSP (value))
        {
          Lisp_Object tem;
@@ -3933,7 +4119,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
                }
              else if (EQ (k, QCcolor))
                {
-                 if (!STRINGP (v) || XSTRING (v)->size == 0)
+                 if (!STRINGP (v) || SCHARS (v) == 0)
                    break;
                }
              else if (EQ (k, QCstyle))
@@ -3961,7 +4147,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_SYMBOL (value, 3);
+         CHECK_SYMBOL (value);
          if (!EQ (value, Qt) && !NILP (value))
            signal_error ("Invalid inverse-video face attribute value", value);
        }
@@ -3975,8 +4161,8 @@ FRAME 0 means change the face on all frames, and change the default\n\
          /* Don't check for valid color names here because it depends
             on the frame (display) whether the color will be valid
             when the face is realized.  */
-         CHECK_STRING (value, 3);
-         if (XSTRING (value)->size == 0)
+         CHECK_STRING (value);
+         if (SCHARS (value) == 0)
            signal_error ("Empty foreground color value", value);
        }
       old_value = LFACE_FOREGROUND (lface);
@@ -3989,8 +4175,8 @@ FRAME 0 means change the face on all frames, and change the default\n\
          /* Don't check for valid color names here because it depends
             on the frame (display) whether the color will be valid
             when the face is realized.  */
-         CHECK_STRING (value, 3);
-         if (XSTRING (value)->size == 0)
+         CHECK_STRING (value);
+         if (SCHARS (value) == 0)
            signal_error ("Empty background color value", value);
        }
       old_value = LFACE_BACKGROUND (lface);
@@ -4011,7 +4197,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
     {
       if (!UNSPECIFIEDP (value))
        {
-         CHECK_SYMBOL (value, 3);
+         CHECK_SYMBOL (value);
          if (face_numeric_swidth (value) < 0)
            signal_error ("Invalid face width", value);
        }
@@ -4019,30 +4205,44 @@ FRAME 0 means change the face on all frames, and change the default\n\
       LFACE_SWIDTH (lface) = value;
       font_related_attr_p = 1;
     }
-  else if (EQ (attr, QCfont))
+  else if (EQ (attr, QCfont) || EQ (attr, QCfontset))
     {
 #ifdef HAVE_WINDOW_SYSTEM
-      /* Set font-related attributes of the Lisp face from an
-        XLFD font name.  */
-      struct frame *f;
-      Lisp_Object tmp;
+      if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame)))
+       {
+         /* Set font-related attributes of the Lisp face from an XLFD
+            font name.  */
+         struct frame *f;
+         Lisp_Object tmp;
 
-      CHECK_STRING (value, 3);
-      if (EQ (frame, Qt))
-       f = SELECTED_FRAME ();
-      else
-       f = check_x_frame (frame);
+         if (EQ (frame, Qt))
+           f = SELECTED_FRAME ();
+         else
+           f = check_x_frame (frame);
 
-      /* VALUE may be a fontset name or an alias of fontset.  In such
-         a case, use the base fontset name.  */
-      tmp = Fquery_fontset (value, Qnil);
-      if (!NILP (tmp))
-       value = tmp;
+         if (!UNSPECIFIEDP (value))
+           {
+             CHECK_STRING (value);
 
-      if (!set_lface_from_font_name (f, lface, value, 1, 1))
-       signal_error ("Invalid font or fontset name", value);
+             /* VALUE may be a fontset name or an alias of fontset.  In
+                such a case, use the base fontset name.  */
+             tmp = Fquery_fontset (value, Qnil);
+             if (!NILP (tmp))
+               value = tmp;
+             else if (EQ (attr, QCfontset))
+               signal_error ("Invalid fontset name", value);
+
+             if (EQ (attr, QCfont))
+               {
+                 if (!set_lface_from_font_name (f, lface, value, 1, 1))
+                   signal_error ("Invalid font or fontset name", value);
+               }
+             else
+               LFACE_FONTSET (lface) = value;
+           }
 
-      font_attr_p = 1;
+         font_attr_p = 1;
+       }
 #endif /* HAVE_WINDOW_SYSTEM */
     }
   else if (EQ (attr, QCinherit))
@@ -4089,6 +4289,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
      init_iterator will then free realized faces.  */
   if (!EQ (frame, Qt)
       && (EQ (attr, QCfont)
+         || EQ (attr, QCfontset)
          || NILP (Fequal (old_value, value))))
     {
       ++face_change_count;
@@ -4107,7 +4308,8 @@ FRAME 0 means change the face on all frames, and change the default\n\
 #ifdef HAVE_WINDOW_SYSTEM
          /* Changed font-related attributes of the `default' face are
             reflected in changed `font' frame parameters. */
-         if ((font_related_attr_p || font_attr_p)
+         if (FRAMEP (frame)
+             && (font_related_attr_p || font_attr_p)
              && lface_fully_specified_p (XVECTOR (lface)->contents))
            set_font_frame_param (frame, lface);
          else
@@ -4153,23 +4355,39 @@ FRAME 0 means change the face on all frames, and change the default\n\
        }
 #endif /* HAVE_WINDOW_SYSTEM */
       else if (EQ (face, Qmenu))
-       ++menu_face_change_count;
+       {
+         /* Indicate that we have to update the menu bar when
+            realizing faces on FRAME.  FRAME t change the
+            default for new frames.  We do this by setting
+            setting the flag in new face caches   */
+         if (FRAMEP (frame))
+           {
+             struct frame *f = XFRAME (frame);
+             if (FRAME_FACE_CACHE (f) == NULL)
+               FRAME_FACE_CACHE (f) = make_face_cache (f);
+             FRAME_FACE_CACHE (f)->menu_face_changed_p = 1;
+           }
+         else
+           menu_face_changed_default = 1;
+       }
 
       if (!NILP (param))
-       if (EQ (frame, Qt))
-         /* Update `default-frame-alist', which is used for new frames.  */
-         {
-           store_in_alist (&Vdefault_frame_alist, param, value);
-         }
-       else
-         /* Update the current frame's parameters.  */
-         {
-           Lisp_Object cons;
-           cons = XCAR (Vparam_value_alist);
-           XCAR (cons) = param;
-           XCDR (cons) = value;
-           Fmodify_frame_parameters (frame, Vparam_value_alist);
-         }
+       {
+         if (EQ (frame, Qt))
+           /* Update `default-frame-alist', which is used for new frames.  */
+           {
+             store_in_alist (&Vdefault_frame_alist, param, value);
+           }
+         else
+           /* Update the current frame's parameters.  */
+           {
+             Lisp_Object cons;
+             cons = XCAR (Vparam_value_alist);
+             XSETCAR (cons, param);
+             XSETCDR (cons, value);
+             Fmodify_frame_parameters (frame, Vparam_value_alist);
+           }
+       }
     }
 
   return face;
@@ -4179,7 +4397,7 @@ FRAME 0 means change the face on all frames, and change the default\n\
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Set the `font' frame parameter of FRAME determined from `default'
-   face attributes LFACE.  If a face or fontset name is explicitely
+   face attributes LFACE.  If a font name is explicitely
    specfied in LFACE, use it as is.  Otherwise, determine a font name
    from the other font-related atrributes of LFACE.  In that case, if
    there's no matching font, signals an error.  */
@@ -4194,7 +4412,7 @@ set_font_frame_param (frame, lface)
     {
       Lisp_Object font_name;
       char *font;
-      
+
       if (STRINGP (LFACE_FONT (lface)))
        font_name = LFACE_FONT (lface);
       else
@@ -4202,13 +4420,14 @@ set_font_frame_param (frame, lface)
          /* Choose a font name that reflects LFACE's attributes and has
             the registry and encoding pattern specified in the default
             fontset (3rd arg: -1) for ASCII characters (4th arg: 0).  */
-         font = choose_face_font (f, XVECTOR (lface)->contents, -1, 0);
+         font = choose_face_font (f, XVECTOR (lface)->contents, Qnil, NULL);
          if (!font)
            error ("No font matches the specified attribute");
          font_name = build_string (font);
          xfree (font);
        }
-  
+
+      f->default_face_done_p = 0;
       Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font_name), Qnil));
     }
 }
@@ -4230,6 +4449,14 @@ update_face_from_frame_parameter (f, param, new_value)
   if (NILP (f->face_alist))
     return;
 
+  /* Changing a named face means that all realized faces depending on
+     that face are invalid.  Since we cannot tell which realized faces
+     depend on the face, make sure they are all removed.  This is done
+     by incrementing face_change_count.  The next call to
+     init_iterator will then free realized faces.  */
+  ++face_change_count;
+  ++windows_or_buffers_changed;
+
   if (EQ (param, Qforeground_color))
     {
       lface = lface_from_face_name (f, Qdefault, 1);
@@ -4278,22 +4505,18 @@ update_face_from_frame_parameter (f, param, new_value)
    doesn't take a frame argument.  */
 
 DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
-       Sinternal_face_x_get_resource, 3, 3, 0, "")
-  (resource, class, frame)
+       Sinternal_face_x_get_resource, 3, 3, 0, doc: /* */)
+     (resource, class, frame)
      Lisp_Object resource, class, frame;
 {
   Lisp_Object value = Qnil;
-#ifndef WINDOWSNT
-#ifndef macintosh
-  CHECK_STRING (resource, 0);
-  CHECK_STRING (class, 1);
-  CHECK_LIVE_FRAME (frame, 2);
+  CHECK_STRING (resource);
+  CHECK_STRING (class);
+  CHECK_LIVE_FRAME (frame);
   BLOCK_INPUT;
   value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
                                  resource, class, Qnil, Qnil);
   UNBLOCK_INPUT;
-#endif /* not macintosh */
-#endif /* not WINDOWSNT */
   return value;
 }
 
@@ -4312,13 +4535,13 @@ face_boolean_x_resource_value (value, signal_p)
 
   xassert (STRINGP (value));
 
-  if (xstricmp (XSTRING (value)->data, "on") == 0
-      || xstricmp (XSTRING (value)->data, "true") == 0)
+  if (xstricmp (SDATA (value), "on") == 0
+      || xstricmp (SDATA (value), "true") == 0)
     result = Qt;
-  else if (xstricmp (XSTRING (value)->data, "off") == 0
-          || xstricmp (XSTRING (value)->data, "false") == 0)
+  else if (xstricmp (SDATA (value), "off") == 0
+          || xstricmp (SDATA (value), "false") == 0)
     result = Qnil;
-  else if (xstricmp (XSTRING (value)->data, "unspecified") == 0)
+  else if (xstricmp (SDATA (value), "unspecified") == 0)
     result = Qunspecified;
   else if (signal_p)
     signal_error ("Invalid face attribute value from X resource", value);
@@ -4330,15 +4553,15 @@ face_boolean_x_resource_value (value, signal_p)
 DEFUN ("internal-set-lisp-face-attribute-from-resource",
        Finternal_set_lisp_face_attribute_from_resource,
        Sinternal_set_lisp_face_attribute_from_resource,
-       3, 4, 0, "")
-  (face, attr, value, frame)
+       3, 4, 0, doc: /* */)
+     (face, attr, value, frame)
      Lisp_Object face, attr, value, frame;
 {
-  CHECK_SYMBOL (face, 0);
-  CHECK_SYMBOL (attr, 1);
-  CHECK_STRING (value, 2);
+  CHECK_SYMBOL (face);
+  CHECK_SYMBOL (attr);
+  CHECK_STRING (value);
 
-  if (xstricmp (XSTRING (value)->data, "unspecified") == 0)
+  if (xstricmp (SDATA (value), "unspecified") == 0)
     value = Qunspecified;
   else if (EQ (attr, QCheight))
     {
@@ -4349,13 +4572,12 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
   else if (EQ (attr, QCbold) || EQ (attr, QCitalic))
     value = face_boolean_x_resource_value (value, 1);
   else if (EQ (attr, QCweight) || EQ (attr, QCslant) || EQ (attr, QCwidth))
-    value = intern (XSTRING (value)->data);
+    value = intern (SDATA (value));
   else if (EQ (attr, QCreverse_video) || EQ (attr, QCinverse_video))
     value = face_boolean_x_resource_value (value, 1);
   else if (EQ (attr, QCunderline)
           || EQ (attr, QCoverline)
-          || EQ (attr, QCstrike_through)
-          || EQ (attr, QCbox))
+          || EQ (attr, QCstrike_through))
     {
       Lisp_Object boolean_value;
 
@@ -4365,6 +4587,8 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
       if (SYMBOLP (boolean_value))
        value = boolean_value;
     }
+  else if (EQ (attr, QCbox))
+    value = Fcar (Fread_from_string (value, Qnil, Qnil));
 
   return Finternal_set_lisp_face_attribute (face, attr, value, frame);
 }
@@ -4394,22 +4618,22 @@ x_update_menu_appearance (f)
       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;
+      const char *myname = SDATA (Vx_resource_name);
       int changed_p = 0;
 #ifdef USE_MOTIF
       const char *popup_path = "popup_menu";
 #else
       const char *popup_path = "menu.popup";
 #endif
-      
+
       if (STRINGP (LFACE_FOREGROUND (lface)))
        {
          sprintf (line, "%s.%s*foreground: %s",
                   myname, popup_path,
-                  XSTRING (LFACE_FOREGROUND (lface))->data);
+                  SDATA (LFACE_FOREGROUND (lface)));
          XrmPutLineResource (&rdb, line);
          sprintf (line, "%s.pane.menubar*foreground: %s",
-                  myname, XSTRING (LFACE_FOREGROUND (lface))->data);
+                  myname, SDATA (LFACE_FOREGROUND (lface)));
          XrmPutLineResource (&rdb, line);
          changed_p = 1;
        }
@@ -4418,14 +4642,14 @@ x_update_menu_appearance (f)
        {
          sprintf (line, "%s.%s*background: %s",
                   myname, popup_path,
-                  XSTRING (LFACE_BACKGROUND (lface))->data);
+                  SDATA (LFACE_BACKGROUND (lface)));
          XrmPutLineResource (&rdb, line);
          sprintf (line, "%s.pane.menubar*background: %s",
-                  myname, XSTRING (LFACE_BACKGROUND (lface))->data);
+                  myname, SDATA (LFACE_BACKGROUND (lface)));
          XrmPutLineResource (&rdb, line);
          changed_p = 1;
        }
-         
+
       if (face->font_name
          && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
              || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
@@ -4449,33 +4673,61 @@ x_update_menu_appearance (f)
        }
 
       if (changed_p && f->output_data.x->menubar_widget)
-       {
-         free_frame_menubar (f);
-         set_frame_menubar (f, 1, 1);
-       }
+       free_frame_menubar (f);
     }
 }
 
 #endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
 
 
+DEFUN ("face-attribute-relative-p", Fface_attribute_relative_p,
+       Sface_attribute_relative_p,
+       2, 2, 0,
+       doc: /* Return non-nil if face ATTRIBUTE VALUE is relative.  */)
+     (attribute, value)
+     Lisp_Object attribute, value;
+{
+  if (EQ (value, Qunspecified))
+    return Qt;
+  else if (EQ (attribute, QCheight))
+    return INTEGERP (value) ? Qnil : Qt;
+  else
+    return Qnil;
+}
+
+DEFUN ("merge-face-attribute", Fmerge_face_attribute, Smerge_face_attribute,
+       3, 3, 0,
+       doc: /* Return face ATTRIBUTE VALUE1 merged with VALUE2.
+If VALUE1 or VALUE2 are absolute (see `face-attribute-relative-p'), then
+the result will be absolute, otherwise it will be relative.  */)
+     (attribute, value1, value2)
+     Lisp_Object attribute, value1, value2;
+{
+  if (EQ (value1, Qunspecified))
+    return value2;
+  else if (EQ (attribute, QCheight))
+    return merge_face_heights (value1, value2, value1, Qnil);
+  else
+    return value1;
+}
+
 
 DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute,
        Sinternal_get_lisp_face_attribute,
        2, 3, 0,
-  "Return face attribute KEYWORD of face SYMBOL.\n\
-If SYMBOL does not name a valid Lisp face or KEYWORD isn't a valid\n\
-face attribute name, signal an error.\n\
-If the optional argument FRAME is given, report on face FACE in that\n\
-frame.  If FRAME is t, report on the defaults for face FACE (for new\n\
-frames).  If FRAME is omitted or nil, use the selected frame.")
-  (symbol, keyword, frame)
+       doc: /* Return face attribute KEYWORD of face SYMBOL.
+If SYMBOL does not name a valid Lisp face or KEYWORD isn't a valid
+face attribute name, signal an error.
+If the optional argument FRAME is given, report on face FACE in that
+frame.  If FRAME is t, report on the defaults for face FACE (for new
+frames).  If FRAME is omitted or nil, use the selected frame.  */)
+     (symbol, keyword, frame)
      Lisp_Object symbol, keyword, frame;
 {
   Lisp_Object lface, value = Qnil;
 
-  CHECK_SYMBOL (symbol, 0);
-  CHECK_SYMBOL (keyword, 1);
+  CHECK_SYMBOL (symbol);
+  CHECK_SYMBOL (keyword);
 
   if (EQ (frame, Qt))
     lface = lface_from_face_name (NULL, symbol, 1);
@@ -4483,7 +4735,7 @@ frames).  If FRAME is omitted or nil, use the selected frame.")
     {
       if (NILP (frame))
        frame = selected_frame;
-      CHECK_LIVE_FRAME (frame, 2);
+      CHECK_LIVE_FRAME (frame);
       lface = lface_from_face_name (XFRAME (frame), symbol, 1);
     }
 
@@ -4518,6 +4770,8 @@ frames).  If FRAME is omitted or nil, use the selected frame.")
     value = LFACE_INHERIT (lface);
   else if (EQ (keyword, QCfont))
     value = LFACE_FONT (lface);
+  else if (EQ (keyword, QCfontset))
+    value = LFACE_FONTSET (lface);
   else
     signal_error ("Invalid face attribute name", keyword);
 
@@ -4528,14 +4782,14 @@ frames).  If FRAME is omitted or nil, use the selected frame.")
 DEFUN ("internal-lisp-face-attribute-values",
        Finternal_lisp_face_attribute_values,
        Sinternal_lisp_face_attribute_values, 1, 1, 0,
-  "Return a list of valid discrete values for face attribute ATTR.\n\
-Value is nil if ATTR doesn't have a discrete set of valid values.")
-  (attr)
+       doc: /* Return a list of valid discrete values for face attribute ATTR.
+Value is nil if ATTR doesn't have a discrete set of valid values.  */)
+     (attr)
      Lisp_Object attr;
 {
   Lisp_Object result = Qnil;
 
-  CHECK_SYMBOL (attr, 0);
+  CHECK_SYMBOL (attr);
 
   if (EQ (attr, QCweight)
       || EQ (attr, QCslant)
@@ -4580,15 +4834,15 @@ Value is nil if ATTR doesn't have a discrete set of valid values.")
 
 DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
        Sinternal_merge_in_global_face, 2, 2, 0,
-  "Add attributes from frame-default definition of FACE to FACE on FRAME.\n\
-Default face attributes override any local face attributes.")
-  (face, frame)
+       doc: /* Add attributes from frame-default definition of FACE to FACE on FRAME.
+Default face attributes override any local face attributes.  */)
+     (face, frame)
      Lisp_Object face, frame;
 {
   int i;
   Lisp_Object global_lface, local_lface, *gvec, *lvec;
 
-  CHECK_LIVE_FRAME (frame, 1);
+  CHECK_LIVE_FRAME (frame);
   global_lface = lface_from_face_name (NULL, face, 1);
   local_lface = lface_from_face_name (XFRAME (frame), face, 0);
   if (NILP (local_lface))
@@ -4614,15 +4868,18 @@ Default face attributes override any local face attributes.")
    return fonts with the same size as the font of a face.  This is
    done in fontset.el.  */
 
-DEFUN ("face-font", Fface_font, Sface_font, 1, 2, 0,
-  "Return the font name of face FACE, or nil if it is unspecified.\n\
-If the optional argument FRAME is given, report on face FACE in that frame.\n\
-If FRAME is t, report on the defaults for face FACE (for new frames).\n\
-  The font default for a face is either nil, or a list\n\
-  of the form (bold), (italic) or (bold italic).\n\
-If FRAME is omitted or nil, use the selected frame.")
-  (face, frame)
-     Lisp_Object face, frame;
+DEFUN ("face-font", Fface_font, Sface_font, 1, 3, 0,
+       doc: /* Return the font name of face FACE, or nil if it is unspecified.
+The font name is, by default, for ASCII characters.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+  The font default for a face is either nil, or a list
+  of the form (bold), (italic) or (bold italic).
+If FRAME is omitted or nil, use the selected frame.  And, in this case,
+if the optional third argument CHARACTER is given,
+return the font name used for CHARACTER.  */)
+     (face, frame, character)
+     Lisp_Object face, frame, character;
 {
   if (EQ (frame, Qt))
     {
@@ -4633,7 +4890,7 @@ If FRAME is omitted or nil, use the selected frame.")
          && !EQ (LFACE_WEIGHT (lface), Qnormal))
        result = Fcons (Qbold, result);
 
-      if (!NILP (LFACE_SLANT (lface))
+      if (!UNSPECIFIEDP (LFACE_SLANT (lface))
          && !EQ (LFACE_SLANT (lface), Qnormal))
        result = Fcons (Qitalic, result);
 
@@ -4642,9 +4899,19 @@ If FRAME is omitted or nil, use the selected frame.")
   else
     {
       struct frame *f = frame_or_selected_frame (frame, 1);
-      int face_id = lookup_named_face (f, face, 0);
+      int face_id = lookup_named_face (f, face);
       struct face *face = FACE_FROM_ID (f, face_id);
-      return face ? build_string (face->font_name) : Qnil;
+
+      if (! face)
+       return Qnil;
+      if (NILP (character))
+       return build_string (face->font_name);
+      CHECK_CHARACTER (character);
+      face_id = FACE_FOR_CHAR (f, face, XINT (character), -1, Qnil);
+      face = FACE_FROM_ID (f, face_id);
+      return (face->font && face->font_name
+             ? build_string (face->font_name)
+             : Qnil);
     }
 }
 
@@ -4675,10 +4942,10 @@ lface_equal_p (v1, v2)
          switch (XTYPE (a))
            {
            case Lisp_String:
-             equal_p = ((STRING_BYTES (XSTRING (a))
-                         == STRING_BYTES (XSTRING (b)))
-                        && bcmp (XSTRING (a)->data, XSTRING (b)->data,
-                                 STRING_BYTES (XSTRING (a))) == 0);
+             equal_p = ((SBYTES (a)
+                         == SBYTES (b))
+                        && bcmp (SDATA (a), SDATA (b),
+                                 SBYTES (a)) == 0);
              break;
 
            case Lisp_Int:
@@ -4699,26 +4966,16 @@ lface_equal_p (v1, v2)
 
 DEFUN ("internal-lisp-face-equal-p", Finternal_lisp_face_equal_p,
        Sinternal_lisp_face_equal_p, 2, 3, 0,
-  "True if FACE1 and FACE2 are equal.\n\
-If the optional argument FRAME is given, report on face FACE in that frame.\n\
-If FRAME is t, report on the defaults for face FACE (for new frames).\n\
-If FRAME is omitted or nil, use the selected frame.")
-  (face1, face2, frame)
+       doc: /* True if FACE1 and FACE2 are equal.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.  */)
+     (face1, face2, frame)
      Lisp_Object face1, face2, frame;
 {
   int equal_p;
-  struct frame *f;
   Lisp_Object lface1, lface2;
 
-  if (EQ (frame, Qt))
-    f = NULL;
-  else
-    /* Don't use check_x_frame here because this function is called
-       before X frames exist.  At that time, if FRAME is nil,
-       selected_frame will be used which is the frame dumped with
-       Emacs.  That frame is not an X frame.  */
-    f = frame_or_selected_frame (frame, 2);
-
   lface1 = lface_from_face_name (NULL, face1, 1);
   lface2 = lface_from_face_name (NULL, face2, 1);
   equal_p = lface_equal_p (XVECTOR (lface1)->contents,
@@ -4729,11 +4986,11 @@ If FRAME is omitted or nil, use the selected frame.")
 
 DEFUN ("internal-lisp-face-empty-p", Finternal_lisp_face_empty_p,
        Sinternal_lisp_face_empty_p, 1, 2, 0,
-  "True if FACE has no attribute specified.\n\
-If the optional argument FRAME is given, report on face FACE in that frame.\n\
-If FRAME is t, report on the defaults for face FACE (for new frames).\n\
-If FRAME is omitted or nil, use the selected frame.")
-  (face, frame)
+       doc: /* True if FACE has no attribute specified.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.  */)
+     (face, frame)
      Lisp_Object face, frame;
 {
   struct frame *f;
@@ -4742,7 +4999,7 @@ If FRAME is omitted or nil, use the selected frame.")
 
   if (NILP (frame))
     frame = selected_frame;
-  CHECK_LIVE_FRAME (frame, 0);
+  CHECK_LIVE_FRAME (frame);
   f = XFRAME (frame);
 
   if (EQ (frame, Qt))
@@ -4760,9 +5017,9 @@ If FRAME is omitted or nil, use the selected frame.")
 
 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist,
        0, 1, 0,
-  "Return an alist of frame-local faces defined on FRAME.\n\
-For internal use only.")
-  (frame)
+       doc: /* Return an alist of frame-local faces defined on FRAME.
+For internal use only.  */)
+     (frame)
      Lisp_Object frame;
 {
   struct frame *f = frame_or_selected_frame (frame, 0);
@@ -4777,10 +5034,10 @@ static INLINE unsigned
 hash_string_case_insensitive (string)
      Lisp_Object string;
 {
-  unsigned char *s;
+  const unsigned char *s;
   unsigned hash = 0;
   xassert (STRINGP (string));
-  for (s = XSTRING (string)->data; *s; ++s)
+  for (s = SDATA (string); *s; ++s)
     hash = (hash << 1) ^ tolower (*s);
   return hash;
 }
@@ -4804,8 +5061,8 @@ lface_hash (v)
 
 /* Return non-zero if LFACE1 and LFACE2 specify the same font (without
    considering charsets/registries).  They do if they specify the same
-   family, point size, weight, width, slant, and fontset.  Both LFACE1
-   and LFACE2 must be fully-specified.  */
+   family, point size, weight, width, slant, font, and fontset.  Both
+   LFACE1 and LFACE2 must be fully-specified.  */
 
 static INLINE int
 lface_same_font_attributes_p (lface1, lface2)
@@ -4813,8 +5070,8 @@ lface_same_font_attributes_p (lface1, lface2)
 {
   xassert (lface_fully_specified_p (lface1)
           && lface_fully_specified_p (lface2));
-  return (xstricmp (XSTRING (lface1[LFACE_FAMILY_INDEX])->data,
-                   XSTRING (lface2[LFACE_FAMILY_INDEX])->data) == 0
+  return (xstricmp (SDATA (lface1[LFACE_FAMILY_INDEX]),
+                   SDATA (lface2[LFACE_FAMILY_INDEX])) == 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])
@@ -4823,8 +5080,14 @@ lface_same_font_attributes_p (lface1, lface2)
          && (EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
              || (STRINGP (lface1[LFACE_FONT_INDEX])
                  && STRINGP (lface2[LFACE_FONT_INDEX])
-                 && xstricmp (XSTRING (lface1[LFACE_FONT_INDEX])->data,
-                              XSTRING (lface2[LFACE_FONT_INDEX])->data))));
+                 && ! xstricmp (SDATA (lface1[LFACE_FONT_INDEX]),
+                                SDATA (lface2[LFACE_FONT_INDEX]))))
+         && (EQ (lface1[LFACE_FONTSET_INDEX], lface2[LFACE_FONTSET_INDEX])
+             || (STRINGP (lface1[LFACE_FONTSET_INDEX])
+                 && STRINGP (lface2[LFACE_FONTSET_INDEX])
+                 && ! xstricmp (SDATA (lface1[LFACE_FONTSET_INDEX]),
+                                SDATA (lface2[LFACE_FONTSET_INDEX]))))
+         );
 }
 
 
@@ -4851,7 +5114,7 @@ make_realized_face (attr)
 /* Free realized face FACE, including its X resources.  FACE may
    be null.  */
 
-static void
+void
 free_realized_face (f, face)
      struct frame *f;
      struct face *face;
@@ -4911,7 +5174,7 @@ prepare_face_for_display (f, face)
 #ifdef WINDOWSNT
          xgcv.font = face->font;
 #endif
-#ifdef macintosh
+#ifdef MAC_OS
          xgcv.font = face->font;
 #endif
          mask |= GCFont;
@@ -4933,6 +5196,249 @@ prepare_face_for_display (f, face)
 }
 
 \f
+/* Returns the `distance' between the colors X and Y.  */
+
+static int
+color_distance (x, y)
+     XColor *x, *y;
+{
+  /* This formula is from a paper title `Colour metric' by Thiadmer Riemersma.
+     Quoting from that paper:
+
+         This formula has results that are very close to L*u*v* (with the
+         modified lightness curve) and, more importantly, it is a more even
+         algorithm: it does not have a range of colours where it suddenly
+         gives far from optimal results.
+
+     See <http://www.compuphase.com/cmetric.htm> for more info.  */
+
+  long r = (x->red   - y->red)   >> 8;
+  long g = (x->green - y->green) >> 8;
+  long b = (x->blue  - y->blue)  >> 8;
+  long r_mean = (x->red + y->red) >> 9;
+
+  return
+    (((512 + r_mean) * r * r) >> 8)
+    + 4 * g * g
+    + (((767 - r_mean) * b * b) >> 8);
+}
+
+
+DEFUN ("color-distance", Fcolor_distance, Scolor_distance, 2, 3, 0,
+       doc: /* Return an integer distance between COLOR1 and COLOR2 on FRAME.
+COLOR1 and COLOR2 may be either strings containing the color name,
+or lists of the form (RED GREEN BLUE).
+If FRAME is unspecified or nil, the current frame is used.  */)
+     (color1, color2, frame)
+     Lisp_Object color1, color2, frame;
+{
+  struct frame *f;
+  XColor cdef1, cdef2;
+
+  if (NILP (frame))
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame);
+  f = XFRAME (frame);
+
+  if ((CONSP (color1) && !parse_rgb_list (color1, &cdef1))
+      || !STRINGP (color1)
+      || !defined_color (f, SDATA (color1), &cdef1, 0))
+    signal_error ("Invalid color", color1);
+  if ((CONSP (color2) && !parse_rgb_list (color2, &cdef2))
+      || !STRINGP (color2)
+      || !defined_color (f, SDATA (color2), &cdef2, 0))
+    signal_error ("Invalid color", color2);
+
+  return make_number (color_distance (&cdef1, &cdef2));
+}
+
+\f
+/***********************************************************************
+                   Face capability testing for ttys
+ ***********************************************************************/
+
+
+/* If the distance (as returned by color_distance) between two colors is
+   less than this, then they are considered the same, for determining
+   whether a color is supported or not.  The range of values is 0-65535.  */
+
+#define TTY_SAME_COLOR_THRESHOLD  10000
+
+
+DEFUN ("tty-supports-face-attributes-p",
+       Ftty_supports_face_attributes_p, Stty_supports_face_attributes_p,
+       1, 2, 0,
+       doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported.
+The optional argument FRAME is the frame on which to test; if it is nil
+or unspecified, then the current frame is used.  If FRAME is not a tty
+frame, then nil is returned.
+
+The definition of `supported' is somewhat heuristic, but basically means
+that a face containing all the attributes in ATTRIBUTES, when merged
+with the default face for display, can be represented in a way that's
+
+ \(1) different in appearance than the default face, and
+ \(2) `close in spirit' to what the attributes specify, if not exact.
+
+Point (2) implies that a `:weight black' attribute will be satisified
+by any terminal that can display bold, and a `:foreground "yellow"' as
+long as the terminal can display a yellowish color, but `:slant italic'
+will _not_ be satisified by the tty display code's automatic
+substitution of a `dim' face for italic.  */)
+     (attributes, frame)
+     Lisp_Object attributes, frame;
+{
+  int weight, i;
+  struct frame *f;
+  Lisp_Object val, fg, bg;
+  XColor fg_tty_color, fg_std_color;
+  XColor bg_tty_color, bg_std_color;
+  Lisp_Object attrs[LFACE_VECTOR_SIZE];
+  unsigned test_caps = 0;
+
+  if (NILP (frame))
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame);
+  f = XFRAME (frame);
+
+  for (i = 0; i < LFACE_VECTOR_SIZE; i++)
+    attrs[i] = Qunspecified;
+  merge_face_vector_with_property (f, attrs, attributes);
+
+  /* This function only works on ttys.  */
+  if (!FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
+    return Qnil;
+
+  /* First check some easy-to-check stuff; ttys support none of the
+     following attributes, so we can just return nil if any are requested.  */
+
+  /* stipple */
+  val = attrs[LFACE_STIPPLE_INDEX];
+  if (!UNSPECIFIEDP (val) && !NILP (val))
+    return Qnil;
+
+  /* font height */
+  val = attrs[LFACE_HEIGHT_INDEX];
+  if (!UNSPECIFIEDP (val) && !NILP (val))
+    return Qnil;
+
+  /* font width */
+  val = attrs[LFACE_SWIDTH_INDEX];
+  if (!UNSPECIFIEDP (val) && !NILP (val)
+      && face_numeric_swidth (val) != XLFD_SWIDTH_MEDIUM)
+    return Qnil;
+
+  /* overline */
+  val = attrs[LFACE_OVERLINE_INDEX];
+  if (!UNSPECIFIEDP (val) && !NILP (val))
+    return Qnil;
+
+  /* strike-through */
+  val = attrs[LFACE_STRIKE_THROUGH_INDEX];
+  if (!UNSPECIFIEDP (val) && !NILP (val))
+    return Qnil;
+
+  /* boxes */
+  val = attrs[LFACE_BOX_INDEX];
+  if (!UNSPECIFIEDP (val) && !NILP (val))
+    return Qnil;
+
+  /* slant (italics/oblique); We consider any non-default value
+     unsupportable on ttys, even though the face code actually `fakes'
+     them using a dim attribute if possible.  This is because the faked
+     result is too different from what the face specifies.  */
+  val = attrs[LFACE_SLANT_INDEX];
+  if (!UNSPECIFIEDP (val) && !NILP (val)
+      && face_numeric_slant (val) != XLFD_SLANT_ROMAN)
+    return Qnil;
+
+
+  /* Test for terminal `capabilities' (non-color character attributes).  */
+
+  /* font weight (bold/dim) */
+  weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
+  if (weight >= 0)
+    {
+      if (weight > XLFD_WEIGHT_MEDIUM)
+       test_caps = TTY_CAP_BOLD;
+      else if (weight < XLFD_WEIGHT_MEDIUM)
+       test_caps = TTY_CAP_DIM;
+    }
+
+  /* underlining */
+  val = attrs[LFACE_UNDERLINE_INDEX];
+  if (!UNSPECIFIEDP (val) && !NILP (val))
+    {
+      if (STRINGP (val))
+       return Qnil;            /* ttys don't support colored underlines */
+      else
+       test_caps |= TTY_CAP_UNDERLINE;
+    }
+
+  /* inverse video */
+  val = attrs[LFACE_INVERSE_INDEX];
+  if (!UNSPECIFIEDP (val) && !NILP (val))
+    test_caps |= TTY_CAP_INVERSE;
+
+
+  /* Color testing.  */
+
+  /* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since
+     we use them when calling `tty_capable_p' below, even if the face
+     specifies no colors.  */
+  fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR;
+  bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR;
+
+  /* Check if foreground color is close enough.  */
+  fg = attrs[LFACE_FOREGROUND_INDEX];
+  if (STRINGP (fg))
+    {
+      if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
+       return Qnil;
+      else if (color_distance (&fg_tty_color, &fg_std_color)
+              > TTY_SAME_COLOR_THRESHOLD)
+       return Qnil;
+    }
+
+  /* Check if background color is close enough.  */
+  bg = attrs[LFACE_BACKGROUND_INDEX];
+  if (STRINGP (bg))
+    {
+      if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
+       return Qnil;
+      else if (color_distance (&bg_tty_color, &bg_std_color)
+              > TTY_SAME_COLOR_THRESHOLD)
+       return Qnil;
+    }
+
+  /* If both foreground and background are requested, see if the
+     distance between them is OK.  We just check to see if the distance
+     between the tty's foreground and background is close enough to the
+     distance between the standard foreground and background.  */
+  if (STRINGP (fg) && STRINGP (bg))
+    {
+      int delta_delta
+       = (color_distance (&fg_std_color, &bg_std_color)
+          - color_distance (&fg_tty_color, &bg_tty_color));
+      if (delta_delta > TTY_SAME_COLOR_THRESHOLD
+         || delta_delta < -TTY_SAME_COLOR_THRESHOLD)
+       return Qnil;
+    }
+
+
+  /* See if the capabilities we selected above are supported, with the
+     given colors.  */
+  if (test_caps != 0 &&
+      ! tty_capable_p (f, test_caps, fg_tty_color.pixel, bg_tty_color.pixel))
+    return Qnil;
+
+
+  /* Hmmm, everything checks out, this terminal must support this face.  */
+  return Qt;
+}
+
+
+\f
 /***********************************************************************
                              Face Cache
  ***********************************************************************/
@@ -4954,6 +5460,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;
 }
 
@@ -5028,11 +5535,10 @@ free_realized_faces (c)
 }
 
 
-/* Free all faces realized for multibyte characters on frame F that
-   has FONTSET.  */
+/* Free all realized faces that are using FONTSET on frame F.  */
 
 void
-free_realized_multibyte_face (f, fontset)
+free_realized_faces_for_fontset (f, fontset)
      struct frame *f;
      int fontset;
 {
@@ -5049,7 +5555,6 @@ free_realized_multibyte_face (f, fontset)
     {
       face = cache->faces_by_id[i];
       if (face
-         && face != face->ascii_face
          && face->fontset == fontset)
        {
          uncache_face (cache, face);
@@ -5107,10 +5612,11 @@ free_face_cache (c)
 
 
 /* Cache realized face FACE in face cache C.  HASH is the hash value
-   of FACE.  If FACE->fontset >= 0, add the new face to the end of the
-   collision list of the face hash table of C.  This is done because
-   otherwise lookup_face would find FACE for every character, even if
-   faces with the same attributes but for specific characters exist.  */
+   of FACE.  If FACE is for ASCII characters (i.e. FACE->ascii_face ==
+   FACE), insert the new face to the beginning of the collision list
+   of the face hash table of C.  Otherwise, add the new face to the
+   end of the collision list.  This way, lookup_face can quickly find
+   that a requested face is not cached.  */
 
 static void
 cache_face (c, face, hash)
@@ -5122,7 +5628,7 @@ cache_face (c, face, hash)
 
   face->hash = hash;
 
-  if (face->fontset >= 0)
+  if (face->ascii_face != face)
     {
       struct face *last = c->buckets[i];
       if (last)
@@ -5209,17 +5715,14 @@ uncache_face (c, face)
 
 
 /* Look up a realized face with face attributes ATTR in the face cache
-   of frame F.  The face will be used to display character C.  Value
-   is the ID of the face found.  If no suitable face is found, realize
-   a new one.  In that case, if C is a multibyte character, BASE_FACE
-   is a face that has the same attributes.  */
+   of frame F.  The face will be used to display ASCII characters.
+   Value is the ID of the face found.  If no suitable face is found,
+   realize a new one.  */
 
 INLINE int
-lookup_face (f, attr, c, base_face)
+lookup_face (f, attr)
      struct frame *f;
      Lisp_Object *attr;
-     int c;
-     struct face *base_face;
 {
   struct face_cache *cache = FRAME_FACE_CACHE (f);
   unsigned hash;
@@ -5234,44 +5737,82 @@ lookup_face (f, attr, c, base_face)
   i = hash % FACE_CACHE_BUCKETS_SIZE;
 
   for (face = cache->buckets[i]; face; face = face->next)
-    if (face->hash == hash
-       && (!FRAME_WINDOW_P (f)
-           || FACE_SUITABLE_FOR_CHAR_P (face, c))
-       && lface_equal_p (face->lface, attr))
-      break;
+    {
+      if (face->ascii_face != face)
+       {
+         /* There's no more ASCII face.  */
+         face = NULL;
+         break;
+       }
+      if (face->hash == hash
+         && lface_equal_p (face->lface, attr))
+       break;
+    }
 
   /* If not found, realize a new face.  */
   if (face == NULL)
-    face = realize_face (cache, attr, c, base_face, -1);
+    face = realize_face (cache, attr, -1);
 
 #if GLYPH_DEBUG
   xassert (face == FACE_FROM_ID (f, face->id));
-
-/* When this function is called from face_for_char (in this case, C is
-   a multibyte character), a fontset of a face returned by
-   realize_face is not yet set, i.e. FACE_SUITABLE_FOR_CHAR_P (FACE,
-   C) is not sutisfied.  The fontset is set for this face by
-   face_for_char later.  */
-#if 0
-  if (FRAME_WINDOW_P (f))
-    xassert (FACE_SUITABLE_FOR_CHAR_P (face, c));
-#endif
 #endif /* GLYPH_DEBUG */
 
   return face->id;
 }
 
 
+/* Look up a realized face that has the same attributes as BASE_FACE
+   except for the font in the face cache of frame F.  If FONT_ID is
+   not negative, it is an ID number of an already opened font that is
+   used by the face.  If FONT_ID is negative, the face has no font.
+   Value is the ID of the face found.  If no suitable face is found,
+   realize a new one.  */
+
+int
+lookup_non_ascii_face (f, font_id, base_face)
+     struct frame *f;
+     int font_id;
+     struct face *base_face;
+{
+  struct face_cache *cache = FRAME_FACE_CACHE (f);
+  unsigned hash;
+  int i;
+  struct face *face;
+
+  xassert (cache != NULL);
+  base_face = base_face->ascii_face;
+  hash = lface_hash (base_face->lface);
+  i = hash % FACE_CACHE_BUCKETS_SIZE;
+
+  for (face = cache->buckets[i]; face; face = face->next)
+    {
+      if (face->ascii_face == face)
+       continue;
+      if (face->ascii_face == base_face
+         && face->font_info_id == font_id)
+       break;
+    }
+
+  /* If not found, realize a new face.  */
+  if (face == NULL)
+    face = realize_non_ascii_face (f, font_id, base_face);
+
+#if GLYPH_DEBUG
+  xassert (face == FACE_FROM_ID (f, face->id));
+#endif /* GLYPH_DEBUG */
+
+  return face->id;
+}
+
 /* Return the face id of the realized face for named face SYMBOL on
-   frame F suitable for displaying character C.  Value is -1 if the
-   face couldn't be determined, which might happen if the default face
-   isn't realized and cannot be realized.  */
+   frame F suitable for displaying ASCII characters.  Value is -1 if
+   the face couldn't be determined, which might happen if the default
+   face isn't realized and cannot be realized.  */
 
 int
-lookup_named_face (f, symbol, c)
+lookup_named_face (f, symbol)
      struct frame *f;
      Lisp_Object symbol;
-     int c;
 {
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
@@ -5287,7 +5828,7 @@ lookup_named_face (f, symbol, c)
   get_lface_attributes (f, symbol, symbol_attrs, 1);
   bcopy (default_face->lface, attrs, sizeof attrs);
   merge_face_vectors (f, symbol_attrs, attrs, Qnil);
-  return lookup_face (f, attrs, c, NULL);
+  return lookup_face (f, attrs);
 }
 
 
@@ -5304,7 +5845,7 @@ ascii_face_of_lisp_face (f, lface_id)
   if (lface_id >= 0 && lface_id < lface_id_to_name_size)
     {
       Lisp_Object face_name = lface_id_to_name[lface_id];
-      face_id = lookup_named_face (f, face_name, 0);
+      face_id = lookup_named_face (f, face_name);
     }
   else
     face_id = -1;
@@ -5352,7 +5893,7 @@ smaller_face (f, face_id, steps)
       /* Look up a face for a slightly smaller/larger font.  */
       pt += delta;
       attrs[LFACE_HEIGHT_INDEX] = make_number (pt);
-      new_face_id = lookup_face (f, attrs, 0, NULL);
+      new_face_id = lookup_face (f, attrs);
       new_face = FACE_FROM_ID (f, new_face_id);
 
       /* If height changes, count that as one step.  */
@@ -5395,7 +5936,7 @@ face_with_height (f, face_id, height)
   face = FACE_FROM_ID (f, face_id);
   bcopy (face->lface, attrs, sizeof attrs);
   attrs[LFACE_HEIGHT_INDEX] = make_number (height);
-  face_id = lookup_face (f, attrs, 0, NULL);
+  face_id = lookup_face (f, attrs);
 #endif /* HAVE_WINDOW_SYSTEM */
 
   return face_id;
@@ -5403,17 +5944,16 @@ face_with_height (f, face_id, height)
 
 
 /* Return the face id of the realized face for named face SYMBOL on
-   frame F suitable for displaying character C, and use attributes of
-   the face FACE_ID for attributes that aren't completely specified by
-   SYMBOL.  This is like lookup_named_face, except that the default
-   attributes come from FACE_ID, not from the default face.  FACE_ID
-   is assumed to be already realized.  */
+   frame F suitable for displaying ASCII characters, and use
+   attributes of the face FACE_ID for attributes that aren't
+   completely specified by SYMBOL.  This is like lookup_named_face,
+   except that the default attributes come from FACE_ID, not from the
+   default face.  FACE_ID is assumed to be already realized.  */
 
 int
-lookup_derived_face (f, symbol, c, face_id)
+lookup_derived_face (f, symbol, face_id)
      struct frame *f;
      Lisp_Object symbol;
-     int c;
      int face_id;
 {
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
@@ -5426,7 +5966,22 @@ lookup_derived_face (f, symbol, c, face_id)
   get_lface_attributes (f, symbol, symbol_attrs, 1);
   bcopy (default_face->lface, attrs, sizeof attrs);
   merge_face_vectors (f, symbol_attrs, attrs, Qnil);
-  return lookup_face (f, attrs, c, default_face);
+  return lookup_face (f, attrs);
+}
+
+DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
+       Sface_attributes_as_vector, 1, 1, 0,
+       doc: /* Return a vector of face attributes corresponding to PLIST.  */)
+     (plist)
+     Lisp_Object plist;
+{
+  Lisp_Object lface;
+  lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
+                       Qunspecified);
+  merge_face_vector_with_property (XFRAME (selected_frame),
+                                  XVECTOR (lface)->contents,
+                                  plist);
+  return lface;
 }
 
 
@@ -5435,24 +5990,24 @@ lookup_derived_face (f, symbol, c, face_id)
                            Font selection
  ***********************************************************************/
 
-DEFUN ("internal-set-font-selection-order",
+ DEFUN ("internal-set-font-selection-order",
        Finternal_set_font_selection_order,
        Sinternal_set_font_selection_order, 1, 1, 0,
-  "Set font selection order for face font selection to ORDER.\n\
-ORDER must be a list of length 4 containing the symbols `:width',\n\
-`:height', `:weight', and `:slant'.  Face attributes appearing\n\
-first in ORDER are matched first, e.g. if `:height' appears before\n\
-`:weight' in ORDER, font selection first tries to find a font with\n\
-a suitable height, and then tries to match the font weight.\n\
-Value is ORDER.")
-  (order)
-       Lisp_Object order;
+       doc: /* Set font selection order for face font selection to ORDER.
+ORDER must be a list of length 4 containing the symbols `:width',
+`:height', `:weight', and `:slant'.  Face attributes appearing
+first in ORDER are matched first, e.g. if `:height' appears before
+`:weight' in ORDER, font selection first tries to find a font with
+a suitable height, and then tries to match the font weight.
+Value is ORDER.  */)
+     (order)
+     Lisp_Object order;
 {
   Lisp_Object list;
   int i;
   int indices[DIM (font_sort_order)];
 
-  CHECK_LIST (order, 0);
+  CHECK_LIST (order);
   bzero (indices, sizeof indices);
   i = 0;
 
@@ -5498,14 +6053,14 @@ Value is ORDER.")
 DEFUN ("internal-set-alternative-font-family-alist",
        Finternal_set_alternative_font_family_alist,
        Sinternal_set_alternative_font_family_alist, 1, 1, 0,
-  "Define alternative font families to try in face font selection.\n\
-ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.\n\
-Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can\n\
-be found.  Value is ALIST.")
-  (alist)
+       doc: /* Define alternative font families to try in face font selection.
+ALIST is an alist of (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
+Each ALTERNATIVE is tried in order if no fonts of font family FAMILY can
+be found.  Value is ALIST.  */)
+     (alist)
      Lisp_Object alist;
 {
-  CHECK_LIST (alist, 0);
+  CHECK_LIST (alist);
   Vface_alternative_font_family_alist = alist;
   free_all_realized_faces (Qnil);
   return alist;
@@ -5515,14 +6070,14 @@ be found.  Value is ALIST.")
 DEFUN ("internal-set-alternative-font-registry-alist",
        Finternal_set_alternative_font_registry_alist,
        Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
-  "Define alternative font registries to try in face font selection.\n\
-ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.\n\
-Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can\n\
-be found.  Value is ALIST.")
-  (alist)
+       doc: /* Define alternative font registries to try in face font selection.
+ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.
+Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can
+be found.  Value is ALIST.  */)
+     (alist)
      Lisp_Object alist;
 {
-  CHECK_LIST (alist, 0);
+  CHECK_LIST (alist);
   Vface_alternative_font_registry_alist = alist;
   free_all_realized_faces (Qnil);
   return alist;
@@ -5577,12 +6132,23 @@ better_font_p (values, font1, font2, compare_pt_p, avgwidth)
 
       if (compare_pt_p || xlfd_idx != XLFD_POINT_SIZE)
        {
-         int delta1 = abs (values[i] - font1->numeric[xlfd_idx]);
-         int delta2 = abs (values[i] - font2->numeric[xlfd_idx]);
+         int delta1, delta2;
+
+         if (xlfd_idx == XLFD_POINT_SIZE)
+           {
+             delta1 = abs (values[i] - (font1->numeric[xlfd_idx]
+                                        / font1->rescale_ratio));
+             delta2 = abs (values[i] - (font2->numeric[xlfd_idx]
+                                        / font2->rescale_ratio));
+             if (abs (delta1 - delta2) < FONT_POINT_SIZE_QUANTUM)
+               continue;
+           }
+         else
+           {
+             delta1 = abs (values[i] - font1->numeric[xlfd_idx]);
+             delta2 = abs (values[i] - font2->numeric[xlfd_idx]);
+           }
 
-         if (xlfd_idx == XLFD_POINT_SIZE
-             && abs (delta1 - delta2) < FONT_POINT_SIZE_QUANTUM)
-           continue;
          if (delta1 > delta2)
            return 0;
          else if (delta1 < delta2)
@@ -5647,11 +6213,17 @@ build_scalable_font_name (f, font, specified_pt)
      struct font_name *font;
      int specified_pt;
 {
-  char point_size[20], pixel_size[20];
+  char pixel_size[20];
   int pixel_value;
   double resy = FRAME_X_DISPLAY_INFO (f)->resy;
   double pt;
 
+  if (font->numeric[XLFD_PIXEL_SIZE] != 0
+      || font->numeric[XLFD_POINT_SIZE] != 0)
+    /* This is a scalable font but is requested for a specific size.
+       We should not change that size.  */
+    return build_font_name (font);
+
   /* If scalable font is for a specific resolution, compute
      the point size we must specify from the resolution of
      the display and the specified resolution of the font.  */
@@ -5665,11 +6237,19 @@ build_scalable_font_name (f, font, specified_pt)
       pt = specified_pt;
       pixel_value = resy / (PT_PER_INCH * 10.0) * pt;
     }
+  /* We may need a font of the different size.  */
+  pixel_value *= font->rescale_ratio;
 
-  /* Set point size of the font.  */
-  sprintf (point_size, "%d", (int) pt);
-  font->fields[XLFD_POINT_SIZE] = point_size;
-  font->numeric[XLFD_POINT_SIZE] = pt;
+  /* We should keep POINT_SIZE 0.  Otherwise, X server can't open a
+     font of the specified PIXEL_SIZE.  */
+#if 0
+  { /* Set point size of the font.  */
+    char point_size[20];
+    sprintf (point_size, "%d", (int) pt);
+    font->fields[XLFD_POINT_SIZE] = point_size;
+    font->numeric[XLFD_POINT_SIZE] = pt;
+  }
+#endif
 
   /* Set pixel size.  */
   sprintf (pixel_size, "%d", pixel_value);
@@ -5705,7 +6285,7 @@ build_scalable_font_name (f, font, specified_pt)
 
 static int
 may_use_scalable_font_p (font)
-     char *font;
+     const char *font;
 {
   if (EQ (Vscalable_fonts_allowed, Qt))
     return 1;
@@ -5733,15 +6313,20 @@ may_use_scalable_font_p (font)
    widths if ATTRS specifies such a width.
 
    Value is a font name which is allocated from the heap.  FONTS is
-   freed by this function.  */
+   freed by this function.
+
+   If NEEDS_OVERSTRIKE is non-zero, a boolean is returned in it to
+   indicate whether the resulting font should be drawn using overstrike
+   to simulate bold-face.  */
 
 static char *
-best_matching_font (f, attrs, fonts, nfonts, width_ratio)
+best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike)
      struct frame *f;
      Lisp_Object *attrs;
      struct font_name *fonts;
      int nfonts;
      int width_ratio;
+     int *needs_overstrike;
 {
   char *font_name;
   struct font_name *best;
@@ -5776,6 +6361,9 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio)
 
   exact_p = 0;
 
+  if (needs_overstrike)
+    *needs_overstrike = 0;
+
   /* Start with the first non-scalable font in the list.  */
   for (i = 0; i < nfonts; ++i)
     if (!font_scalable_p (fonts + i))
@@ -5796,7 +6384,6 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio)
            if (exact_p)
              break;
          }
-
     }
   else
     best = NULL;
@@ -5829,6 +6416,24 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio)
                    && !better_font_p (specified, best, fonts + i, 0, 0)))
              best = fonts + i;
          }
+
+      if (needs_overstrike)
+       {
+         enum xlfd_weight want_weight = specified[XLFD_WEIGHT];
+         enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT];
+
+         if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight)
+           {
+             /* We want a bold font, but didn't get one; try to use
+                overstriking instead to simulate bold-face.  However,
+                don't overstrike an already-bold fontn unless the
+                desired weight grossly exceeds the available weight.  */
+             if (got_weight > XLFD_WEIGHT_MEDIUM)
+               *needs_overstrike = (got_weight - want_weight) > 2;
+             else
+               *needs_overstrike = 1;
+           }
+       }
     }
 
   if (font_scalable_p (best))
@@ -5851,7 +6456,7 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio)
    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.  */
 
@@ -5879,11 +6484,11 @@ try_alternative_families (f, family, registry, fonts)
                nfonts = font_list (f, Qnil, XCAR (alter), registry, fonts);
            }
        }
-      
-      /* Try scalable fonts before giving up.  */
-      if (nfonts == 0 && NILP (Vscalable_fonts_allowed))
+
+      /* Try all scalable fonts before giving up.  */
+      if (nfonts == 0 && ! EQ (Vscalable_fonts_allowed, Qt))
        {
-         int count = BINDING_STACK_SIZE ();
+         int count = SPECPDL_INDEX ();
          specbind (Qscalable_fonts_allowed, Qt);
          nfonts = try_alternative_families (f, family, registry, fonts);
          unbind_to (count, Qnil);
@@ -5895,47 +6500,61 @@ try_alternative_families (f, family, registry, fonts)
 
 /* 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.
+   PATTERN, if a string, specifies a font name pattern to match while
+   ignoring FAMILY and REGISTRY.
+
+   FAMILY, if a list, specifies a list of font families to try.
+
+   REGISTRY, if a list, specifies a list of font registries and
+   encodinging to try.
 
-   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)
+try_font_list (f, pattern, family, registry, fonts)
      struct frame *f;
-     Lisp_Object *attrs;
-     Lisp_Object family, registry;
+     Lisp_Object pattern, 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)
+  if (STRINGP (pattern))
+    {
+      nfonts = font_list (f, pattern, Qnil, Qnil, fonts);
+      if (nfonts == 0 && ! EQ (Vscalable_fonts_allowed, Qt))
+       {
+         int count = SPECPDL_INDEX ();
+         specbind (Qscalable_fonts_allowed, Qt);
+         nfonts = font_list (f, pattern, Qnil, Qnil, fonts);
+         unbind_to (count, Qnil);
+       }
+    }
+  else
     {
-      struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-      if (default_face)
-       family = default_face->lface[LFACE_FAMILY_INDEX];
+      Lisp_Object tail;
+
+      if (NILP (family))
+       nfonts = font_list (f, Qnil, Qnil, registry, fonts);
       else
-       family = build_string ("fixed");
-      nfonts = font_list (f, Qnil, family, registry, fonts);
+       for (tail = family; ! nfonts && CONSP (tail); tail = XCDR (tail))
+         nfonts = try_alternative_families (f, XCAR (tail), registry, fonts);
+
+      /* Try font family of the default face or "fixed".  */
+      if (nfonts == 0 && !NILP (family))
+       {
+         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 = try_alternative_families (f, family, registry, fonts);
+       }
+
+      /* Try any family with the given registry.  */
+      if (nfonts == 0 && !NILP (family))
+       nfonts = try_alternative_families (f, Qnil, registry, fonts);
     }
-      
-  /* Try any family with the given registry.  */
-  if (nfonts == 0)
-    nfonts = font_list (f, Qnil, Qnil, registry, fonts);
 
   return nfonts;
 }
@@ -5951,53 +6570,109 @@ face_fontset (attrs)
 {
   Lisp_Object name;
 
-  name = attrs[LFACE_FONT_INDEX];
+  name = attrs[LFACE_FONTSET_INDEX];
   if (!STRINGP (name))
     return -1;
   return fs_query_fontset (name, 0);
 }
 
 
-/* Choose a name of font to use on frame F to display character C with
+/* Choose a name of font to use on frame F to display characters with
    Lisp face attributes specified by ATTRS.  The font name is
-   determined by the font-related attributes in ATTRS and the name
-   pattern for C in FONTSET.  Value is the font name which is
-   allocated from the heap and must be freed by the caller, or NULL if
-   we can get no information about the font name of C.  It is assured
-   that we always get some information for a single byte
-   character.  */
+   determined by the font-related attributes in ATTRS and FONT-SPEC
+   (if specified).
 
-static char *
-choose_face_font (f, attrs, fontset, c)
+   When we are choosing a font for ASCII characters, FONT-SPEC is
+   always nil.  Otherwise FONT-SPEC is a list
+       [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
+   or a string specifying a font name pattern.
+
+   If NEEDS_OVERSTRIKE is not NULL, a boolean is returned in it to
+   indicate whether the resulting font should be drawn using
+   overstrike to simulate bold-face.
+
+   Value is the font name which is allocated from the heap and must be
+   freed by the caller.  */
+
+char *
+choose_face_font (f, attrs, font_spec, needs_overstrike)
      struct frame *f;
      Lisp_Object *attrs;
-     int fontset, c;
+     Lisp_Object font_spec;
+     int *needs_overstrike;
 {
-  Lisp_Object pattern;
+  Lisp_Object pattern, family, adstyle, registry;
   char *font_name = NULL;
   struct font_name *fonts;
-  int nfonts, width_ratio;
+  int nfonts;
 
-  /* Get (foundry and) family name and registry (and encoding) name of
-     a font for C.  */
-  pattern = fontset_font_pattern (f, fontset, c);
-  if (NILP (pattern))
+  if (needs_overstrike)
+    *needs_overstrike = 0;
+
+  /* If we are choosing an ASCII font and a font name is explicitly
+     specified in ATTRS, return it.  */
+  if (NILP (font_spec) && STRINGP (attrs[LFACE_FONT_INDEX]))
+    return xstrdup (SDATA (attrs[LFACE_FONT_INDEX]));
+
+  if (NILP (attrs[LFACE_FAMILY_INDEX]))
+    family = Qnil;
+  else
+    family = Fcons (attrs[LFACE_FAMILY_INDEX], Qnil);
+
+  /* Decide FAMILY, ADSTYLE, and REGISTRY from FONT_SPEC.  But,
+     ADSTYLE is not used in the font selector for the moment.  */
+  if (VECTORP (font_spec))
     {
-      xassert (!SINGLE_BYTE_CHAR_P (c));
-      return NULL;
+      pattern = Qnil;
+      if (STRINGP (AREF (font_spec, FONT_SPEC_FAMILY_INDEX)))
+       family = Fcons (AREF (font_spec, FONT_SPEC_FAMILY_INDEX), family);
+      adstyle = AREF (font_spec, FONT_SPEC_ADSTYLE_INDEX);
+      registry = Fcons (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX), Qnil);
+    }
+  else if (STRINGP (font_spec))
+    {
+      pattern = font_spec;
+      family = Qnil;
+      adstyle = Qnil;
+      registry = Qnil;
+    }
+  else
+    {
+      /* We are choosing an ASCII font.  By default, use the registry
+        name "iso8859-1".  But, if the registry name of the ASCII
+        font specified in the fontset of ATTRS is not "iso8859-1"
+        (e.g "iso10646-1"), use also that name with higher
+        priority.  */
+      int fontset = face_fontset (attrs);
+      Lisp_Object ascii;
+      int len;
+      struct font_name font;
+
+      pattern = Qnil;
+      adstyle = Qnil;
+      registry = Fcons (build_string ("iso8859-1"), Qnil);
+
+      ascii = fontset_ascii (fontset);
+      len = SBYTES (ascii);
+      if (len < 9
+         || strcmp (SDATA (ascii) + len - 9, "iso8859-1"))
+       {
+         font.name = LSTRDUPA (ascii);
+         /* Check if the name is in XLFD.  */
+         if (split_font_name (f, &font, 0))
+           {
+             font.fields[XLFD_ENCODING][-1] = '-';
+             registry = Fcons (build_string (font.fields[XLFD_REGISTRY]),
+                               registry);
+           }
+       }
     }
-  
-  /* If what we got is a name pattern, return it.  */
-  if (STRINGP (pattern))
-    return xstrdup (XSTRING (pattern)->data);
 
   /* 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, 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);
+  nfonts = try_font_list (f, pattern, family, registry, &fonts);
+  font_name = best_matching_font (f, attrs, fonts, nfonts, NILP (font_spec),
+                                 needs_overstrike);
   return font_name;
 }
 
@@ -6018,18 +6693,19 @@ realize_basic_faces (f)
      struct frame *f;
 {
   int success_p = 0;
-  int count = BINDING_STACK_SIZE ();
+  int count = SPECPDL_INDEX ();
 
-  /* Block input there so that we won't be surprised by an X expose
-     event, for instance without having the faces set up.  */
+  /* Block input here so that we won't be surprised by an X expose
+     event, for instance, without having the faces set up.  */
   BLOCK_INPUT;
   specbind (Qscalable_fonts_allowed, Qt);
 
   if (realize_default_face (f))
     {
       realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
+      realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
       realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
-      realize_named_face (f, Qfringe, BITMAP_AREA_FACE_ID);
+      realize_named_face (f, Qfringe, FRINGE_FACE_ID);
       realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
       realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
       realize_named_face (f, Qborder, BORDER_FACE_ID);
@@ -6038,14 +6714,14 @@ 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;
+         FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
 #ifdef USE_X_TOOLKIT
          x_update_menu_appearance (f);
 #endif
        }
-      
+
       success_p = 1;
     }
 
@@ -6072,11 +6748,12 @@ realize_default_face (f)
   /* If the `default' face is not yet known, create it.  */
   lface = lface_from_face_name (f, Qdefault, 0);
   if (NILP (lface))
-    {
-      Lisp_Object frame;
-      XSETFRAME (frame, f);
-      lface = Finternal_make_lisp_face (Qdefault, frame);
-    }
+  {
+       Lisp_Object frame;
+       XSETFRAME (frame, f);
+       lface = Finternal_make_lisp_face (Qdefault, frame);
+  }
+
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
@@ -6085,7 +6762,9 @@ realize_default_face (f)
       frame_font = Fassq (Qfont, f->param_alist);
       xassert (CONSP (frame_font) && STRINGP (XCDR (frame_font)));
       frame_font = XCDR (frame_font);
-      set_lface_from_font_name (f, lface, frame_font, 1, 1);
+      set_lface_from_font_name (f, lface, frame_font,
+                                f->default_face_done_p, 1);
+      f->default_face_done_p = 1;
     }
 #endif /* HAVE_WINDOW_SYSTEM */
 
@@ -6094,8 +6773,10 @@ realize_default_face (f)
       LFACE_FAMILY (lface) = build_string ("default");
       LFACE_SWIDTH (lface) = Qnormal;
       LFACE_HEIGHT (lface) = make_number (1);
-      LFACE_WEIGHT (lface) = Qnormal;
-      LFACE_SLANT (lface) = Qnormal;
+      if (UNSPECIFIEDP (LFACE_WEIGHT (lface)))
+       LFACE_WEIGHT (lface) = Qnormal;
+      if (UNSPECIFIEDP (LFACE_SLANT (lface)))
+       LFACE_SLANT (lface) = Qnormal;
       LFACE_AVGWIDTH (lface) = Qunspecified;
     }
 
@@ -6152,7 +6833,7 @@ realize_default_face (f)
   xassert (lface_fully_specified_p (XVECTOR (lface)->contents));
   check_lface (lface);
   bcopy (XVECTOR (lface)->contents, attrs, sizeof attrs);
-  face = realize_face (c, attrs, 0, NULL, DEFAULT_FACE_ID);
+  face = realize_face (c, attrs, DEFAULT_FACE_ID);
   return 1;
 }
 
@@ -6191,23 +6872,19 @@ realize_named_face (f, symbol, id)
   merge_face_vectors (f, symbol_attrs, attrs, Qnil);
 
   /* Realize the face.  */
-  new_face = realize_face (c, attrs, 0, NULL, id);
+  new_face = realize_face (c, attrs, id);
 }
 
 
 /* Realize the fully-specified face with attributes ATTRS in face
-   cache CACHE for character C.  If C is a multibyte character,
-   BASE_FACE is a face that has the same attributes.  Otherwise,
-   BASE_FACE is ignored.  If FORMER_FACE_ID is non-negative, it is an
-   ID of face to remove before caching the new face.  Value is a
-   pointer to the newly created realized face.  */
+   cache CACHE for ASCII characters.  If FORMER_FACE_ID is
+   non-negative, it is an ID of face to remove before caching the new
+   face.  Value is a pointer to the newly created realized face.  */
 
 static struct face *
-realize_face (cache, attrs, c, base_face, former_face_id)
+realize_face (cache, attrs, former_face_id)
      struct face_cache *cache;
      Lisp_Object *attrs;
-     int c;
-     struct face *base_face;
      int former_face_id;
 {
   struct face *face;
@@ -6225,37 +6902,73 @@ realize_face (cache, attrs, c, base_face, former_face_id)
     }
 
   if (FRAME_WINDOW_P (cache->f))
-    face = realize_x_face (cache, attrs, c, base_face);
+    face = realize_x_face (cache, attrs);
   else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
-    face = realize_tty_face (cache, attrs, c);
+    face = realize_tty_face (cache, attrs);
   else
     abort ();
 
   /* Insert the new face.  */
   cache_face (cache, face, lface_hash (attrs));
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (cache->f) && face->font == NULL)
-    load_face_font (cache->f, face, c);
-#endif  /* HAVE_WINDOW_SYSTEM */
+  return face;
+}
+
+
+/* Realize the fully-specified face that has the same attributes as
+   BASE_FACE except for the font on frame F.  If FONT_ID is not
+   negative, it is an ID number of an already opened font that should
+   be used by the face.  If FONT_ID is negative, the face has no font,
+   i.e., characters are displayed by empty boxes.  */
+
+static struct face *
+realize_non_ascii_face (f, font_id, base_face)
+     struct frame *f;
+     int font_id;
+     struct face *base_face;
+{
+  struct face_cache *cache = FRAME_FACE_CACHE (f);
+  struct face *face;
+  struct font_info *font_info;
+
+  face = (struct face *) xmalloc (sizeof *face);
+  *face = *base_face;
+  face->gc = 0;
+
+  /* Don't try to free the colors copied bitwise from BASE_FACE.  */
+  face->colors_copied_bitwise_p = 1;
+
+  face->font_info_id = font_id;
+  if (font_id >= 0)
+    {
+      font_info = FONT_INFO_FROM_ID (f, font_id);
+      face->font = font_info->font;
+      face->font_name = font_info->full_name;
+    }
+  else
+    {
+      face->font = NULL;
+      face->font_name = NULL;
+    }
+
+  face->gc = 0;
+
+  cache_face (cache, face, face->hash);
+
   return face;
 }
 
 
 /* Realize the fully-specified face with attributes ATTRS in face
-   cache CACHE for character C.  Do it for X frame CACHE->f.  If C is
-   a multibyte character, BASE_FACE is a face that has the same
-   attributes.  Otherwise, BASE_FACE is ignored.  If the new face
-   doesn't share font with the default face, a fontname is allocated
-   from the heap and set in `font_name' of the new face, but it is not
-   yet loaded here.  Value is a pointer to the newly created realized
-   face.  */
+   cache CACHE for ASCII characters.  Do it for X frame CACHE->f.  If
+   the new face doesn't share font with the default face, a fontname
+   is allocated from the heap and set in `font_name' of the new face,
+   but it is not yet loaded here.  Value is a pointer to the newly
+   created realized face.  */
 
 static struct face *
-realize_x_face (cache, attrs, c, base_face)
+realize_x_face (cache, attrs)
      struct face_cache *cache;
      Lisp_Object *attrs;
-     int c;
-     struct face *base_face;
 {
 #ifdef HAVE_WINDOW_SYSTEM
   struct face *face, *default_face;
@@ -6263,55 +6976,24 @@ realize_x_face (cache, attrs, c, base_face)
   Lisp_Object stipple, overline, strike_through, box;
 
   xassert (FRAME_WINDOW_P (cache->f));
-  xassert (SINGLE_BYTE_CHAR_P (c)
-          || base_face);
 
   /* Allocate a new realized face.  */
   face = make_realized_face (attrs);
+  face->ascii_face = face;
 
   f = cache->f;
 
-  /* If C is a multibyte character, we share all face attirbutes with
-     BASE_FACE including the realized fontset.  But, we must load a
-     different font.  */
-  if (!SINGLE_BYTE_CHAR_P (c))
-    {
-      bcopy (base_face, face, sizeof *face);
-      face->gc = 0;
-
-      /* Don't try to free the colors copied bitwise from BASE_FACE.  */
-      face->foreground_defaulted_p = 1;
-      face->background_defaulted_p = 1;
-      face->underline_defaulted_p = 1;
-      face->overline_color_defaulted_p = 1;
-      face->strike_through_color_defaulted_p = 1;
-      face->box_color_defaulted_p = 1;
-
-      /* to force realize_face to load font */
-      face->font = NULL;
-      return face;
-    }
-
-  /* Now we are realizing a face for ASCII (and unibyte) characters.  */
-
   /* Determine the font to use.  Most of the time, the font will be
      the same as the font of the default face, so try that first.  */
   default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
   if (default_face
-      && FACE_SUITABLE_FOR_CHAR_P (default_face, c)
       && lface_same_font_attributes_p (default_face->lface, attrs))
     {
       face->font = default_face->font;
-      face->fontset = default_face->fontset;
       face->font_info_id = default_face->font_info_id;
       face->font_name = default_face->font_name;
-      face->ascii_face = face;
-
-      /* But, as we can't share the fontset, make a new realized
-        fontset that has the same base fontset as of the default
-        face.  */
       face->fontset
-       = make_fontset_for_ascii_face (f, default_face->fontset);
+       = make_fontset_for_ascii_face (f, default_face->fontset, face);
     }
   else
     {
@@ -6323,22 +7005,16 @@ realize_x_face (cache, attrs, c, base_face)
         are constructed from ATTRS.  */
       int fontset = face_fontset (attrs);
 
-      if ((fontset == -1) && default_face)
+      /* If we are realizing the default face, ATTRS should specify a
+        fontset.  In other words, if FONTSET is -1, we are not
+        realizing the default face, thus the default face should have
+        already been realized.  */
+      if (fontset == -1)
        fontset = default_face->fontset;
-      face->fontset = make_fontset_for_ascii_face (f, fontset);
-      face->font = NULL;       /* to force realize_face to load font */
-
-#ifdef macintosh
-      /* Load the font if it is specified in ATTRS.  This fixes
-         changing frame font on the Mac.  */
-      if (STRINGP (attrs[LFACE_FONT_INDEX]))
-        {
-          struct font_info *font_info =
-            FS_LOAD_FONT (f, 0, XSTRING (attrs[LFACE_FONT_INDEX])->data, -1);
-          if (font_info)
-            face->font = font_info->font;
-        }
-#endif
+      if (fontset == -1)
+       abort ();
+      load_face_font (f, face);
+      face->fontset = make_fontset_for_ascii_face (f, fontset, face);
     }
 
   /* Load colors, and set remaining attributes.  */
@@ -6470,7 +7146,6 @@ realize_x_face (cache, attrs, c, base_face)
   if (!NILP (stipple))
     face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h);
 
-  xassert (FACE_SUITABLE_FOR_CHAR_P (face, c));
   return face;
 #endif /* HAVE_WINDOW_SYSTEM */
 }
@@ -6504,12 +7179,12 @@ map_tty_color (f, face, idx, defaulted)
       pixel = default_pixel = FACE_TTY_DEFAULT_BG_COLOR;
       default_other_pixel = FACE_TTY_DEFAULT_FG_COLOR;
     }
-  
+
   XSETFRAME (frame, f);
   color = face->lface[idx];
-  
+
   if (STRINGP (color)
-      && XSTRING (color)->size
+      && SCHARS (color)
       && CONSP (Vtty_defined_color_alist)
       && (def = assq_no_quit (color, call1 (Qtty_color_alist, frame)),
          CONSP (def)))
@@ -6563,14 +7238,13 @@ map_tty_color (f, face, idx, defaulted)
 
 
 /* Realize the fully-specified face with attributes ATTRS in face
-   cache CACHE for character C.  Do it for TTY frame CACHE->f.  Value is a
-   pointer to the newly created realized face.  */
+   cache CACHE for ASCII characters.  Do it for TTY frame CACHE->f.
+   Value is a pointer to the newly created realized face.  */
 
 static struct face *
-realize_tty_face (cache, attrs, c)
+realize_tty_face (cache, attrs)
      struct face_cache *cache;
      Lisp_Object *attrs;
-     int c;
 {
   struct face *face;
   int weight, slant;
@@ -6602,7 +7276,7 @@ realize_tty_face (cache, attrs, c)
   /* Map color names to color indices.  */
   map_tty_color (f, face, LFACE_FOREGROUND_INDEX, &face_colors_defaulted);
   map_tty_color (f, face, LFACE_BACKGROUND_INDEX, &face_colors_defaulted);
-  
+
   /* Swap colors if face is inverse-video.  If the colors are taken
      from the frame colors, they are already inverted, since the
      frame-creation function calls x-handle-reverse-video.  */
@@ -6626,13 +7300,13 @@ realize_tty_face (cache, attrs, c)
 DEFUN ("tty-suppress-bold-inverse-default-colors",
        Ftty_suppress_bold_inverse_default_colors,
        Stty_suppress_bold_inverse_default_colors, 1, 1, 0,
-  "Suppress/allow boldness of faces with inverse default colors.\n\
-SUPPRESS non-nil means suppress it.\n\
-This affects bold faces on TTYs whose foreground is the default background\n\
-color of the display and whose background is the default foreground color.\n\
-For such faces, the bold face attribute is ignored if this variable\n\
-is non-nil.")
-  (suppress)
+       doc: /* Suppress/allow boldness of faces with inverse default colors.
+SUPPRESS non-nil means suppress it.
+This affects bold faces on TTYs whose foreground is the default background
+color of the display and whose background is the default foreground color.
+For such faces, the bold face attribute is ignored if this variable
+is non-nil.  */)
+     (suppress)
      Lisp_Object suppress;
 {
   tty_suppress_bold_inverse_default_colors_p = !NILP (suppress);
@@ -6663,21 +7337,25 @@ compute_char_face (f, ch, prop)
   if (NILP (prop))
     {
       struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-      face_id = FACE_FOR_CHAR (f, face, ch);
+      face_id = FACE_FOR_CHAR (f, face, ch, -1, Qnil);
     }
   else
     {
       Lisp_Object attrs[LFACE_VECTOR_SIZE];
-      struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-      bcopy (default_face->lface, attrs, sizeof attrs);
+      struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+      bcopy (face->lface, attrs, sizeof attrs);
       merge_face_vector_with_property (f, attrs, prop);
-      face_id = lookup_face (f, attrs, ch, NULL);
+      face_id = lookup_face (f, attrs);
+      if (! ASCII_CHAR_P (ch))
+       {
+         face = FACE_FROM_ID (f, face_id);
+         face_id = FACE_FOR_CHAR (f, face, ch, -1, Qnil);
+       }
     }
 
   return face_id;
 }
 
-
 /* Return the face ID associated with buffer position POS for
    displaying ASCII characters.  Return in *ENDPTR the position at
    which a different face is needed, as far as text properties and
@@ -6806,7 +7484,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
 
   /* Look up a realized face with the given face attributes,
      or realize a new one for ASCII characters.  */
-  return lookup_face (f, attrs, 0, NULL);
+  return lookup_face (f, attrs);
 }
 
 
@@ -6860,7 +7538,7 @@ face_at_string_position (w, string, pos, bufpos, region_beg,
      Limit is the maximum position up to which to check for property
      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);
+  XSETFASTINT (limit, SCHARS (string));
   end = Fnext_single_property_change (position, prop_name, string, limit);
   if (INTEGERP (end))
     *endptr = XFASTINT (end);
@@ -6905,7 +7583,7 @@ face_at_string_position (w, string, pos, bufpos, region_beg,
 
   /* Look up a realized face with the given face attributes,
      or realize a new one for ASCII characters.  */
-  return lookup_face (f, attrs, 0, NULL);
+  return lookup_face (f, attrs);
 }
 
 
@@ -6928,13 +7606,13 @@ dump_realized_face (face)
 #endif
   fprintf (stderr, "foreground: 0x%lx (%s)\n",
           face->foreground,
-          XSTRING (face->lface[LFACE_FOREGROUND_INDEX])->data);
+          SDATA (face->lface[LFACE_FOREGROUND_INDEX]));
   fprintf (stderr, "background: 0x%lx (%s)\n",
           face->background,
-          XSTRING (face->lface[LFACE_BACKGROUND_INDEX])->data);
+          SDATA (face->lface[LFACE_BACKGROUND_INDEX]));
   fprintf (stderr, "font_name: %s (%s)\n",
           face->font_name,
-          XSTRING (face->lface[LFACE_FAMILY_INDEX])->data);
+          SDATA (face->lface[LFACE_FAMILY_INDEX]));
 #ifdef HAVE_X_WINDOWS
   fprintf (stderr, "font = %p\n", face->font);
 #endif
@@ -6942,14 +7620,13 @@ dump_realized_face (face)
   fprintf (stderr, "fontset: %d\n", face->fontset);
   fprintf (stderr, "underline: %d (%s)\n",
           face->underline_p,
-          XSTRING (Fsymbol_name (face->lface[LFACE_UNDERLINE_INDEX]))->data);
+          SDATA (Fsymbol_name (face->lface[LFACE_UNDERLINE_INDEX])));
   fprintf (stderr, "hash: %d\n", face->hash);
-  fprintf (stderr, "charset: %d\n", face->charset);
 }
 
 
-DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
-   (n)
+DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: /* */)
+     (n)
      Lisp_Object n;
 {
   if (NILP (n))
@@ -6971,7 +7648,7 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
   else
     {
       struct face *face;
-      CHECK_NUMBER (n, 0);
+      CHECK_NUMBER (n);
       face = FACE_FROM_ID (SELECTED_FRAME (), XINT (n));
       if (face == NULL)
        error ("Not a valid face");
@@ -6983,8 +7660,8 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
 
 
 DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
-       0, 0, 0, "")
-  ()
+       0, 0, 0, doc: /* */)
+     ()
 {
   fprintf (stderr, "number of colors = %d\n", ncolors_allocated);
   fprintf (stderr, "number of pixmaps = %d\n", npixmaps_allocated);
@@ -7035,6 +7712,8 @@ syms_of_xfaces ()
   staticpro (&QCwidth);
   QCfont = intern (":font");
   staticpro (&QCfont);
+  QCfontset = intern (":fontset");
+  staticpro (&QCfontset);
   QCbold = intern (":bold");
   staticpro (&QCbold);
   QCitalic = intern (":italic");
@@ -7130,8 +7809,12 @@ syms_of_xfaces ()
   staticpro (&Qborder);
   Qmouse = intern ("mouse");
   staticpro (&Qmouse);
+  Qmode_line_inactive = intern ("mode-line-inactive");
+  staticpro (&Qmode_line_inactive);
   Qtty_color_desc = intern ("tty-color-desc");
   staticpro (&Qtty_color_desc);
+  Qtty_color_standard_values = intern ("tty-color-standard-values");
+  staticpro (&Qtty_color_standard_values);
   Qtty_color_by_index = intern ("tty-color-by-index");
   staticpro (&Qtty_color_by_index);
   Qtty_color_alist = intern ("tty-color-alist");
@@ -7154,6 +7837,8 @@ syms_of_xfaces ()
 #endif
   defsubr (&Scolor_gray_p);
   defsubr (&Scolor_supported_p);
+  defsubr (&Sface_attribute_relative_p);
+  defsubr (&Smerge_face_attribute);
   defsubr (&Sinternal_get_lisp_face_attribute);
   defsubr (&Sinternal_lisp_face_attribute_values);
   defsubr (&Sinternal_lisp_face_equal_p);
@@ -7162,9 +7847,12 @@ syms_of_xfaces ()
   defsubr (&Sinternal_merge_in_global_face);
   defsubr (&Sface_font);
   defsubr (&Sframe_face_alist);
+  defsubr (&Stty_supports_face_attributes_p);
+  defsubr (&Scolor_distance);
   defsubr (&Sinternal_set_font_selection_order);
   defsubr (&Sinternal_set_alternative_font_family_alist);
   defsubr (&Sinternal_set_alternative_font_registry_alist);
+  defsubr (&Sface_attributes_as_vector);
 #if GLYPH_DEBUG
   defsubr (&Sdump_face);
   defsubr (&Sshow_face_resources);
@@ -7177,41 +7865,51 @@ syms_of_xfaces ()
 #endif
 
   DEFVAR_LISP ("font-list-limit", &Vfont_list_limit,
-    "*Limit for font matching.\n\
-If an integer > 0, font matching functions won't load more than\n\
-that number of fonts when searching for a matching font.");
+              doc: /* *Limit for font matching.
+If an integer > 0, font matching functions won't load more than
+that number of fonts when searching for a matching font.  */);
   Vfont_list_limit = make_number (DEFAULT_FONT_LIST_LIMIT);
 
   DEFVAR_LISP ("face-new-frame-defaults", &Vface_new_frame_defaults,
-    "List of global face definitions (for internal use only.)");
+    doc: /* List of global face definitions (for internal use only.)  */);
   Vface_new_frame_defaults = Qnil;
 
   DEFVAR_LISP ("face-default-stipple", &Vface_default_stipple,
-    "*Default stipple pattern used on monochrome displays.\n\
-This stipple pattern is used on monochrome displays\n\
-instead of shades of gray for a face background color.\n\
-See `set-face-stipple' for possible values for this variable.");
+    doc: /* *Default stipple pattern used on monochrome displays.
+This stipple pattern is used on monochrome displays
+instead of shades of gray for a face background color.
+See `set-face-stipple' for possible values for this variable.  */);
   Vface_default_stipple = build_string ("gray3");
 
   DEFVAR_LISP ("tty-defined-color-alist", &Vtty_defined_color_alist,
-   "An alist of defined terminal colors and their RGB values.");
+   doc: /* An alist of defined terminal colors and their RGB values.  */);
   Vtty_defined_color_alist = Qnil;
 
   DEFVAR_LISP ("scalable-fonts-allowed", &Vscalable_fonts_allowed,
-    "Allowed scalable fonts.\n\
-A value of nil means don't allow any scalable fonts.\n\
-A value of t means allow any scalable font.\n\
-Otherwise, value must be a list of regular expressions.  A font may be\n\
-scaled if its name matches a regular expression in the list.\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.");
+              doc: /* Allowed scalable fonts.
+A value of nil means don't allow any scalable fonts.
+A value of t means allow any scalable font.
+Otherwise, value must be a list of regular expressions.  A font may be
+scaled if its name matches a regular expression in the list.
+Note that if value is nil, a scalable font might still be used, if no
+other font of the appropriate family and registry is available.  */);
   Vscalable_fonts_allowed = Qnil;
 
   DEFVAR_LISP ("face-ignored-fonts", &Vface_ignored_fonts,
-    "List of ignored fonts.\n\
-Each element is a regular expression that matches names of fonts to ignore.");
+              doc: /* List of ignored fonts.
+Each element is a regular expression that matches names of fonts to
+ignore.  */);
   Vface_ignored_fonts = Qnil;
 
+  DEFVAR_LISP ("face-font-rescale-alist", &Vface_font_rescale_alist,
+              doc: /* Alist of fonts vs the rescaling factors.
+Each element is a cons (FONT-NAME-PATTERN . RESCALE-RATIO), where
+FONT-NAME-PATTERN is a regular expression matching a font name, and
+RESCALE-RATIO is a floating point number to specify how much larger
+\(or smaller) font we should use.  For instance, if a face requests
+a font of 10 point, we actually use a font of 10 * RESCALE-RATIO point.  */);
+  Vface_font_rescale_alist = Qnil;
+
 #ifdef HAVE_WINDOW_SYSTEM
   defsubr (&Sbitmap_spec_p);
   defsubr (&Sx_list_fonts);