(Ftty_suppress_bold_inverse_default_colors): Doc fix.
[bpt/emacs.git] / src / xfaces.c
index 34d02ee..e7b1e2c 100644 (file)
@@ -1,5 +1,5 @@
 /* xfaces.c -- "Face" primitives.
-   Copyright (C) 1993, 1994, 1998, 1999 Free Software Foundation.
+   Copyright (C) 1993, 1994, 1998, 1999, 2000 Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -26,19 +26,19 @@ Boston, MA 02111-1307, USA.  */
    changed by defining `faces'.  Each face can specify the following
    display attributes:
 
-   1. Font family or fontset alias name.
-   
+   1. Font family name.
+
    2. Relative proportionate width, aka character set width or set
    width (swidth), e.g. `semi-compressed'.
-   
-   3. Font height in 1/10pt
-   
+
+   3. Font height in 1/10pt.
+
    4. Font weight, e.g. `bold'.
-   
+
    5. Font slant, e.g. `italic'.
-   
+
    6. Foreground color.
-   
+
    7. Background color.
 
    8. Whether or not characters should be underlined, and in what color.
@@ -55,20 +55,30 @@ 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.
+   When this attribyte is specified, the face uses a font opened by
+   that pattern as is.  In addition, all the other font-related
+   attributes (1st thru 5th) are generated from the opened font name.
+   On the other hand, if one of the other font-related attributes are
+   specified, this attribute is set to nil.  In that case, the face
+   doesn't inherit this attribute from the `default' face, and uses a
+   font determined by the other attributes (those may be inherited
+   from the `default' face).
+
    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
    faces.  The value of a named face in such an alist is a Lisp vector
-   with the symbol `face' in slot 0, and a slot for each each of the
-   face attributes mentioned above.
+   with the symbol `face' in slot 0, and a slot for each of the face
+   attributes mentioned above.
 
    There is also a global face alist `Vface_new_frame_defaults'.  Face
    definitions from this list are used to initialize faces of newly
    created frames.
-   
+
    A face doesn't have to specify all attributes.  Those not specified
-   have a value of `unspecified'.  Faces specifying all attributes are
-   called `fully-specified'.
+   have a value of `unspecified'.  Faces specifying all attributes but
+   the 14th are called `fully-specified'.
 
 
    Face merging.
@@ -82,7 +92,7 @@ Boston, MA 02111-1307, USA.  */
 
 
    Face realization.
-   
+
    After all face attributes for a character have been determined by
    merging faces of that character, that face is `realized'.  The
    realization process maps face attributes to what is physically
@@ -90,47 +100,44 @@ Boston, MA 02111-1307, USA.  */
    `realized face' in form of a struct face which is stored in the
    face cache of the frame on which it was realized.
 
-   Face realization is done in the context of the charset of the
-   character to display because different fonts and encodings are used
-   for different charsets.  In other words, for characters of
-   different charsets, different realized faces are needed to display
+   Face realization is done in the context of the character to display
+   because different fonts may be used for different characters.  In
+   other words, for characters that have different font
+   specifications, different realized faces are needed to display
    them.
 
-   Except for composite characters (CHARSET_COMPOSITION), faces are
-   always realized for a specific character set and contain a specific
-   font, even if the face being realized specifies a fontset (see
-   `font selection' below).  The reason is that the result of the new
-   font selection stage is better than what can be done with
-   statically defined font name patterns in fontsets.
+   Font specification is done by fontsets.  See the comment in
+   fontset.c for the details.  In the current implementation, all ASCII
+   characters share the same font in a fontset.
+
+   Faces are at first realized for ASCII characters, and, at that
+   time, assigned a specific realized fontset.  Hereafter, we call
+   such a face as `ASCII face'.  When a face for a multibyte character
+   is realized, it inherits (thus shares) a fontset of an ASCII face
+   that has the same attributes other than font-related ones.
+
+   Thus, all realzied face have a realized fontset.
 
 
    Unibyte text.
 
-   In unibyte text, Emacs' charsets aren't applicable; function
-   `char-charset' reports CHARSET_ASCII for all characters, including
-   those > 0x7f.  The X registry and encoding of fonts to use is
-   determined from the variable `x-unibyte-registry-and-encoding' in
-   this case.  The variable is initialized at Emacs startup time from
-   the font the user specified for Emacs.
+   Unibyte text (i.e. raw 8-bit characters) is displayed with the same
+   font as ASCII characters.  That is because it is expected that
+   unibyte text users specify a font that is suitable both for ASCII
+   and raw 8-bit characters.
 
-   Currently all unibyte text, i.e. all buffers with
-   enable_multibyte_characters nil are displayed with fonts of the
-   same registry and encoding `x-unibyte-registry-and-encoding'.  This
-   is consistent with the fact that languages can also be set
-   globally, only.
-   
 
    Font selection.
 
    Font selection tries to find the best available matching font for a
-   given (charset, face) combination.  This is done slightly
-   differently for faces specifying a fontset, or a font family name.
+   given (character, face) combination.
 
-   If the face specifies a fontset alias name, that fontset determines
-   a pattern for fonts of the given charset.  If the face specifies a
-   font family, a font pattern is constructed.  Charset symbols have a
-   property `x-charset-registry' for that purpose that maps a charset
-   to an XLFD registry and encoding in the font pattern constructed.
+   If the face specifies a fontset name, that fontset determines a
+   pattern for fonts of the given character.  If the face specifies a
+   font name or the other font-related attributes, a fontset is
+   realized from the default fontset.  In that case, that
+   specification determines a pattern for ASCII characters and the
+   default fontset determines a pattern for multibyte characters.
 
    Available fonts on the system on which Emacs runs are then matched
    against the font pattern.  The result of font selection is the best
@@ -152,15 +159,17 @@ Boston, MA 02111-1307, USA.  */
    face doesn't exist.
 
 
-   Composite characters.  
-   
-   Realized faces for composite characters are the only ones having a
-   fontset id >= 0.  When a composite character is encoded into a
-   sequence of non-composite characters (in xterm.c), a suitable font
-   for the non-composite characters is then selected and realized,
-   i.e.  the realization process is delayed but in principle the same.
+   Character compositition.
+
+   Usually, the realization process is already finished when Emacs
+   actually reflects the desired glyph matrix on the screen.  However,
+   on displaying a composition (sequence of characters to be composed
+   on the screen), a suitable font for the components of the
+   composition is selected and realized while drawing them on the
+   screen, i.e.  the realization process is delayed but in principle
+   the same.
+
 
-   
    Initialization of basic faces.
 
    The faces `default', `modeline' are considered `basic faces'.
@@ -177,22 +186,44 @@ Boston, MA 02111-1307, USA.  */
 
 #define SCALABLE_FONTS 1
 
+#include <config.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <config.h>
 #include "lisp.h"
 #include "charset.h"
 #include "frame.h"
 
+#ifdef HAVE_WINDOW_SYSTEM
+#include "fontset.h"
+#endif
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
-#include "fontset.h"
+#ifdef USE_MOTIF
+#include <Xm/Xm.h>
+#include <Xm/XmStrDefs.h>
+#endif /* USE_MOTIF */
 #endif
 
 #ifdef MSDOS
 #include "dosfns.h"
 #endif
 
+#ifdef WINDOWSNT
+#include "w32term.h"
+#include "fontset.h"
+/* Redefine X specifics to W32 equivalents to avoid cluttering the
+   code with #ifdef blocks. */
+#define FRAME_X_DISPLAY_INFO FRAME_W32_DISPLAY_INFO
+#define x_display_info w32_display_info
+#define FRAME_X_FONT_TABLE FRAME_W32_FONT_TABLE
+#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. */
+#define FONT_WIDTH FONT_MAX_WIDTH
+#endif
+
 #include "buffer.h"
 #include "dispextern.h"
 #include "blockinput.h"
@@ -219,7 +250,6 @@ Boston, MA 02111-1307, USA.  */
 #endif /* HAVE_X_WINDOWS */
 
 #include <stdio.h>
-#include <stdlib.h>
 #include <ctype.h>
 #include "keyboard.h"
 
@@ -237,7 +267,7 @@ Boston, MA 02111-1307, USA.  */
 
 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
 
-/* Make a copy of string S on the stack using alloca.  Value is a pointer 
+/* Make a copy of string S on the stack using alloca.  Value is a pointer
    to the copy.  */
 
 #define STRDUPA(S) strcpy ((char *) alloca (strlen ((S)) + 1), (S))
@@ -247,11 +277,21 @@ Boston, MA 02111-1307, USA.  */
 
 #define LSTRDUPA(S) STRDUPA (XSTRING ((S))->data)
 
-/* Size of hash table of realized faces in face caches (should be a 
+/* 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
+
 /* Keyword symbols used for face attribute names.  */
 
 Lisp_Object QCfamily, QCheight, QCweight, QCslant, QCunderline;
@@ -272,16 +312,29 @@ Lisp_Object Qreleased_button, Qpressed_button;
 Lisp_Object QCstyle, QCcolor, QCline_width;
 Lisp_Object Qunspecified;
 
-/* The symbol `x-charset-registry'.  This property of charsets defines
-   the X registry and encoding that fonts should have that are used to
-   display characters of that charset.  */
+char unspecified_fg[] = "unspecified-fg", unspecified_bg[] = "unspecified-bg";
 
-Lisp_Object Qx_charset_registry;
+/* The name of the function to call when the background of the frame
+   has changed, frame_update_face_colors.  */
+
+Lisp_Object Qframe_update_face_colors;
 
 /* Names of basic faces.  */
 
-Lisp_Object Qdefault, Qmodeline, Qtool_bar, Qregion, Qmargin;
-Lisp_Object Qheader_line;
+Lisp_Object Qdefault, Qtool_bar, Qregion, Qfringe;
+Lisp_Object Qheader_line, Qscroll_bar, Qcursor, Qborder, Qmouse, Qmenu;
+extern Lisp_Object Qmode_line;
+
+/* The symbol `face-alias'.  A symbols having that property is an
+   alias for another face.  Value of the property is the name of
+   the aliased face.  */
+
+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
@@ -290,11 +343,6 @@ Lisp_Object Qheader_line;
 
 Lisp_Object Vface_default_stipple;
 
-/* Default registry and encoding to use for charsets whose charset
-   symbols don't specify one.  */
-
-Lisp_Object Vface_default_registry;
-
 /* Alist of alternative font families.  Each element is of the form
    (FAMILY FAMILY1 FAMILY2 ...).  If fonts of FAMILY can't be loaded,
    try FAMILY1, then FAMILY2, ...  */
@@ -330,7 +378,7 @@ extern Lisp_Object Qmouse_face;
 
 /* Error symbol for wrong_type_argument in load_pixmap.  */
 
-Lisp_Object Qpixmap_spec_p;
+Lisp_Object Qbitmap_spec_p;
 
 /* Alist of global face definitions.  Each element is of the form
    (FACE . LFACE) where FACE is a symbol naming a face and LFACE
@@ -348,10 +396,8 @@ static int next_lface_id;
 static Lisp_Object *lface_id_to_name;
 static int lface_id_to_name_size;
 
-/* An alist of elements (COLOR-NAME . INDEX) mapping color names
-   to color indices for tty frames.  */
-
-Lisp_Object Vface_tty_color_alist;
+/* tty color-related functions (defined on lisp/term/tty-colors.el).  */
+Lisp_Object Qtty_color_desc, Qtty_color_by_index;
 
 /* Counter for calls to clear_face_cache.  If this counter reaches
    CLEAR_FONT_TABLE_COUNT, and a frame has more than
@@ -366,6 +412,13 @@ static int clear_font_table_count;
 
 int 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
+   which is hard to read on an LCD monitor.  */
+
+int tty_suppress_bold_inverse_default_colors_p;
+
 /* The total number of colors currently allocated.  */
 
 #if GLYPH_DEBUG
@@ -381,6 +434,7 @@ static int ngcs;
 struct font_name;
 struct table_entry;
 
+static Lisp_Object resolve_face_name P_ ((Lisp_Object));
 static int may_use_scalable_font_p P_ ((struct font_name *, 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 *,
@@ -390,15 +444,12 @@ static int first_font_matching P_ ((struct frame *f, char *,
 static int x_face_list_fonts P_ ((struct frame *, char *,
                                  struct font_name *, int, int, int));
 static int font_scalable_p P_ ((struct font_name *));
-static Lisp_Object deduce_unibyte_registry P_ ((struct frame *, char *));
 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 char *xstrdup P_ ((char *));
 static unsigned char *xstrlwr P_ ((unsigned char *));
 static void signal_error P_ ((char *, Lisp_Object));
-static void add_to_log P_ ((struct frame *, char *, Lisp_Object, Lisp_Object));
 static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int));
-static void load_face_font_or_fontset P_ ((struct frame *, struct face *, char *, int));
+static void load_face_font P_ ((struct frame *, struct face *, int));
 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 *));
@@ -407,14 +458,15 @@ static void free_font_names P_ ((struct font_name *, int));
 static int sorted_font_list P_ ((struct frame *, char *,
                                 int (*cmpfn) P_ ((const void *, const void *)),
                                 struct font_name **));
-static int font_list P_ ((struct frame *, char *, char *, char *, struct font_name **));
-static int try_font_list P_ ((struct frame *, Lisp_Object *, char *, char *, char *,
-                             struct font_name **));
+static int font_list P_ ((struct frame *, Lisp_Object, Lisp_Object,
+                         Lisp_Object, struct font_name **));
+static int try_font_list P_ ((struct frame *, Lisp_Object *, Lisp_Object,
+                             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));
+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));
+                                       Lisp_Object *, int, struct face *));
 static struct face *realize_tty_face P_ ((struct face_cache *,
                                          Lisp_Object *, int));
 static int realize_basic_faces P_ ((struct frame *));
@@ -432,18 +484,15 @@ 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_ ((struct frame *, Lisp_Object *));
-static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int,
-                                  Lisp_Object));
-static char *choose_face_fontset_font P_ ((struct frame *, Lisp_Object *,
-                                          int, int));
+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_ ((Lisp_Object *from, Lisp_Object *));
 static void merge_face_vector_with_property P_ ((struct frame *, Lisp_Object *,
                                                 Lisp_Object));
-static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object, char *,
-                                        int));
+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 *, int, Lisp_Object));
+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));
@@ -459,11 +508,12 @@ static int xlfd_fixed_p P_ ((struct font_name *));
 static int xlfd_numeric_value P_ ((struct table_entry *, int, struct font_name *,
                                   int, int));
 static Lisp_Object xlfd_symbolic_value P_ ((struct table_entry *, int,
-                                           struct font_name *, int, int));
+                                           struct font_name *, int,
+                                           Lisp_Object));
 static struct table_entry *xlfd_lookup_field_contents P_ ((struct table_entry *, int,
                                                           struct font_name *, int));
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 
 static int split_font_name P_ ((struct frame *, struct font_name *, int));
 static int xlfd_point_size P_ ((struct frame *, struct font_name *));
@@ -473,7 +523,11 @@ 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 *));
 
-#endif /* HAVE_X_WINDOWS */
+#ifdef WINDOWSNT
+extern Lisp_Object w32_list_fonts P_ ((struct frame *, Lisp_Object, int, int));
+#endif /* WINDOWSNT */
+
+#endif /* HAVE_WINDOW_SYSTEM */
 
 \f
 /***********************************************************************
@@ -482,6 +536,138 @@ static void clear_font_table P_ ((struct frame *));
 
 #ifdef HAVE_X_WINDOWS
 
+#ifdef DEBUG_X_COLORS
+
+/* The following is a poor mans infrastructure for debugging X color
+   allocation problems on displays with PseudoColor-8.  Some X servers
+   like 3.3.5 XF86_SVGA with Matrox cards apparently don't implement
+   color reference counts completely so that they don't signal an
+   error when a color is freed whose reference count is already 0.
+   Other X servers do.  To help me debug this, the following code
+   implements a simple reference counting schema of its own, for a
+   single display/screen.  --gerd.  */
+
+/* Reference counts for pixel colors.  */
+
+int color_count[256];
+
+/* Register color PIXEL as allocated.  */
+
+void
+register_color (pixel)
+     unsigned long pixel;
+{
+  xassert (pixel < 256);
+  ++color_count[pixel];
+}
+
+
+/* Register color PIXEL as deallocated.  */
+
+void
+unregister_color (pixel)
+     unsigned long pixel;
+{
+  xassert (pixel < 256);
+  if (color_count[pixel] > 0)
+    --color_count[pixel];
+  else
+    abort ();
+}
+
+
+/* Register N colors from PIXELS as deallocated.  */
+
+void
+unregister_colors (pixels, n)
+     unsigned long *pixels;
+     int n;
+{
+  int i;
+  for (i = 0; i < n; ++i)
+    unregister_color (pixels[i]);
+}
+
+
+DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
+  "Dump currently allocated colors and their reference counts to stderr.")
+  ()
+{
+  int i, n;
+
+  fputc ('\n', stderr);
+
+  for (i = n = 0; i < sizeof color_count / sizeof color_count[0]; ++i)
+    if (color_count[i])
+      {
+       fprintf (stderr, "%3d: %5d", i, color_count[i]);
+       ++n;
+       if (n % 5 == 0)
+         fputc ('\n', stderr);
+       else
+         fputc ('\t', stderr);
+      }
+
+  if (n % 5 != 0)
+    fputc ('\n', stderr);
+  return Qnil;
+}
+
+
+#endif /* DEBUG_X_COLORS */
+
+/* Free colors used on frame F.  PIXELS is an array of NPIXELS pixel
+   color values.  Interrupt input must be blocked when this function
+   is called.  */
+
+void
+x_free_colors (f, pixels, npixels)
+     struct frame *f;
+     unsigned long *pixels;
+     int npixels;
+{
+  int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
+
+  /* If display has an immutable color map, freeing colors is not
+     necessary and some servers don't allow it.  So don't do it.  */
+  if (class != StaticColor && class != StaticGray && class != TrueColor)
+    {
+      XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+                  pixels, npixels, 0);
+#ifdef DEBUG_X_COLORS
+      unregister_colors (pixels, npixels);
+#endif
+    }
+}
+
+
+/* Free colors used on frame F.  PIXELS is an array of NPIXELS pixel
+   color values.  Interrupt input must be blocked when this function
+   is called.  */
+
+void
+x_free_dpy_colors (dpy, screen, cmap, pixels, npixels)
+     Display *dpy;
+     Screen *screen;
+     Colormap cmap;
+     unsigned long *pixels;
+     int npixels;
+{
+  struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
+  int class = dpyinfo->visual->class;
+
+  /* If display has an immutable color map, freeing colors is not
+     necessary and some servers don't allow it.  So don't do it.  */
+  if (class != StaticColor && class != StaticGray && class != TrueColor)
+    {
+      XFreeColors (dpy, cmap, pixels, npixels, 0);
+#ifdef DEBUG_X_COLORS
+      unregister_colors (pixels, npixels);
+#endif
+    }
+}
+
+
 /* Create and return a GC for use on frame F.  GC values and mask
    are given by XGCV and MASK.  */
 
@@ -515,19 +701,38 @@ x_free_gc (f, gc)
 
 #endif /* HAVE_X_WINDOWS */
 
+#ifdef WINDOWSNT
+/* W32 emulation of GCs */
 
-/* Like strdup, but uses xmalloc.  */
+static INLINE GC
+x_create_gc (f, mask, xgcv)
+     struct frame *f;
+     unsigned long mask;
+     XGCValues *xgcv;
+{
+  GC gc;
+  BLOCK_INPUT;
+  gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, xgcv);
+  UNBLOCK_INPUT;
+  IF_DEBUG (++ngcs);
+  return gc;
+}
 
-static char *
-xstrdup (s)
-     char *s;
+
+/* Free GC which was used on frame F.  */
+
+static INLINE void
+x_free_gc (f, gc)
+     struct frame *f;
+     GC gc;
 {
-  int len = strlen (s) + 1;
-  char *p = (char *) xmalloc (len);
-  bcopy (s, p, len);
-  return p;
+  BLOCK_INPUT;
+  xassert (--ngcs >= 0);
+  xfree (gc);
+  UNBLOCK_INPUT;
 }
 
+#endif  /* WINDOWSNT */
 
 /* Like stricmp.  Used to compare parts of font names which are in
    ISO8859-1.  */
@@ -577,71 +782,22 @@ signal_error (s, arg)
 }
 
 
-/* Display a message with format string FORMAT and arguments ARG1 and
-   ARG2 on frame F.  Used to display errors if fonts, bitmaps, colors 
-   etc. for a realized face on frame F cannot be loaded.  (If we would
-   signal an error in these cases, we would end up in an infinite
-   recursion because this would stop realization, and the redisplay
-   triggered by the signal would try to realize that same face again.)
-
-   If basic faces of F are not realized, just add the message to the
-   messages buffer "*Messages*".  Because Fmessage calls
-   echo_area_display which tries to realize basic faces again, we would
-   otherwise also end in an infinite recursion.  */
-
-static void
-add_to_log (f, format, arg1, arg2)
-     struct frame *f;
-     char *format;
-     Lisp_Object arg1, arg2;
-{
-  Lisp_Object args[3];
-  Lisp_Object nargs;
-  Lisp_Object msg;
-  char *buffer;
-  extern int waiting_for_input;
-
-  /* Function note_mouse_highlight calls face_at_buffer_position which
-     may realize a face.  If some attribute of that face is invalid,
-     say an invalid color, don't display an error to avoid calling
-     Lisp from XTread_socket.  */
-  if (waiting_for_input)
-    return;
-
-  nargs = make_number (DIM (args));
-  args[0] = build_string (format);
-  args[1] = arg1;
-  args[2] = arg2;
-  msg = Fformat (nargs, args);
-
-  /* Log the error, but don't display it in the echo area.  This
-     proves to be annoying in many cases.  */
-  buffer = LSTRDUPA (msg);
-  message_dolog (buffer, strlen (buffer), 1, 0);
-}
-
-
-/* If FRAME is nil, return selected_frame.  Otherwise, check that
-   FRAME is a live frame, and return a pointer to it.  NPARAM
-   is the parameter number of FRAME, for CHECK_LIVE_FRAME.  This is
-   here because it's a frequent pattern in Lisp function definitions.  */
+/* If FRAME is nil, return a pointer to the selected frame.
+   Otherwise, check that FRAME is a live frame, and return a pointer
+   to it.  NPARAM is the parameter number of FRAME, for
+   CHECK_LIVE_FRAME.  This is here because it's a frequent pattern in
+   Lisp function definitions.  */
 
 static INLINE struct frame *
 frame_or_selected_frame (frame, nparam)
      Lisp_Object frame;
      int nparam;
 {
-  struct frame *f;
-  
   if (NILP (frame))
-    f = selected_frame;
-  else
-    {
-      CHECK_LIVE_FRAME (frame, nparam);
-      f = XFRAME (frame);
-    }
+    frame = selected_frame;
 
-  return f;
+  CHECK_LIVE_FRAME (frame, nparam);
+  return XFRAME (frame);
 }
 
 \f
@@ -658,21 +814,24 @@ init_frame_faces (f)
   /* Make a face cache, if F doesn't have one.  */
   if (FRAME_FACE_CACHE (f) == NULL)
     FRAME_FACE_CACHE (f) = make_face_cache (f);
-      
-#ifdef HAVE_X_WINDOWS
+
+#ifdef HAVE_WINDOW_SYSTEM
   /* Make the image cache.  */
-  if (FRAME_X_P (f))
+  if (FRAME_WINDOW_P (f))
     {
       if (FRAME_X_IMAGE_CACHE (f) == NULL)
        FRAME_X_IMAGE_CACHE (f) = make_image_cache ();
       ++FRAME_X_IMAGE_CACHE (f)->refcount;
     }
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
-  /* Realize basic faces.  Must have enough information in frame 
+  /* Realize basic faces.  Must have enough information in frame
      parameters to realize basic faces at this point.  */
 #ifdef HAVE_X_WINDOWS
   if (!FRAME_X_P (f) || FRAME_X_WINDOW (f))
+#endif
+#ifdef WINDOWSNT
+  if (!FRAME_WINDOW_P (f) || FRAME_W32_WINDOW (f))
 #endif
     if (!realize_basic_faces (f))
       abort ();
@@ -686,15 +845,15 @@ free_frame_faces (f)
      struct frame *f;
 {
   struct face_cache *face_cache = FRAME_FACE_CACHE (f);
-  
+
   if (face_cache)
     {
       free_face_cache (face_cache);
       FRAME_FACE_CACHE (f) = NULL;
     }
 
-#ifdef HAVE_X_WINDOWS
-  if (FRAME_X_P (f))
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (f))
     {
       struct image_cache *image_cache = FRAME_X_IMAGE_CACHE (f);
       if (image_cache)
@@ -704,13 +863,14 @@ free_frame_faces (f)
            free_image_cache (f);
        }
     }
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 }
 
 
-/* Recompute basic faces for frame F.  Call this after changing frame
-   parameters on which those faces depend, or when realized faces have
-   been freed due to changing attributes of named faces.  */
+/* Clear face caches, and recompute basic faces for frame F.  Call
+   this after changing frame parameters on which those faces depend,
+   or when realized faces have been freed due to changing attributes
+   of named faces. */
 
 void
 recompute_basic_faces (f)
@@ -718,8 +878,9 @@ recompute_basic_faces (f)
 {
   if (FRAME_FACE_CACHE (f))
     {
-      int realized_p = realize_basic_faces (f);
-      xassert (realized_p);
+      clear_face_cache (0);
+      if (!realize_basic_faces (f))
+       abort ();
     }
 }
 
@@ -731,7 +892,7 @@ void
 clear_face_cache (clear_fonts_p)
      int clear_fonts_p;
 {
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   Lisp_Object tail, frame;
   struct frame *f;
 
@@ -746,7 +907,7 @@ clear_face_cache (clear_fonts_p)
       FOR_EACH_FRAME (tail, frame)
        {
          f = XFRAME (frame);
-         if (FRAME_X_P (f)
+         if (FRAME_WINDOW_P (f)
              && FRAME_X_DISPLAY_INFO (f)->n_fonts > CLEAR_FONT_TABLE_NFONTS)
            {
              free_all_realized_faces (frame);
@@ -760,14 +921,14 @@ clear_face_cache (clear_fonts_p)
       FOR_EACH_FRAME (tail, frame)
        {
          f = XFRAME (frame);
-         if (FRAME_X_P (f))
+         if (FRAME_WINDOW_P (f))
            {
              clear_face_gcs (FRAME_FACE_CACHE (f));
              clear_image_cache (f, 0);
            }
        }
     }
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 }
 
 
@@ -783,78 +944,53 @@ Optional THOROUGHLY non-nil means try to free unused fonts, too.")
 
 
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 
 
-/* Remove those fonts from the font table of frame F that are not used
-   by fontsets.  Called from clear_face_cache from time to time.  */
+/* Remove those fonts from the font table of frame F exept for the
+   default ASCII font for the frame.  Called from clear_face_cache
+   from time to time.  */
 
 static void
 clear_font_table (f)
      struct frame *f;
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  char *used;
-  Lisp_Object rest, frame;
   int i;
 
-  xassert (FRAME_X_P (f));
+  xassert (FRAME_WINDOW_P (f));
 
-  used = (char *) alloca (dpyinfo->n_fonts * sizeof *used);
-  bzero (used, dpyinfo->n_fonts * sizeof *used);
+  /* Free those fonts that are not used by the frame F as the default.  */
+  for (i = 0; i < dpyinfo->n_fonts; ++i)
+    {
+      struct font_info *font_info = dpyinfo->font_table + i;
 
-  /* For all frames with the same x_display_info as F, record
-     in `used' those fonts that are in use by fontsets.  */
-  FOR_EACH_FRAME (rest, frame)
-    if (FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
-      {
-       struct frame *f = XFRAME (frame);
-       struct fontset_data *fontset_data = FRAME_FONTSET_DATA (f);
+      if (!font_info->name
+         || font_info->font == FRAME_FONT (f))
+       continue;
 
-       for (i = 0; i < fontset_data->n_fontsets; ++i)
-         {
-           struct fontset_info *info = fontset_data->fontset_table[i];
-           int j;
-           
-           for (j = 0; j <= MAX_CHARSET; ++j)
-             {
-               int idx = info->font_indexes[j];
-               if (idx >= 0)
-                 used[idx] = 1;
-             }
-         }
-      }
+      /* Free names.  */
+      if (font_info->full_name != font_info->name)
+       xfree (font_info->full_name);
+      xfree (font_info->name);
 
-  /* Free those fonts that are not used by fontsets.  */
-  for (i = 0; i < dpyinfo->n_fonts; ++i)
-    if (used[i] == 0 && dpyinfo->font_table[i].name)
-      {
-       struct font_info *font_info = dpyinfo->font_table + i;
-
-       /* Free names.  In xfns.c there is a comment that full_name
-          should never be freed because it is always shared with
-          something else.  I don't think this is true anymore---see
-          x_load_font.  It's either equal to font_info->name or
-          allocated via xmalloc, and there seems to be no place in
-          the source files where full_name is transferred to another
-          data structure.  */
-       if (font_info->full_name != font_info->name)
-         xfree (font_info->full_name);
-       xfree (font_info->name);
-
-       /* Free the font.  */
-       BLOCK_INPUT;
-       XFreeFont (dpyinfo->display, font_info->font);
-       UNBLOCK_INPUT;
-
-       /* Mark font table slot free.  */
-       font_info->font = NULL;
-       font_info->name = font_info->full_name = NULL;
-      }
-}
+      /* Free the font.  */
+      BLOCK_INPUT;
+#ifdef HAVE_X_WINDOWS
+      XFreeFont (dpyinfo->display, font_info->font);
+#endif
+#ifdef WINDOWSNT
+      w32_unload_font (dpyinfo, font_info->font);
+#endif
+      UNBLOCK_INPUT;
 
+      /* Mark font table slot free.  */
+      font_info->font = NULL;
+      font_info->name = font_info->full_name = NULL;
+    }
+}
 
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
 
 \f
@@ -862,34 +998,55 @@ clear_font_table (f)
                              X Pixmaps
  ***********************************************************************/
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 
-DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
-  "Non-nil if OBJECT is a valid pixmap specification.\n\
-A pixmap specification is either a string, or a list (WIDTH HEIGHT DATA)\n\
-where WIDTH is the pixel width of the pixmap, HEIGHT is its height,\n\
-and DATA contains the bits of the pixmap.")
+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)
      Lisp_Object object;
 {
-  Lisp_Object height, width;
+  int pixmap_p = 0;
+
+  if (STRINGP (object))
+    /* If OBJECT is a string, it's a file name.  */
+    pixmap_p = 1;
+  else if (CONSP (object))
+    {
+      /* Otherwise OBJECT must be (WIDTH HEIGHT DATA), WIDTH and
+        HEIGHT must be integers > 0, and DATA must be string large
+        enough to hold a bitmap of the specified size.  */
+      Lisp_Object width, height, data;
+
+      height = width = data = Qnil;
+
+      if (CONSP (object))
+       {
+         width = XCAR (object);
+         object = XCDR (object);
+         if (CONSP (object))
+           {
+             height = XCAR (object);
+             object = XCDR (object);
+             if (CONSP (object))
+               data = XCAR (object);
+           }
+       }
+
+      if (NATNUMP (width) && NATNUMP (height) && STRINGP (data))
+       {
+         int bytes_per_row = ((XFASTINT (width) + BITS_PER_CHAR - 1)
+                              / BITS_PER_CHAR);
+         if (STRING_BYTES (XSTRING (data)) >= bytes_per_row * XINT (height))
+           pixmap_p = 1;
+       }
+    }
 
-  return ((STRINGP (object)
-          || (CONSP (object)
-              && CONSP (XCONS (object)->cdr)
-              && CONSP (XCONS (XCONS (object)->cdr)->cdr)
-              && NILP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->cdr)
-              && (width = XCONS (object)->car, INTEGERP (width))
-              && (height = XCONS (XCONS (object)->cdr)->car,
-                  INTEGERP (height))
-              && STRINGP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)
-              && XINT (width) > 0
-              && XINT (height) > 0
-              /* The string must have enough bits for width * height.  */
-              && ((XSTRING (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)->size
-                   * (BITS_PER_INT / sizeof (int)))
-                  >= XFASTINT (width) * XFASTINT (height))))
-         ? Qt : Qnil);
+  return pixmap_p ? Qt : Qnil;
 }
 
 
@@ -912,9 +1069,9 @@ load_pixmap (f, name, w_ptr, h_ptr)
   if (NILP (name))
     return 0;
 
-  tem = Fpixmap_spec_p (name);
+  tem = Fbitmap_spec_p (name);
   if (NILP (tem))
-    wrong_type_argument (Qpixmap_spec_p, name);
+    wrong_type_argument (Qbitmap_spec_p, name);
 
   BLOCK_INPUT;
   if (CONSP (name))
@@ -940,7 +1097,7 @@ load_pixmap (f, name, w_ptr, h_ptr)
 
   if (bitmap_id < 0)
     {
-      add_to_log (f, "Invalid or undefined bitmap %s", name, Qnil);
+      add_to_log ("Invalid or undefined bitmap %s", name, Qnil);
       bitmap_id = 0;
 
       if (w_ptr)
@@ -963,7 +1120,7 @@ load_pixmap (f, name, w_ptr, h_ptr)
   return bitmap_id;
 }
 
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
 
 \f
@@ -971,7 +1128,7 @@ load_pixmap (f, name, w_ptr, h_ptr)
                         Minimum font bounds
  ***********************************************************************/
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 
 /* Update the line_height of frame F.  Return non-zero if line height
    changes.  */
@@ -980,92 +1137,65 @@ int
 frame_update_line_height (f)
      struct frame *f;
 {
-  int fontset, line_height, changed_p;
-  
-  fontset = f->output_data.x->fontset;
-  if (fontset > 0)
-    line_height = FRAME_FONTSET_DATA (f)->fontset_table[fontset]->height;
-  else
-    line_height = FONT_HEIGHT (f->output_data.x->font);
-  
-  changed_p = line_height != f->output_data.x->line_height;
-  f->output_data.x->line_height = line_height;
+  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_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
 \f
 /***********************************************************************
                                Fonts
  ***********************************************************************/
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 
-/* Load font or fontset of face FACE which is used on frame F.
-   FONTSET is the fontset FACE should use or -1, if FACE doesn't use a
-   fontset.  FONT_NAME is the name of the font to load, if no fontset
-   is used.  It is null if no suitable font name could be determined
-   for the face.  */
+/* 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.  */
 
 static void
-load_face_font_or_fontset (f, face, font_name, fontset)
+load_face_font (f, face, c)
      struct frame *f;
      struct face *face;
-     char *font_name;
-     int fontset;
+     int c;
 {
   struct font_info *font_info = NULL;
+  char *font_name;
 
   face->font_info_id = -1;
-  face->fontset = fontset;
   face->font = NULL;
-  
+
+  font_name = choose_face_font (f, face->lface, face->fontset, c);
+  if (!font_name)
+    return;
+
   BLOCK_INPUT;
-  if (fontset >= 0)
-    font_info = FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII,
-                             NULL, fontset);
-  else if (font_name)
-    font_info = FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f), face->charset,
-                             font_name, -1);
+  font_info = FS_LOAD_FACE_FONT (f, c, font_name, face);
   UNBLOCK_INPUT;
 
   if (font_info)
     {
-      char *s;
-      int i;
-      
-      face->font_info_id = FONT_INFO_ID (f, font_info);
+      face->font_info_id = font_info->font_idx;
       face->font = font_info->font;
       face->font_name = font_info->full_name;
-
-      /* Make the registry part of the font name readily accessible.
-        The registry is used to find suitable faces for unibyte text.  */
-      s = font_info->full_name + strlen (font_info->full_name);
-      i = 0;
-      while (i < 2 && --s >= font_info->full_name)
-       if (*s == '-')
-         ++i;
-
-      if (!STRINGP (face->registry)
-         || xstricmp (XSTRING (face->registry)->data, s + 1) != 0)
+      if (face->gc)
        {
-         if (STRINGP (Vface_default_registry)
-             && !xstricmp (XSTRING (Vface_default_registry)->data, s + 1))
-           face->registry = Vface_default_registry;
-         else
-           face->registry = build_string (s + 1);
+         x_free_gc (f, face->gc);
+         face->gc = 0;
        }
     }
-  else if (fontset >= 0)
-    add_to_log (f, "Unable to load ASCII font of fontset %d",
-               make_number (fontset), Qnil);
-  else if (font_name)
-    add_to_log (f, "Unable to load font %s",
+  else
+    add_to_log ("Unable to load font %s",
                build_string (font_name), Qnil);
+  xfree (font_name);
 }
 
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
 
 \f
@@ -1073,7 +1203,136 @@ load_face_font_or_fontset (f, face, font_name, fontset)
                                X Colors
  ***********************************************************************/
 
+/* A version of defined_color for non-X frames.  */
+
+int
+tty_defined_color (f, color_name, color_def, alloc)
+     struct frame *f;
+     char *color_name;
+     XColor *color_def;
+     int alloc;
+{
+  Lisp_Object color_desc;
+  unsigned long color_idx = FACE_TTY_DEFAULT_COLOR,
+    red = 0, green = 0, blue = 0;
+  int status = 1;
+
+  if (*color_name && !NILP (Ffboundp (Qtty_color_desc)))
+    {
+      Lisp_Object frame;
+
+      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 (strcmp (color_name, "unspecified-fg") == 0)
+       color_idx = FACE_TTY_DEFAULT_FG_COLOR;
+      else if (strcmp (color_name, "unspecified-bg") == 0)
+       color_idx = FACE_TTY_DEFAULT_BG_COLOR;
+    }
+
+  if (color_idx != 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;
+}
+
+
+/* Decide if color named COLOR_NAME is valid for the display
+   associated with the frame F; if so, return the rgb values in
+   COLOR_DEF.  If ALLOC is nonzero, allocate a new colormap cell.
+
+   This does the right thing for any type of frame.  */
+
+int
+defined_color (f, color_name, color_def, alloc)
+     struct frame *f;
+     char *color_name;
+     XColor *color_def;
+     int alloc;
+{
+  if (!FRAME_WINDOW_P (f))
+    return tty_defined_color (f, color_name, color_def, alloc);
 #ifdef HAVE_X_WINDOWS
+  else if (FRAME_X_P (f))
+    return x_defined_color (f, color_name, color_def, alloc);
+#endif
+#ifdef WINDOWSNT
+  else if (FRAME_W32_P (f))
+    return w32_defined_color (f, color_name, color_def, alloc);
+#endif
+#ifdef macintosh
+  else if (FRAME_MAC_P (f))
+    /* FIXME: mac_defined_color doesn't exist!  */
+    return mac_defined_color (f, color_name, color_def, alloc);
+#endif
+  else
+    abort ();
+}
+
+
+/* Given the index IDX of a tty color on frame F, return its name, a
+   Lisp string.  */
+
+Lisp_Object
+tty_color_name (f, idx)
+     struct frame *f;
+     int idx;
+{
+  if (idx >= 0 && !NILP (Ffboundp (Qtty_color_by_index)))
+    {
+      Lisp_Object frame;
+      Lisp_Object coldesc;
+
+      XSETFRAME (frame, f);
+      coldesc = call2 (Qtty_color_by_index, make_number (idx), frame);
+
+      if (!NILP (coldesc))
+       return XCAR (coldesc);
+    }
+#ifdef MSDOS
+  /* We can have an MSDOG frame under -nw for a short window of
+     opportunity before internal_terminal_init is called.  DTRT.  */
+  if (FRAME_MSDOS_P (f) && !inhibit_window_system)
+    return msdos_stdcolor_name (idx);
+#endif
+
+  if (idx == FACE_TTY_DEFAULT_FG_COLOR)
+    return build_string (unspecified_fg);
+  if (idx == FACE_TTY_DEFAULT_BG_COLOR)
+    return build_string (unspecified_bg);
+
+#ifdef WINDOWSNT
+  return vga_stdcolor_name (idx);
+#endif
+
+  return Qunspecified;
+}
+
 
 /* Return non-zero if COLOR_NAME is a shade of gray (or white or
    black) on frame F.  The algorithm is taken from 20.2 faces.el.  */
@@ -1095,7 +1354,7 @@ face_color_gray_p (f, color_name)
                  < max (color.blue, color.red) / 20));
   else
     gray_p = 0;
-  
+
   return gray_p;
 }
 
@@ -1111,48 +1370,57 @@ face_color_supported_p (f, color_name, background_p)
      int background_p;
 {
   Lisp_Object frame;
+  XColor not_used;
 
   XSETFRAME (frame, f);
-  return (!NILP (Vwindow_system)
-         && (!NILP (Fx_display_color_p (frame))
-             || xstricmp (color_name, "black") == 0
-             || xstricmp (color_name, "white") == 0
-             || (background_p
-                 && face_color_gray_p (f, color_name))
-             || (!NILP (Fx_display_grayscale_p (frame))
-                 && face_color_gray_p (f, color_name))));
-}  
-
-
-DEFUN ("face-color-gray-p", Fface_color_gray_p, Sface_color_gray_p, 1, 2, 0,
+  return (FRAME_WINDOW_P (f)
+         ? (!NILP (Fxw_display_color_p (frame))
+            || xstricmp (color_name, "black") == 0
+            || xstricmp (color_name, "white") == 0
+            || (background_p
+                && face_color_gray_p (f, color_name))
+            || (!NILP (Fx_display_grayscale_p (frame))
+                && face_color_gray_p (f, color_name)))
+         : tty_defined_color (f, color_name, &not_used, 0));
+}
+
+
+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)
      Lisp_Object color, frame;
 {
-  struct frame *f = check_x_frame (frame);
+  struct frame *f;
+
+  CHECK_FRAME (frame, 0);
   CHECK_STRING (color, 0);
+  f = XFRAME (frame);
   return face_color_gray_p (f, XSTRING (color)->data) ? Qt : Qnil;
 }
 
 
-DEFUN ("face-color-supported-p", Fface_color_supported_p,
-       Sface_color_supported_p, 2, 3, 0,
+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.")
-   (frame, color, background_p)
+   (color, frame, background_p)
      Lisp_Object frame, color, background_p;
 {
-  struct frame *f = check_x_frame (frame);
+  struct frame *f;
+
+  CHECK_FRAME (frame, 0);
   CHECK_STRING (color, 0);
+  f = XFRAME (frame);
   if (face_color_supported_p (f, XSTRING (color)->data, !NILP (background_p)))
     return Qt;
   return Qnil;
 }
 
+
 /* Load color with name NAME for use by face FACE on frame F.
    TARGET_INDEX must be one of LFACE_FOREGROUND_INDEX,
    LFACE_BACKGROUND_INDEX, LFACE_UNDERLINE_INDEX, LFACE_OVERLINE_INDEX,
@@ -1170,7 +1438,7 @@ load_color (f, face, name, target_index)
      enum lface_attribute_index target_index;
 {
   XColor color;
-  
+
   xassert (STRINGP (name));
   xassert (target_index == LFACE_FOREGROUND_INDEX
           || target_index == LFACE_BACKGROUND_INDEX
@@ -1178,40 +1446,40 @@ load_color (f, face, name, target_index)
           || target_index == LFACE_OVERLINE_INDEX
           || target_index == LFACE_STRIKE_THROUGH_INDEX
           || target_index == LFACE_BOX_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))
     {
-      add_to_log (f, "Unable to load color %s", name, Qnil);
-      
+      add_to_log ("Unable to load color \"%s\"", name, Qnil);
+
       switch (target_index)
        {
        case LFACE_FOREGROUND_INDEX:
          face->foreground_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_BACKGROUND_INDEX:
          face->background_defaulted_p = 1;
          color.pixel = FRAME_BACKGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_UNDERLINE_INDEX:
          face->underline_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_OVERLINE_INDEX:
          face->overline_color_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_STRIKE_THROUGH_INDEX:
          face->strike_through_color_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
          break;
-         
+
        case LFACE_BOX_INDEX:
          face->box_color_defaulted_p = 1;
          color.pixel = FRAME_FOREGROUND_PIXEL (f);
@@ -1225,11 +1493,13 @@ load_color (f, face, name, target_index)
   else
     ++ncolors_allocated;
 #endif
-  
+
   return color.pixel;
 }
 
 
+#ifdef HAVE_WINDOW_SYSTEM
+
 /* Load colors for face FACE which is used on frame F.  Colors are
    specified by slots LFACE_BACKGROUND_INDEX and LFACE_FOREGROUND_INDEX
    of ATTRS.  If the background color specified is not supported on F,
@@ -1260,7 +1530,7 @@ load_face_colors (f, face, attrs)
      "supported" as background because we are supposed to use stipple
      for them.  */
   if (!face_color_supported_p (f, XSTRING (bg)->data, 0)
-      && !NILP (Fpixmap_spec_p (Vface_default_stipple)))
+      && !NILP (Fbitmap_spec_p (Vface_default_stipple)))
     {
       x_destroy_bitmap (f, face->stipple);
       face->stipple = load_pixmap (f, Vface_default_stipple,
@@ -1279,24 +1549,11 @@ unload_color (f, pixel)
      struct frame *f;
      unsigned long pixel;
 {
-  Display *dpy = FRAME_X_DISPLAY (f);
-  int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
-
-  if (pixel == BLACK_PIX_DEFAULT (f)
-      || pixel == WHITE_PIX_DEFAULT (f))
-    return;
-
+#ifdef HAVE_X_WINDOWS
   BLOCK_INPUT;
-  
-  /* If display has an immutable color map, freeing colors is not
-     necessary and some servers don't allow it.  So don't do it.  */
-  if (! (class == StaticColor || class == StaticGray || class == TrueColor))
-    {
-      Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-      XFreeColors (dpy, cmap, &pixel, 1, 0);
-    }
-  
+  x_free_colors (f, &pixel, 1);
   UNBLOCK_INPUT;
+#endif
 }
 
 
@@ -1307,145 +1564,54 @@ free_face_colors (f, face)
      struct frame *f;
      struct face *face;
 {
-  int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
-  
-  /* If display has an immutable color map, freeing colors is not
-     necessary and some servers don't allow it.  So don't do it.  */
-  if (class != StaticColor
-      && class != StaticGray
-      && class != TrueColor)
-    {
-      Display *dpy;
-      Colormap cmap;
-      
-      BLOCK_INPUT;
-      dpy = FRAME_X_DISPLAY (f);
-      cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-      
-      if (face->foreground != BLACK_PIX_DEFAULT (f)
-         && face->foreground != WHITE_PIX_DEFAULT (f)
-         && !face->foreground_defaulted_p)
-       {
-         XFreeColors (dpy, cmap, &face->foreground, 1, 0);
-         IF_DEBUG (--ncolors_allocated);
-       }
-      
-      if (face->background != BLACK_PIX_DEFAULT (f)
-         && face->background != WHITE_PIX_DEFAULT (f)
-         && !face->background_defaulted_p)
-       {
-         XFreeColors (dpy, cmap, &face->background, 1, 0);
-         IF_DEBUG (--ncolors_allocated);
-       }
-
-      if (face->underline_p
-         && !face->underline_defaulted_p
-         && face->underline_color != BLACK_PIX_DEFAULT (f)
-         && face->underline_color != WHITE_PIX_DEFAULT (f))
-       {
-         XFreeColors (dpy, cmap, &face->underline_color, 1, 0);
-         IF_DEBUG (--ncolors_allocated);
-       }
-
-      if (face->overline_p
-         && !face->overline_color_defaulted_p
-         && face->overline_color != BLACK_PIX_DEFAULT (f)
-         && face->overline_color != WHITE_PIX_DEFAULT (f))
-       {
-         XFreeColors (dpy, cmap, &face->overline_color, 1, 0);
-         IF_DEBUG (--ncolors_allocated);
-       }
-
-      if (face->strike_through_p
-         && !face->strike_through_color_defaulted_p
-         && face->strike_through_color != BLACK_PIX_DEFAULT (f)
-         && face->strike_through_color != WHITE_PIX_DEFAULT (f))
-       {
-         XFreeColors (dpy, cmap, &face->strike_through_color, 1, 0);
-         IF_DEBUG (--ncolors_allocated);
-       }
-
-      if (face->box != FACE_NO_BOX
-         && !face->box_color_defaulted_p
-         && face->box_color != BLACK_PIX_DEFAULT (f)
-         && face->box_color != WHITE_PIX_DEFAULT (f))
-       {
-         XFreeColors (dpy, cmap, &face->box_color, 1, 0);
-         IF_DEBUG (--ncolors_allocated);
-       }
+#ifdef HAVE_X_WINDOWS
+  BLOCK_INPUT;
 
-      UNBLOCK_INPUT;
+  if (!face->foreground_defaulted_p)
+    {
+      x_free_colors (f, &face->foreground, 1);
+      IF_DEBUG (--ncolors_allocated);
     }
-}
-
-#else  /* ! HAVE_X_WINDOWS */
 
-#ifdef MSDOS
-unsigned long
-load_color (f, face, name, target_index)
-     struct frame *f;
-     struct face *face;
-     Lisp_Object name;
-     enum lface_attribute_index target_index;
-{
-  Lisp_Object color;
-  int color_idx = FACE_TTY_DEFAULT_COLOR;
-
-  if (NILP (name))
-    return (unsigned long)FACE_TTY_DEFAULT_COLOR;
+  if (!face->background_defaulted_p)
+    {
+      x_free_colors (f, &face->background, 1);
+      IF_DEBUG (--ncolors_allocated);
+    }
 
-  CHECK_STRING (name, 0);
+  if (face->underline_p
+      && !face->underline_defaulted_p)
+    {
+      x_free_colors (f, &face->underline_color, 1);
+      IF_DEBUG (--ncolors_allocated);
+    }
 
-  color = Qnil;
-  if (XSTRING (name)->size && !NILP (Ffboundp (Qmsdos_color_translate)))
+  if (face->overline_p
+      && !face->overline_color_defaulted_p)
     {
-      color = call1 (Qmsdos_color_translate, name);
+      x_free_colors (f, &face->overline_color, 1);
+      IF_DEBUG (--ncolors_allocated);
+    }
 
-      if (INTEGERP (color))
-       return (unsigned long)XINT (color);
+  if (face->strike_through_p
+      && !face->strike_through_color_defaulted_p)
+    {
+      x_free_colors (f, &face->strike_through_color, 1);
+      IF_DEBUG (--ncolors_allocated);
+    }
 
-      add_to_log (f, "Unable to load color %s", name, Qnil);
-      
-      switch (target_index)
-       {
-       case LFACE_FOREGROUND_INDEX:
-         face->foreground_defaulted_p = 1;
-         color_idx = FRAME_FOREGROUND_PIXEL (f);
-         break;
-         
-       case LFACE_BACKGROUND_INDEX:
-         face->background_defaulted_p = 1;
-         color_idx = FRAME_BACKGROUND_PIXEL (f);
-         break;
-         
-       case LFACE_UNDERLINE_INDEX:
-         face->underline_defaulted_p = 1;
-         color_idx = FRAME_FOREGROUND_PIXEL (f);
-         break;
-         
-       case LFACE_OVERLINE_INDEX:
-         face->overline_color_defaulted_p = 1;
-         color_idx = FRAME_FOREGROUND_PIXEL (f);
-         break;
-         
-       case LFACE_STRIKE_THROUGH_INDEX:
-         face->strike_through_color_defaulted_p = 1;
-         color_idx = FRAME_FOREGROUND_PIXEL (f);
-         break;
-         
-       case LFACE_BOX_INDEX:
-         face->box_color_defaulted_p = 1;
-         color_idx = FRAME_FOREGROUND_PIXEL (f);
-         break;
-       }
+  if (face->box != FACE_NO_BOX
+      && !face->box_color_defaulted_p)
+    {
+      x_free_colors (f, &face->box_color, 1);
+      IF_DEBUG (--ncolors_allocated);
     }
-  else
-    color_idx = msdos_stdcolor_idx (XSTRING (name)->data);
 
-  return (unsigned long)color_idx;
+  UNBLOCK_INPUT;
+#endif /* HAVE_X_WINDOWS */
 }
-#endif /* MSDOS */
-#endif /* ! HAVE_X_WINDOWS */
+
+#endif /* HAVE_WINDOW_SYSTEM */
 
 
 \f
@@ -1474,7 +1640,7 @@ enum xlfd_field
   XLFD_LAST
 };
 
-/* An enumerator for each possible slant value of a font.  Taken from 
+/* An enumerator for each possible slant value of a font.  Taken from
    the XLFD specification.  */
 
 enum xlfd_slant
@@ -1644,7 +1810,7 @@ xlfd_lookup_field_contents (table, dim, font, field_index)
     {
       mid = (low + high) / 2;
       cmp = strcmp (table[mid].name, s);
-      
+
       if (cmp < 0)
        low = mid + 1;
       else if (cmp > 0)
@@ -1689,7 +1855,7 @@ xlfd_symbolic_value (table, dim, font, field_index, dflt)
      int dim;
      struct font_name *font;
      int field_index;
-     int dflt;
+     Lisp_Object dflt;
 {
   struct table_entry *p;
   p = xlfd_lookup_field_contents (table, dim, font, field_index);
@@ -1762,7 +1928,7 @@ xlfd_symbolic_swidth (font)
   return xlfd_symbolic_value (swidth_table, DIM (swidth_table),
                              font, XLFD_SWIDTH, Qnormal);
 }
-     
+
 
 /* Look up the entry of SYMBOL in the vector TABLE which has DIM
    entries.  Value is a pointer to the matching table entry or null if
@@ -1777,7 +1943,7 @@ face_value (table, dim, symbol)
   int i;
 
   xassert (SYMBOLP (symbol));
-  
+
   for (i = 0; i < dim; ++i)
     if (EQ (*table[i].symbol, symbol))
       break;
@@ -1834,7 +2000,7 @@ face_numeric_swidth (width)
 }
 
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 
 /* Return non-zero if FONT is the name of a fixed-pitch font.  */
 
@@ -1879,6 +2045,27 @@ xlfd_point_size (f, font)
 }
 
 
+/* Return point size of PIXEL dots while considering Y-resultion (DPI)
+   of frame F.  This function is used to guess a point size of font
+   when only the pixel height of the font is available.  */
+
+static INLINE int
+pixel_point_size (f, pixel)
+     struct frame *f;
+     int pixel;
+{
+  double resy = FRAME_X_DISPLAY_INFO (f)->resy;
+  double real_pt;
+  int int_pt;
+
+  /* As one inch is 72 points, 72/RESY gives the point size of one dot.  */
+  real_pt = pixel * 72 / resy;
+  int_pt = real_pt + 0.5;
+
+  return int_pt;
+}
+
+
 /* 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,
@@ -1906,13 +2093,13 @@ split_font_name (f, font, numeric_p)
        {
          font->fields[i] = p;
          ++i;
-         
+
          while (*p && *p != '-')
            ++p;
-         
+
          if (*p != '-')
            break;
-         
+
          *p++ = 0;
        }
     }
@@ -1936,7 +2123,7 @@ split_font_name (f, font, numeric_p)
 
 /* Build an XLFD font name from font name fields in FONT.  Value is a
    pointer to the font name, which is allocated via xmalloc.  */
-   
+
 static char *
 build_font_name (font)
      struct font_name *font;
@@ -2013,7 +2200,7 @@ sort_fonts (f, fonts, nfonts, cmpfn)
    For all fonts found, set FONTS[i].name to the name of the font,
    allocated via xmalloc, and split font names into fields.  Ignore
    fonts that we can't parse.  Value is the number of fonts found.
-   
+
    This is similar to x_list_fonts.  The differences are:
 
    1. It avoids consing.
@@ -2028,14 +2215,48 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
      int nfonts, try_alternatives_p;
      int scalable_fonts_p;
 {
-  Display *dpy = f ? FRAME_X_DISPLAY (f) : x_display_list->display;
   int n, i, j;
   char **names;
+#ifdef HAVE_X_WINDOWS
+  Display *dpy = f ? FRAME_X_DISPLAY (f) : x_display_list->display;
 
   /* Get the list of fonts matching PATTERN from the X server.  */
   BLOCK_INPUT;
   names = XListFonts (dpy, pattern, nfonts, &n);
   UNBLOCK_INPUT;
+#endif
+#ifdef WINDOWSNT
+  /* NTEMACS_TODO : currently this uses w32_list_fonts, but it may be
+     better to do it the other way around. */
+  Lisp_Object lfonts;
+  Lisp_Object lpattern, tem;
+
+  n = 0;
+  names = NULL;
+
+  lpattern = build_string (pattern);
+
+  /* Get the list of fonts matching PATTERN.  */
+  BLOCK_INPUT;
+  lfonts = w32_list_fonts (f, lpattern, 0, nfonts);
+  UNBLOCK_INPUT;
+
+  /* Count fonts returned */
+  for (tem = lfonts; CONSP (tem); tem = XCDR (tem))
+    n++;
+
+  /* Allocate array.  */
+  if (n)
+    names = (char **) xmalloc (n * sizeof (char *));
+
+  /* Extract font names into char * array.  */
+  tem = lfonts;
+  for (i = 0; i < n; i++)
+    {
+      names[i] = XSTRING (XCAR (tem))->data;
+      tem = XCDR (tem);
+    }
+#endif
 
   if (names)
     {
@@ -2068,12 +2289,14 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
 
       n = j;
 
+#ifdef HAVE_X_WINDOWS
       /* Free font names.  */
       BLOCK_INPUT;
       XFreeFontNames (names);
       UNBLOCK_INPUT;
+#endif
     }
-  
+
 
   /* If no fonts found, try patterns from Valternate_fontname_alist.  */
   if (n == 0 && try_alternatives_p)
@@ -2094,7 +2317,7 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
        {
          Lisp_Object patterns = XCAR (list);
          Lisp_Object name;
-      
+
          while (CONSP (patterns)
                 /* If list is screwed up, give up.  */
                 && (name = XCAR (patterns),
@@ -2109,10 +2332,10 @@ x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
            patterns = XCDR (patterns);
        }
     }
-  
+
   return n;
 }
-  
+
 
 /* Determine the first font matching PATTERN on frame F.  Return in
    *FONT the matching font name, split into fields.  Value is non-zero
@@ -2133,7 +2356,7 @@ first_font_matching (f, pattern, font)
   if (nfonts > 0)
     {
       bcopy (&fonts[0], font, sizeof *font);
-      
+
       fonts[0].name = NULL;
       free_font_names (fonts, nfonts);
     }
@@ -2158,20 +2381,20 @@ sorted_font_list (f, pattern, cmpfn, fonts)
      struct font_name **fonts;
 {
   int nfonts;
-  
+
   /* 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);
-  
+
   *fonts = (struct font_name *) xmalloc (nfonts * sizeof **fonts);
 #if SCALABLE_FONTS
   nfonts = x_face_list_fonts (f, pattern, *fonts, nfonts, 1, 1);
 #else
   nfonts = x_face_list_fonts (f, pattern, *fonts, nfonts, 1, 0);
 #endif
-  
-  /* Sort the resulting array and return it in *FONTS.  If no 
+
+  /* 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);
@@ -2206,7 +2429,7 @@ cmp_font_names (a, b)
   if (cmp == 0)
     {
       int i;
-      
+
       for (i = 0; i < DIM (font_sort_order) && cmp == 0; ++i)
        {
          int j = font_sort_order[i];
@@ -2229,44 +2452,49 @@ cmp_font_names (a, b)
 
 
 /* Get a sorted list of fonts of family FAMILY on frame F.  If PATTERN
-   is non-null list fonts matching that pattern.  Otherwise, if
-   REGISTRY_AND_ENCODING is non-null return only fonts with that
-   registry and encoding, otherwise return fonts of any registry and
-   encoding.  Set *FONTS to a vector of font_name structures allocated
-   from the heap containing the fonts found.  Value is the number of
-   fonts found.  */
+   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.  */
 
 static int
-font_list (f, pattern, family, registry_and_encoding, fonts)
+font_list (f, pattern, family, registry, fonts)
      struct frame *f;
-     char *pattern;
-     char *family;
-     char *registry_and_encoding;
+     Lisp_Object pattern, family, registry;
      struct font_name **fonts;
 {
-  if (pattern == NULL)
-    {
-      if (family == NULL)
-       family = "*";
-      
-      if (registry_and_encoding == NULL)
-       registry_and_encoding = "*";
-      
-      pattern = (char *) alloca (strlen (family)
-                                + strlen (registry_and_encoding)
-                                + 10);
-      if (index (family, '-'))
-       sprintf (pattern, "-%s-*-%s", family, registry_and_encoding);
-      else
-       sprintf (pattern, "-*-%s-*-%s", family, registry_and_encoding);
+  char *pattern_str, *family_str, *registry_str;
+
+  if (NILP (pattern))
+    {
+      family_str = (NILP (family) ? "*" : (char *) XSTRING (family)->data);
+      registry_str = (NILP (registry) ? "*" : (char *) XSTRING (registry)->data);
+
+      pattern_str = (char *) alloca (strlen (family_str)
+                                    + strlen (registry_str)
+                                    + 10);
+      strcpy (pattern_str, index (family_str, '-') ? "-" : "-*-");
+      strcat (pattern_str, family_str);
+      strcat (pattern_str, "-*-");
+      strcat (pattern_str, registry_str);
+      if (!index (registry_str, '-'))
+       {
+         if (registry_str[strlen (registry_str) - 1] == '*')
+           strcat (pattern_str, "-*");
+         else
+           strcat (pattern_str, "*-*");
+       }
     }
-  
-  return sorted_font_list (f, pattern, cmp_font_names, fonts);
+  else
+    pattern_str = (char *) XSTRING (pattern)->data;
+
+  return sorted_font_list (f, pattern_str, cmp_font_names, fonts);
 }
 
 
 /* Remove elements from LIST whose cars are `equal'.  Called from
-   x-font-list and x-font-family-list to remove duplicate font
+   x-family-fonts and x-font-family-list to remove duplicate font
    entries.  */
 
 static void
@@ -2274,7 +2502,7 @@ remove_duplicates (list)
      Lisp_Object list;
 {
   Lisp_Object tail = list;
-  
+
   while (!NILP (tail) && !NILP (XCDR (tail)))
     {
       Lisp_Object next = XCDR (tail);
@@ -2286,7 +2514,7 @@ remove_duplicates (list)
 }
 
 
-DEFUN ("x-font-list", Fxfont_list, Sx_font_list, 0, 2, 0,
+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\
@@ -2310,26 +2538,18 @@ the face font sort order.")
   int i, nfonts;
   Lisp_Object result;
   struct gcpro gcpro1;
-  char *family_pattern;
 
-  if (NILP (family))
-    family_pattern = "*";
-  else
-    {
-      CHECK_STRING (family, 1);
-      family_pattern = LSTRDUPA (family);
-    }
-  
+  if (!NILP (family))
+    CHECK_STRING (family, 1);
+
   result = Qnil;
   GCPRO1 (result);
-  nfonts = font_list (f, NULL, family_pattern, NULL, &fonts);
+  nfonts = font_list (f, Qnil, family, Qnil, &fonts);
   for (i = nfonts - 1; i >= 0; --i)
     {
       Lisp_Object v = Fmake_vector (make_number (8), Qnil);
       char *tem;
 
-#define ASET(VECTOR, IDX, VAL) (XVECTOR (VECTOR)->contents[IDX] = (VAL))
-      
       ASET (v, 0, build_string (fonts[i].fields[XLFD_FAMILY]));
       ASET (v, 1, xlfd_symbolic_swidth (fonts + i));
       ASET (v, 2, make_number (xlfd_point_size (f, fonts + i)));
@@ -2342,10 +2562,8 @@ the face font sort order.")
               fonts[i].fields[XLFD_ENCODING]);
       ASET (v, 7, build_string (tem));
       xfree (tem);
-      
+
       result = Fcons (v, result);
-      
-#undef ASET
     }
 
   remove_duplicates (result);
@@ -2378,8 +2596,8 @@ are fixed-pitch.")
   for (limit = 500;;)
     {
       specbind (intern ("font-list-limit"), make_number (limit));
-      nfonts = font_list (f, NULL, "*", NULL, &fonts);
-      
+      nfonts = font_list (f, Qnil, Qnil, Qnil, &fonts);
+
       if (nfonts == limit)
        {
          free_font_names (fonts, nfonts);
@@ -2388,7 +2606,7 @@ are fixed-pitch.")
       else
        break;
     }
-  
+
   result = Qnil;
   GCPRO1 (result);
   for (i = nfonts - 1; i >= 0; --i)
@@ -2432,7 +2650,7 @@ the WIDTH times as wide as FACE on FRAME.")
 
   check_x ();
   CHECK_STRING (pattern, 0);
-  
+
   if (NILP (maximum))
     maxnames = 2000;
   else
@@ -2447,7 +2665,7 @@ the WIDTH times as wide as FACE on FRAME.")
   /* We can't simply call check_x_frame because this function may be
      called before any frame is created.  */
   f = frame_or_selected_frame (frame, 2);
-  if (!FRAME_X_P (f))
+  if (!FRAME_WINDOW_P (f))
     {
       /* Perhaps we have not yet created any frame.  */
       f = NULL;
@@ -2462,13 +2680,13 @@ 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, CHARSET_ASCII);
+      int face_id = lookup_named_face (f, face, 0);
       struct face *face = FACE_FROM_ID (f, face_id);
 
       if (face->font)
-       size = face->font->max_bounds.width;
+       size = FONT_WIDTH (face->font);
       else
-       size = FRAME_FONT (f)->max_bounds.width;
+       size = FONT_WIDTH (FRAME_FONT (f));
 
       if (!NILP (width))
        size *= XINT (width);
@@ -2486,7 +2704,7 @@ the WIDTH times as wide as FACE on FRAME.")
   }
 }
 
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
 
 \f
@@ -2522,6 +2740,8 @@ the WIDTH times as wide as FACE on FRAME.")
      XVECTOR (LFACE)->contents[LFACE_STRIKE_THROUGH_INDEX]
 #define LFACE_BOX(LFACE) \
      XVECTOR (LFACE)->contents[LFACE_BOX_INDEX]
+#define LFACE_FONT(LFACE) \
+     XVECTOR (LFACE)->contents[LFACE_FONT_INDEX]
 
 /* 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.  */
@@ -2531,7 +2751,7 @@ the WIDTH times as wide as FACE on FRAME.")
       && XVECTOR (LFACE)->size == LFACE_VECTOR_SIZE    \
       && EQ (XVECTOR (LFACE)->contents[0], Qface))
 
-     
+
 #if GLYPH_DEBUG
 
 /* Check consistency of Lisp face attribute vector ATTRS.  */
@@ -2573,7 +2793,10 @@ check_lface_attrs (attrs)
 #ifdef HAVE_WINDOW_SYSTEM
   xassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
           || SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
-          || !NILP (Fpixmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
+          || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
+  xassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
+          || NILP (attrs[LFACE_FONT_INDEX])
+          || STRINGP (attrs[LFACE_FONT_INDEX]));
 #endif
 }
 
@@ -2599,12 +2822,40 @@ check_lface (lface)
 #endif /* GLYPH_DEBUG == 0 */
 
 
+/* Resolve face name FACE_NAME.  If FACE_NAME is a string, intern it
+   to make it a symvol.  If FACE_NAME is an alias for another face,
+   return that face's name.  */
+
+static Lisp_Object
+resolve_face_name (face_name)
+     Lisp_Object face_name;
+{
+  Lisp_Object aliased;
+
+  if (STRINGP (face_name))
+    face_name = intern (XSTRING (face_name)->data);
+
+  for (;;)
+    {
+      aliased = Fget (face_name, Qface_alias);
+      if (NILP (aliased))
+       break;
+      else
+       face_name = aliased;
+    }
+
+  return face_name;
+}
+
+
 /* Return the face definition of FACE_NAME on frame F.  F null means
    return the global definition.  FACE_NAME may be a string or a
    symbol (apparently Emacs 20.2 allows strings as face names in face
-   text properties; ediff uses that).  If SIGNAL_P is non-zero, signal
-   an error if FACE_NAME is not a valid face name.  If SIGNAL_P is
-   zero, value is nil if FACE_NAME is not a valid face name.  */
+   text properties; ediff uses that).  If FACE_NAME is an alias for
+   another face, return that face's definition.  If SIGNAL_P is
+   non-zero, signal an error if FACE_NAME is not a valid face name.
+   If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
+   name.  */
 
 static INLINE Lisp_Object
 lface_from_face_name (f, face_name, signal_p)
@@ -2614,8 +2865,7 @@ lface_from_face_name (f, face_name, signal_p)
 {
   Lisp_Object lface;
 
-  if (STRINGP (face_name))
-    face_name = intern (XSTRING (face_name)->data);
+  face_name = resolve_face_name (face_name);
 
   if (f)
     lface = assq_no_quit (face_name, f->face_alist);
@@ -2672,102 +2922,113 @@ lface_fully_specified_p (attrs)
   int i;
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-    if (UNSPECIFIEDP (attrs[i]))
+    if (UNSPECIFIEDP (attrs[i]) && i != LFACE_FONT_INDEX)
       break;
 
   return i == LFACE_VECTOR_SIZE;
 }
 
+#ifdef HAVE_WINDOW_SYSTEM
 
-#ifdef HAVE_X_WINDOWS
+/* Set font-related attributes of Lisp face LFACE from the fullname of
+   the font opened by FONTNAME.  If FORCE_P is zero, set only
+   unspecified attributes of LFACE.  The exception is `font'
+   attribute.  It is set to FONTNAME as is regardless of FORCE_P.
+
+   If FONTNAME is not available on frame F,
+       return 0 if MAY_FAIL_P is non-zero, otherwise abort.
+   If the fullname is not in a valid XLFD format,
+       return 0 if MAY_FAIL_P is non-zero, otherwise set normal values
+       in LFACE and return 1.
+   Otherwise, return 1.  */
 
-/* Set font-related attributes of Lisp face LFACE from XLFD font name
-   FONT_NAME.  If FORCE_P is zero, set only unspecified attributes of
-   LFACE.  Ignore fields of FONT_NAME containing wildcards.  Value is
-   zero if not successful because FONT_NAME was not in a valid format.
-   A valid format is one that is suitable for split_font_name, see the
-   comment there.  */
-   
 static int
-set_lface_from_font_name (f, lface, font_name, force_p)
+set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
      struct frame *f;
      Lisp_Object lface;
-     char *font_name;
-     int force_p;
+     Lisp_Object fontname;
+     int force_p, may_fail_p;
 {
   struct font_name font;
   char *buffer;
   int pt;
-  int free_font_name_p = 0;
+  int have_xlfd_p;
+  int fontset;
+  char *font_name = XSTRING (fontname)->data;
+  struct font_info *font_info;
 
-  /* If FONT_NAME contains wildcards, use the first matching font.  */
-  if (index (font_name, '*') || index (font_name, '?'))
+  /* 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;
+
+  /* Check if FONT_NAME is surely available on the system.  Usually
+     FONT_NAME is already cached for the frame F and FS_LOAD_FONT
+     returns quickly.  But, even if FONT_NAME is not yet cached,
+     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);
+  UNBLOCK_INPUT;
+
+  if (!font_info)
     {
-      if (!first_font_matching (f, font_name, &font))
+      if (may_fail_p)
        return 0;
-      free_font_name_p = 1;
-    }
-  else
-    {
-      font.name = STRDUPA (font_name);
-      if (!split_font_name (f, &font, 1))
-       {
-         /* The font name may be something like `6x13'.  Make
-            sure we use the full name.  */
-         struct font_info *font_info;
-
-         BLOCK_INPUT;
-         font_info = fs_load_font (f, FRAME_X_FONT_TABLE (f),
-                                   CHARSET_ASCII, font_name, -1);
-         UNBLOCK_INPUT;
-         
-         if (!font_info)
-           return 0;
-         
-         font.name = STRDUPA (font_info->full_name);
-         split_font_name (f, &font, 1);
-       }
-      
-      /* FONT_NAME should not be a fontset name, here.  */
-      xassert (xstricmp (font.fields[XLFD_REGISTRY], "fontset") != 0);
+      abort ();
     }
 
+  font.name = STRDUPA (font_info->full_name);
+  have_xlfd_p = split_font_name (f, &font, 1);
+
   /* Set attributes only if unspecified, otherwise face defaults for
-     new frames would never take effect.  */
-  
+     new frames would never take effect.  If we couldn't get a font
+     name conforming to XLFD, set normal values.  */
+
   if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
     {
-      buffer = (char *) alloca (strlen (font.fields[XLFD_FAMILY])
-                               + strlen (font.fields[XLFD_FOUNDRY])
-                               + 2);
-      sprintf (buffer, "%s-%s", font.fields[XLFD_FOUNDRY],
-              font.fields[XLFD_FAMILY]);
-      LFACE_FAMILY (lface) = build_string (buffer);
+      Lisp_Object val;
+      if (have_xlfd_p)
+       {
+         buffer = (char *) alloca (strlen (font.fields[XLFD_FAMILY])
+                                   + strlen (font.fields[XLFD_FOUNDRY])
+                                   + 2);
+         sprintf (buffer, "%s-%s", font.fields[XLFD_FOUNDRY],
+                  font.fields[XLFD_FAMILY]);
+         val = build_string (buffer);
+       }
+      else
+       val = build_string ("*");
+      LFACE_FAMILY (lface) = val;
     }
 
   if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
     {
-      pt = xlfd_point_size (f, &font);
+      if (have_xlfd_p)
+       pt = xlfd_point_size (f, &font);
+      else
+       pt = pixel_point_size (f, font_info->height * 10);
       xassert (pt > 0);
       LFACE_HEIGHT (lface) = make_number (pt);
     }
 
   if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
-    LFACE_SWIDTH (lface) = xlfd_symbolic_swidth (&font);
+    LFACE_SWIDTH (lface)
+      = have_xlfd_p ? xlfd_symbolic_swidth (&font) : Qnormal;
 
   if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
-    LFACE_WEIGHT (lface) = xlfd_symbolic_weight (&font);
+    LFACE_WEIGHT (lface)
+      = have_xlfd_p ? xlfd_symbolic_weight (&font) : Qnormal;
 
   if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
-    LFACE_SLANT (lface) = xlfd_symbolic_slant (&font);
+    LFACE_SLANT (lface)
+      = have_xlfd_p ? xlfd_symbolic_slant (&font) : Qnormal;
+
+  LFACE_FONT (lface) = fontname;
 
-  if (free_font_name_p)
-    xfree (font.name);
-  
   return 1;
 }
-
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
 
 /* Merge two Lisp face attribute vectors FROM and TO and store the
@@ -2803,7 +3064,7 @@ merge_face_vectors (from, to)
 
    Face specifications earlier in lists take precedence over later
    specifications.  */
-   
+
 static void
 merge_face_vector_with_property (f, to, prop)
      struct frame *f;
@@ -2813,7 +3074,7 @@ merge_face_vector_with_property (f, to, prop)
   if (CONSP (prop))
     {
       Lisp_Object first = XCAR (prop);
-      
+
       if (EQ (first, Qforeground_color)
          || EQ (first, Qbackground_color))
        {
@@ -2830,7 +3091,7 @@ merge_face_vector_with_property (f, to, prop)
                to[LFACE_BACKGROUND_INDEX] = color_name;
            }
          else
-           add_to_log (f, "Invalid face color", color_name, Qnil);
+           add_to_log ("Invalid face color", color_name, Qnil);
        }
       else if (SYMBOLP (first)
               && *XSYMBOL (first)->name->data == ':')
@@ -2846,14 +3107,14 @@ merge_face_vector_with_property (f, to, prop)
                  if (STRINGP (value))
                    to[LFACE_FAMILY_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face font family", value, Qnil);
+                   add_to_log ("Invalid face font family", value, Qnil);
                }
              else if (EQ (keyword, QCheight))
                {
                  if (INTEGERP (value))
                    to[LFACE_HEIGHT_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face font height", value, Qnil);
+                   add_to_log ("Invalid face font height", value, Qnil);
                }
              else if (EQ (keyword, QCweight))
                {
@@ -2861,7 +3122,7 @@ merge_face_vector_with_property (f, to, prop)
                      && face_numeric_weight (value) >= 0)
                    to[LFACE_WEIGHT_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face weight", value, Qnil);
+                   add_to_log ("Invalid face weight", value, Qnil);
                }
              else if (EQ (keyword, QCslant))
                {
@@ -2869,7 +3130,7 @@ merge_face_vector_with_property (f, to, prop)
                      && face_numeric_slant (value) >= 0)
                    to[LFACE_SLANT_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face slant", value, Qnil);
+                   add_to_log ("Invalid face slant", value, Qnil);
                }
              else if (EQ (keyword, QCunderline))
                {
@@ -2878,7 +3139,7 @@ merge_face_vector_with_property (f, to, prop)
                      || STRINGP (value))
                    to[LFACE_UNDERLINE_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face underline", value, Qnil);
+                   add_to_log ("Invalid face underline", value, Qnil);
                }
              else if (EQ (keyword, QCoverline))
                {
@@ -2887,7 +3148,7 @@ merge_face_vector_with_property (f, to, prop)
                      || STRINGP (value))
                    to[LFACE_OVERLINE_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face overline", value, Qnil);
+                   add_to_log ("Invalid face overline", value, Qnil);
                }
              else if (EQ (keyword, QCstrike_through))
                {
@@ -2896,7 +3157,7 @@ merge_face_vector_with_property (f, to, prop)
                      || STRINGP (value))
                    to[LFACE_STRIKE_THROUGH_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face strike-through", value, Qnil);
+                   add_to_log ("Invalid face strike-through", value, Qnil);
                }
              else if (EQ (keyword, QCbox))
                {
@@ -2908,7 +3169,7 @@ merge_face_vector_with_property (f, to, prop)
                      || NILP (value))
                    to[LFACE_BOX_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face box", value, Qnil);
+                   add_to_log ("Invalid face box", value, Qnil);
                }
              else if (EQ (keyword, QCinverse_video)
                       || EQ (keyword, QCreverse_video))
@@ -2916,30 +3177,30 @@ merge_face_vector_with_property (f, to, prop)
                  if (EQ (value, Qt) || NILP (value))
                    to[LFACE_INVERSE_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face inverse-video", value, Qnil);
+                   add_to_log ("Invalid face inverse-video", value, Qnil);
                }
              else if (EQ (keyword, QCforeground))
                {
                  if (STRINGP (value))
                    to[LFACE_FOREGROUND_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face foreground", value, Qnil);
+                   add_to_log ("Invalid face foreground", value, Qnil);
                }
              else if (EQ (keyword, QCbackground))
                {
                  if (STRINGP (value))
                    to[LFACE_BACKGROUND_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face background", value, Qnil);
+                   add_to_log ("Invalid face background", value, Qnil);
                }
              else if (EQ (keyword, QCstipple))
                {
 #ifdef HAVE_X_WINDOWS
-                 Lisp_Object pixmap_p = Fpixmap_spec_p (value);
+                 Lisp_Object pixmap_p = Fbitmap_spec_p (value);
                  if (!NILP (pixmap_p))
                    to[LFACE_STIPPLE_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face stipple", value, Qnil);
+                   add_to_log ("Invalid face stipple", value, Qnil);
 #endif
                }
              else if (EQ (keyword, QCwidth))
@@ -2948,10 +3209,10 @@ merge_face_vector_with_property (f, to, prop)
                      && face_numeric_swidth (value) >= 0)
                    to[LFACE_SWIDTH_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face width", value, Qnil);
+                   add_to_log ("Invalid face width", value, Qnil);
                }
              else
-               add_to_log (f, "Invalid attribute %s in face property",
+               add_to_log ("Invalid attribute %s in face property",
                            keyword, Qnil);
 
              prop = XCDR (XCDR (prop));
@@ -2974,7 +3235,7 @@ merge_face_vector_with_property (f, to, prop)
       /* PROP ought to be a face name.  */
       Lisp_Object lface = lface_from_face_name (f, prop, 0);
       if (NILP (lface))
-       add_to_log (f, "Invalid face text property value: %s", prop, Qnil);
+       add_to_log ("Invalid face text property value: %s", prop, Qnil);
       else
        merge_face_vectors (XVECTOR (lface)->contents, to);
     }
@@ -2997,7 +3258,7 @@ Value is a vector of face attributes.")
 
   CHECK_SYMBOL (face, 0);
   global_lface = lface_from_face_name (NULL, face, 0);
-  
+
   if (!NILP (frame))
     {
       CHECK_LIVE_FRAME (frame, 1);
@@ -3013,9 +3274,9 @@ Value is a vector of face attributes.")
       global_lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
                                   Qunspecified);
       XVECTOR (global_lface)->contents[0] = Qface;
-      Vface_new_frame_defaults = Fcons (Fcons (face, global_lface), 
+      Vface_new_frame_defaults = Fcons (Fcons (face, global_lface),
                                        Vface_new_frame_defaults);
-      
+
       /* Assign the new Lisp face a unique ID.  The mapping from Lisp
         face id to Lisp face is given by the vector lface_id_to_name.
         The mapping from Lisp face to Lisp face id is given by the
@@ -3027,7 +3288,7 @@ Value is a vector of face attributes.")
          lface_id_to_name = (Lisp_Object *) xrealloc (lface_id_to_name, sz);
          lface_id_to_name_size = new_size;
        }
-      
+
       lface_id_to_name[next_lface_id] = face;
       Fput (face, Qface, make_number (next_lface_id));
       ++next_lface_id;
@@ -3035,7 +3296,7 @@ Value is a vector of face attributes.")
   else if (f == NULL)
     for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
       XVECTOR (global_lface)->contents[i] = Qunspecified;
-    
+
   /* Add a frame-local definition.  */
   if (f)
     {
@@ -3069,7 +3330,7 @@ Otherwise check for the existence of a global face.")
      Lisp_Object face, frame;
 {
   Lisp_Object lface;
-  
+
   if (!NILP (frame))
     {
       CHECK_LIVE_FRAME (frame, 1);
@@ -3095,7 +3356,7 @@ Value is TO.")
      Lisp_Object from, to, frame, new_frame;
 {
   Lisp_Object lface, copy;
-  
+
   CHECK_SYMBOL (from, 0);
   CHECK_SYMBOL (to, 1);
   if (NILP (new_frame))
@@ -3116,10 +3377,10 @@ Value is TO.")
       lface = lface_from_face_name (XFRAME (frame), from, 1);
       copy = Finternal_make_lisp_face (to, new_frame);
     }
-  
+
   bcopy (XVECTOR (lface)->contents, XVECTOR (copy)->contents,
         LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
-  
+
   return to;
 }
 
@@ -3136,22 +3397,27 @@ frame.")
 {
   Lisp_Object lface;
   Lisp_Object old_value = Qnil;
+  /* Set 1 if ATTR is QCfont.  */
+  int font_attr_p = 0;
+  /* 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);
 
+  face = resolve_face_name (face);
+
   /* Set lface to the Lisp attribute vector of FACE.  */
   if (EQ (frame, Qt))
     lface = lface_from_face_name (NULL, face, 1);
   else
     {
       if (NILP (frame))
-       XSETFRAME (frame, selected_frame);
-      
+       frame = selected_frame;
+
       CHECK_LIVE_FRAME (frame, 3);
       lface = lface_from_face_name (XFRAME (frame), face, 0);
-      
+
       /* If a frame-local face doesn't exist yet, create one.  */
       if (NILP (lface))
        lface = Finternal_make_lisp_face (face, frame);
@@ -3215,7 +3481,7 @@ frame.")
            || (STRINGP (value)
                && XSTRING (value)->size == 0))
          signal_error ("Invalid face underline", value);
-      
+
       old_value = LFACE_UNDERLINE (lface);
       LFACE_UNDERLINE (lface) = value;
     }
@@ -3229,7 +3495,7 @@ frame.")
            || (STRINGP (value)
                && XSTRING (value)->size == 0))
          signal_error ("Invalid face overline", value);
-      
+
       old_value = LFACE_OVERLINE (lface);
       LFACE_OVERLINE (lface) = value;
     }
@@ -3243,14 +3509,14 @@ frame.")
            || (STRINGP (value)
                && XSTRING (value)->size == 0))
          signal_error ("Invalid face strike-through", value);
-      
+
       old_value = LFACE_STRIKE_THROUGH (lface);
       LFACE_STRIKE_THROUGH (lface) = value;
     }
   else if (EQ (attr, QCbox))
     {
       int valid_p;
-      
+
       /* Allow t meaning a simple box of width 1 in foreground color
          of the face.  */
       if (EQ (value, Qt))
@@ -3267,7 +3533,7 @@ frame.")
       else if (CONSP (value))
        {
          Lisp_Object tem;
-         
+
          tem = value;
          while (CONSP (tem))
            {
@@ -3279,7 +3545,7 @@ frame.")
                break;
              v = XCAR (tem);
              tem = XCDR (tem);
-             
+
              if (EQ (k, QCline_width))
                {
                  if (!INTEGERP (v) || XINT (v) <= 0)
@@ -3306,7 +3572,7 @@ frame.")
 
       if (!valid_p)
        signal_error ("Invalid face box", value);
-      
+
       old_value = LFACE_BOX (lface);
       LFACE_BOX (lface) = value;
     }
@@ -3355,7 +3621,7 @@ frame.")
 #ifdef HAVE_X_WINDOWS
       if (!UNSPECIFIEDP (value)
          && !NILP (value)
-         && NILP (Fpixmap_spec_p (value)))
+         && NILP (Fbitmap_spec_p (value)))
        signal_error ("Invalid stipple attribute", value);
       old_value = LFACE_STIPPLE (lface);
       LFACE_STIPPLE (lface) = value;
@@ -3375,22 +3641,29 @@ frame.")
     }
   else if (EQ (attr, QCfont))
     {
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
       /* Set font-related attributes of the Lisp face from an
         XLFD font name.  */
       struct frame *f;
+      Lisp_Object tmp;
 
       CHECK_STRING (value, 3);
       if (EQ (frame, Qt))
-       f = selected_frame;
+       f = SELECTED_FRAME ();
       else
        f = check_x_frame (frame);
-      
-      if (!set_lface_from_font_name (f, lface, XSTRING (value)->data, 1))
-       signal_error ("Invalid font name", value);
-      
-      font_related_attr_p = 1;
-#endif /* HAVE_X_WINDOWS */
+
+      /* VALUE may be a fontset name or an alias of fontset.  In such
+         a case, use the base fontset name.  */
+      tmp = Fquery_fontset (value, Qnil);
+      if (!NILP (tmp))
+       value = tmp;
+
+      if (!set_lface_from_font_name (f, lface, value, 1, 1))
+       signal_error ("Invalid font or fontset name", value);
+
+      font_attr_p = 1;
+#endif /* HAVE_WINDOW_SYSTEM */
     }
   else if (EQ (attr, QCbold))
     {
@@ -3407,6 +3680,14 @@ frame.")
   else
     signal_error ("Invalid face attribute name", attr);
 
+  if (font_related_attr_p
+      && !UNSPECIFIEDP (value))
+    /* If a font-related attribute other than QCfont is specified, the
+       original `font' attribute nor that of default face is useless
+       to determine a new font.  Thus, we set it to nil so that font
+       selection mechanism doesn't use it.  */
+    LFACE_FONT (lface) = Qnil;
+
   /* 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
@@ -3420,72 +3701,159 @@ frame.")
       ++windows_or_buffers_changed;
     }
 
-#ifdef HAVE_X_WINDOWS
-  /* Changed font-related attributes of the `default' face are
-     reflected in changed `font' frame parameters.  */
-  if (EQ (face, Qdefault)
-      && !EQ (frame, Qt)
-      && font_related_attr_p
-      && lface_fully_specified_p (XVECTOR (lface)->contents)
+#ifdef HAVE_WINDOW_SYSTEM
+
+  if (!EQ (frame, Qt)
+      && !UNSPECIFIEDP (value)
       && NILP (Fequal (old_value, value)))
-    set_font_frame_param (frame, lface);
+    {
+      Lisp_Object param;
+
+      param = Qnil;
+
+      if (EQ (face, Qdefault))
+       {
+         /* Changed font-related attributes of the `default' face are
+            reflected in changed `font' frame parameters. */
+         if ((font_related_attr_p || font_attr_p)
+             && lface_fully_specified_p (XVECTOR (lface)->contents))
+           set_font_frame_param (frame, lface);
+         else if (EQ (attr, QCforeground))
+           param = Qforeground_color;
+         else if (EQ (attr, QCbackground))
+           param = Qbackground_color;
+       }
+#ifndef WINDOWSNT
+      else if (EQ (face, Qscroll_bar))
+       {
+         /* Changing the colors of `scroll-bar' sets frame parameters
+            `scroll-bar-foreground' and `scroll-bar-background'. */
+         if (EQ (attr, QCforeground))
+           param = Qscroll_bar_foreground;
+         else if (EQ (attr, QCbackground))
+           param = Qscroll_bar_background;
+       }
+#endif
+      else if (EQ (face, Qborder))
+       {
+         /* Changing background color of `border' sets frame parameter
+            `border-color'.  */
+         if (EQ (attr, QCbackground))
+           param = Qborder_color;
+       }
+      else if (EQ (face, Qcursor))
+       {
+         /* Changing background color of `cursor' sets frame parameter
+            `cursor-color'.  */
+         if (EQ (attr, QCbackground))
+           param = Qcursor_color;
+       }
+      else if (EQ (face, Qmouse))
+       {
+         /* Changing background color of `mouse' sets frame parameter
+            `mouse-color'.  */
+         if (EQ (attr, QCbackground))
+           param = Qmouse_color;
+       }
+
+      if (!NILP (param))
+       Fmodify_frame_parameters (frame, Fcons (Fcons (param, value), Qnil));
+    }
+
+#endif /* HAVE_WINDOW_SYSTEM */
 
-#endif /* HAVE_X_WINDOWS */
-  
   return face;
 }
 
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 
-/* Set the `font' frame parameter of FRAME according to `default' face
-   attributes LFACE.  */
+/* Set the `font' frame parameter of FRAME determined from `default'
+   face attributes LFACE.  If a face or fontset 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.  */
 
 static void
 set_font_frame_param (frame, lface)
      Lisp_Object frame, lface;
 {
   struct frame *f = XFRAME (frame);
-  Lisp_Object frame_font;
-  int fontset;
+  Lisp_Object font_name;
   char *font;
 
-  /* Get FRAME's font parameter.  */
-  frame_font = Fassq (Qfont, f->param_alist);
-  xassert (CONSP (frame_font) && STRINGP (XCDR (frame_font)));
-  frame_font = XCDR (frame_font);
+  if (STRINGP (LFACE_FONT (lface)))
+    font_name = LFACE_FONT (lface);
+  else
+    {
+      /* Choose a font name that reflects LFACE's attributes and has
+        the registry and encoding pattern specified in the default
+        fontset (3rd arg: -1) for ASCII characters (4th arg: 0).  */
+      font = choose_face_font (f, XVECTOR (lface)->contents, -1, 0);
+      if (!font)
+       error ("No font matches the specified attribute");
+      font_name = build_string (font);
+      xfree (font);
+    }
+  store_frame_param (f, Qfont, font_name);
+}
+
 
-  fontset = fs_query_fontset (f, XSTRING (frame_font)->data);
-  if (fontset >= 0)
+/* Update the corresponding face when frame parameter PARAM on frame F
+   has been assigned the value NEW_VALUE.  */
+
+void
+update_face_from_frame_parameter (f, param, new_value)
+     struct frame *f;
+     Lisp_Object param, new_value;
+{
+  Lisp_Object lface;
+
+  /* If there are no faces yet, give up.  This is the case when called
+     from Fx_create_frame, and we do the necessary things later in
+     face-set-after-frame-defaults.  */
+  if (NILP (f->face_alist))
+    return;
+
+  if (EQ (param, Qforeground_color))
     {
-      /* Frame parameter is a fontset name.  Modify the fontset so
-         that all its fonts reflect face attributes LFACE.  */
-      int charset;
-      struct fontset_info *fontset_info;
+      lface = lface_from_face_name (f, Qdefault, 1);
+      LFACE_FOREGROUND (lface) = (STRINGP (new_value)
+                                 ? new_value : Qunspecified);
+      realize_basic_faces (f);
+    }
+  else if (EQ (param, Qbackground_color))
+    {
+      Lisp_Object frame;
 
-      fontset_info = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-      
-      for (charset = 0; charset < MAX_CHARSET; ++charset)
-       if (fontset_info->fontname[charset])
-         {
-           font = choose_face_fontset_font (f, XVECTOR (lface)->contents,
-                                            fontset, charset);
-           Fset_fontset_font (frame_font, CHARSET_SYMBOL (charset),
-                              build_string (font), frame);
-           xfree (font);
-         }
+      /* Changing the background color might change the background
+        mode, so that we have to load new defface specs.  Call
+        frame-update-face-colors to do that.  */
+      XSETFRAME (frame, f);
+      call1 (Qframe_update_face_colors, frame);
+
+      lface = lface_from_face_name (f, Qdefault, 1);
+      LFACE_BACKGROUND (lface) = (STRINGP (new_value)
+                                 ? new_value : Qunspecified);
+      realize_basic_faces (f);
     }
-  else
+  if (EQ (param, Qborder_color))
     {
-      /* Frame parameter is an X font name.  I believe this can 
-         only happen in unibyte mode.  */
-      font = choose_face_font (f, XVECTOR (lface)->contents,
-                              -1, Vface_default_registry);
-      if (font)
-       {
-         store_frame_param (f, Qfont, build_string (font));
-         xfree (font);
-       }
+      lface = lface_from_face_name (f, Qborder, 1);
+      LFACE_BACKGROUND (lface) = (STRINGP (new_value)
+                                 ? new_value : Qunspecified);
+    }
+  else if (EQ (param, Qcursor_color))
+    {
+      lface = lface_from_face_name (f, Qcursor, 1);
+      LFACE_BACKGROUND (lface) = (STRINGP (new_value)
+                                 ? new_value : Qunspecified);
+    }
+  else if (EQ (param, Qmouse_color))
+    {
+      lface = lface_from_face_name (f, Qmouse, 1);
+      LFACE_BACKGROUND (lface) = (STRINGP (new_value)
+                                 ? new_value : Qunspecified);
     }
 }
 
@@ -3499,7 +3867,8 @@ DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
   (resource, class, frame)
      Lisp_Object resource, class, frame;
 {
-  Lisp_Object value;
+  Lisp_Object value = Qnil;
+#ifndef WINDOWSNT
   CHECK_STRING (resource, 0);
   CHECK_STRING (class, 1);
   CHECK_LIVE_FRAME (frame, 2);
@@ -3507,6 +3876,7 @@ DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
   value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
                                  resource, class, Qnil, Qnil);
   UNBLOCK_INPUT;
+#endif
   return value;
 }
 
@@ -3515,7 +3885,7 @@ DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
    If VALUE is "on" or "true", return t.  If VALUE is "off" or
    "false", return nil.  Otherwise, if SIGNAL_P is non-zero, signal an
    error; if SIGNAL_P is zero, return 0.  */
-   
+
 static Lisp_Object
 face_boolean_x_resource_value (value, signal_p)
      Lisp_Object value;
@@ -3524,7 +3894,7 @@ face_boolean_x_resource_value (value, signal_p)
   Lisp_Object result = make_number (0);
 
   xassert (STRINGP (value));
-  
+
   if (xstricmp (XSTRING (value)->data, "on") == 0
       || xstricmp (XSTRING (value)->data, "true") == 0)
     result = Qt;
@@ -3582,6 +3952,221 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
   return Finternal_set_lisp_face_attribute (face, attr, value, frame);
 }
 
+#endif /* HAVE_WINDOW_SYSTEM */
+
+\f
+#ifdef HAVE_X_WINDOWS
+/***********************************************************************
+                             Menu face
+ ***********************************************************************/
+
+#ifdef USE_X_TOOLKIT
+
+#include "../lwlib/lwlib-utils.h"
+
+/* Structure used to pass X resources to functions called via
+   XtApplyToWidgets.  */
+
+struct x_resources
+{
+  Arg *av;
+  int ac;
+};
+
+
+#ifdef USE_MOTIF
+
+static void xm_apply_resources P_ ((Widget, XtPointer));
+static void xm_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
+
+
+/* Set widget W's X resources from P which points to an x_resources
+   structure.  If W is a cascade button, apply resources to W's
+   submenu.  */
+
+static void
+xm_apply_resources (w, p)
+     Widget w;
+     XtPointer p;
+{
+  Widget submenu = 0;
+  struct x_resources *res = (struct x_resources *) p;
+
+  XtSetValues (w, res->av, res->ac);
+  XtVaGetValues (w, XmNsubMenuId, &submenu, NULL);
+  if (submenu)
+    {
+      XtSetValues (submenu, res->av, res->ac);
+      XtApplyToWidgets (submenu, xm_apply_resources, p);
+    }
+}
+
+
+/* Set X resources of menu-widget WIDGET on frame F from face `menu'.
+   This is the LessTif/Motif version.  As of LessTif 0.88 it has the
+   following problems:
+
+   1. Setting the XmNfontList resource leads to an infinite loop
+   somewhere in LessTif.  */
+
+static void
+xm_set_menu_resources_from_menu_face (f, widget)
+     struct frame *f;
+     Widget widget;
+{
+  struct face *face;
+  Lisp_Object lface;
+  Arg av[3];
+  int ac = 0;
+  XmFontList fl = 0;
+
+  lface = lface_from_face_name (f, Qmenu, 1);
+  face = FACE_FROM_ID (f, MENU_FACE_ID);
+
+  if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
+    {
+      XtSetArg (av[ac], XmNforeground, face->foreground);
+      ++ac;
+    }
+
+  if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
+    {
+      XtSetArg (av[ac], XmNbackground, face->background);
+      ++ac;
+    }
+
+  /* If any font-related attribute of `menu' is set, set the font.  */
+  if (face->font
+      && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
+         || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+         || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
+         || !UNSPECIFIEDP (LFACE_SLANT (lface))
+         || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
+    {
+#if 0 /* Setting the font leads to an infinite loop somewhere
+        in LessTif during geometry computation.  */
+      XmFontListEntry fe;
+      fe = XmFontListEntryCreate ("menu_font", XmFONT_IS_FONT, face->font);
+      fl = XmFontListAppendEntry (NULL, fe);
+      XtSetArg (av[ac], XmNfontList, fl);
+      ++ac;
+#endif
+    }
+
+  xassert (ac <= sizeof av / sizeof *av);
+
+  if (ac)
+    {
+      struct x_resources res;
+
+      XtSetValues (widget, av, ac);
+      res.av = av, res.ac = ac;
+      XtApplyToWidgets (widget, xm_apply_resources, &res);
+      if (fl)
+       XmFontListFree (fl);
+    }
+}
+
+
+#endif /* USE_MOTIF */
+
+#ifdef USE_LUCID
+
+static void xl_apply_resources P_ ((Widget, XtPointer));
+static void xl_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
+
+
+/* Set widget W's resources from P which points to an x_resources
+   structure.  */
+
+static void
+xl_apply_resources (widget, p)
+     Widget widget;
+     XtPointer p;
+{
+  struct x_resources *res = (struct x_resources *) p;
+  XtSetValues (widget, res->av, res->ac);
+}
+
+
+/* On frame F, set X resources of menu-widget WIDGET from face `menu'.
+   This is the Lucid version.  */
+
+static void
+xl_set_menu_resources_from_menu_face (f, widget)
+     struct frame *f;
+     Widget widget;
+{
+  struct face *face;
+  Lisp_Object lface;
+  Arg av[3];
+  int ac = 0;
+
+  lface = lface_from_face_name (f, Qmenu, 1);
+  face = FACE_FROM_ID (f, MENU_FACE_ID);
+
+  if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
+    {
+      XtSetArg (av[ac], XtNforeground, face->foreground);
+      ++ac;
+    }
+
+  if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
+    {
+      XtSetArg (av[ac], XtNbackground, face->background);
+      ++ac;
+    }
+
+  if (face->font
+      && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
+         || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+         || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
+         || !UNSPECIFIEDP (LFACE_SLANT (lface))
+         || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
+    {
+      XtSetArg (av[ac], XtNfont, face->font);
+      ++ac;
+    }
+
+  if (ac)
+    {
+      struct x_resources res;
+
+      XtSetValues (widget, av, ac);
+
+      /* We must do children here in case we're handling a pop-up menu
+        in which case WIDGET is a popup shell.  XtApplyToWidgets
+        is a function from lwlib.  */
+      res.av = av, res.ac = ac;
+      XtApplyToWidgets (widget, xl_apply_resources, &res);
+    }
+}
+
+#endif /* USE_LUCID */
+
+
+/* On frame F, set X resources of menu-widget WIDGET from face `menu'.  */
+
+void
+x_set_menu_resources_from_menu_face (f, widget)
+     struct frame *f;
+     Widget widget;
+{
+  /* Realized faces may have been removed on frame F, e.g. because of
+     face attribute changes.  Recompute them, if necessary, since we
+     will need the `menu' face.  */
+  if (f->face_cache->used == 0)
+    recompute_basic_faces (f);
+
+#ifdef USE_LUCID
+  xl_set_menu_resources_from_menu_face (f, widget);
+#endif
+#ifdef USE_MOTIF
+  xm_set_menu_resources_from_menu_face (f, widget);
+#endif
+}
+
+#endif /* USE_X_TOOLKIT */
 
 #endif /* HAVE_X_WINDOWS */
 
@@ -3600,7 +4185,7 @@ frames).  If FRAME is omitted or nil, use the selected frame.")
      Lisp_Object symbol, keyword, frame;
 {
   Lisp_Object lface, value = Qnil;
-  
+
   CHECK_SYMBOL (symbol, 0);
   CHECK_SYMBOL (keyword, 1);
 
@@ -3609,7 +4194,7 @@ frames).  If FRAME is omitted or nil, use the selected frame.")
   else
     {
       if (NILP (frame))
-       XSETFRAME (frame, selected_frame);
+       frame = selected_frame;
       CHECK_LIVE_FRAME (frame, 2);
       lface = lface_from_face_name (XFRAME (frame), symbol, 1);
     }
@@ -3641,6 +4226,8 @@ frames).  If FRAME is omitted or nil, use the selected frame.")
     value = LFACE_STIPPLE (lface);
   else if (EQ (keyword, QCwidth))
     value = LFACE_SWIDTH (lface);
+  else if (EQ (keyword, QCfont))
+    value = LFACE_FONT (lface);
   else
     signal_error ("Invalid face attribute name", keyword);
 
@@ -3657,9 +4244,9 @@ Value is nil if ATTR doesn't have a discrete set of valid values.")
      Lisp_Object attr;
 {
   Lisp_Object result = Qnil;
-  
+
   CHECK_SYMBOL (attr, 0);
-  
+
   if (EQ (attr, QCweight)
       || EQ (attr, QCslant)
       || EQ (attr, QCwidth))
@@ -3667,7 +4254,7 @@ Value is nil if ATTR doesn't have a discrete set of valid values.")
       /* Extract permissible symbols from tables.  */
       struct table_entry *table;
       int i, dim;
-      
+
       if (EQ (attr, QCweight))
        table = weight_table, dim = DIM (weight_table);
       else if (EQ (attr, QCslant))
@@ -3699,10 +4286,10 @@ Value is nil if ATTR doesn't have a discrete set of valid values.")
 
   return result;
 }
-  
+
 
 DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
-       Sinternal_merge_in_global_face, 2, 2, 0, 
+       Sinternal_merge_in_global_face, 2, 2, 0,
   "Add attributes from frame-default definition of FACE to FACE on FRAME.")
   (face, frame)
      Lisp_Object face, frame;
@@ -3724,7 +4311,7 @@ DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
    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, 
+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\
@@ -3742,17 +4329,17 @@ If FRAME is omitted or nil, use the selected frame.")
       if (!UNSPECIFIEDP (LFACE_WEIGHT (lface))
          && !EQ (LFACE_WEIGHT (lface), Qnormal))
        result = Fcons (Qbold, result);
-      
+
       if (!NILP (LFACE_SLANT (lface))
          && !EQ (LFACE_SLANT (lface), Qnormal))
        result = Fcons (Qitalic, result);
-      
+
       return result;
     }
   else
     {
       struct frame *f = frame_or_selected_frame (frame, 1);
-      int face_id = lookup_named_face (f, face, CHARSET_ASCII);
+      int face_id = lookup_named_face (f, face, 0);
       struct face *face = FACE_FROM_ID (f, face_id);
       return build_string (face->font_name);
     }
@@ -3789,19 +4376,19 @@ lface_equal_p (v1, v2)
                         && bcmp (XSTRING (a)->data, XSTRING (b)->data,
                                  XSTRING (a)->size) == 0);
              break;
-         
+
            case Lisp_Int:
            case Lisp_Symbol:
              equal_p = 0;
              break;
-         
+
            default:
              equal_p = !NILP (Fequal (a, b));
              break;
            }
        }
     }
-         
+
   return equal_p;
 }
 
@@ -3818,7 +4405,7 @@ If FRAME is omitted or nil, use the selected frame.")
   int equal_p;
   struct frame *f;
   Lisp_Object lface1, lface2;
-  
+
   if (EQ (frame, Qt))
     f = NULL;
   else
@@ -3835,7 +4422,7 @@ If FRAME is omitted or nil, use the selected frame.")
   return equal_p ? Qt : Qnil;
 }
 
-  
+
 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\
@@ -3850,13 +4437,10 @@ If FRAME is omitted or nil, use the selected frame.")
   int i;
 
   if (NILP (frame))
-    f = selected_frame;
-  else
-    {
-      CHECK_LIVE_FRAME (frame, 0);
-      f = XFRAME (frame);
-    }
-  
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame, 0);
+  f = XFRAME (frame);
+
   if (EQ (frame, Qt))
     lface = lface_from_face_name (NULL, face, 1);
   else
@@ -3865,13 +4449,13 @@ If FRAME is omitted or nil, use the selected frame.")
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (!UNSPECIFIEDP (XVECTOR (lface)->contents[i]))
       break;
-  
+
   return i == LFACE_VECTOR_SIZE ? Qt : Qnil;
 }
 
 
 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist,
-       0, 1, 0, 
+       0, 1, 0,
   "Return an alist of frame-local faces defined on FRAME.\n\
 For internal use only.")
   (frame)
@@ -3907,17 +4491,17 @@ lface_hash (v)
   return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
          ^ hash_string_case_insensitive (v[LFACE_FOREGROUND_INDEX])
          ^ hash_string_case_insensitive (v[LFACE_BACKGROUND_INDEX])
-         ^ (unsigned) v[LFACE_WEIGHT_INDEX]
-         ^ (unsigned) v[LFACE_SLANT_INDEX]
-         ^ (unsigned) v[LFACE_SWIDTH_INDEX]
+         ^ XFASTINT (v[LFACE_WEIGHT_INDEX])
+         ^ XFASTINT (v[LFACE_SLANT_INDEX])
+         ^ XFASTINT (v[LFACE_SWIDTH_INDEX])
          ^ XFASTINT (v[LFACE_HEIGHT_INDEX]));
 }
 
 
 /* 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 and slant.  Both LFACE1 and
-   LFACE2 must be fully-specified.  */
+   family, point size, weight, width, slant, and fontset.  Both LFACE1
+   and LFACE2 must be fully-specified.  */
 
 static INLINE int
 lface_same_font_attributes_p (lface1, lface2)
@@ -3931,7 +4515,12 @@ lface_same_font_attributes_p (lface1, lface2)
              == XFASTINT (lface2[LFACE_HEIGHT_INDEX]))
          && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
          && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
-         && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX]));
+         && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX])
+         && (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))));
 }
 
 
@@ -3941,18 +4530,15 @@ lface_same_font_attributes_p (lface1, lface2)
  ***********************************************************************/
 
 /* Allocate and return a new realized face for Lisp face attribute
-   vector ATTR, charset CHARSET, and registry REGISTRY.  */
+   vector ATTR.  */
 
 static struct face *
-make_realized_face (attr, charset, registry)
+make_realized_face (attr)
      Lisp_Object *attr;
-     int charset;
-     Lisp_Object registry;
 {
   struct face *face = (struct face *) xmalloc (sizeof *face);
   bzero (face, sizeof *face);
-  face->charset = charset;
-  face->registry = registry;
+  face->ascii_face = face;
   bcopy (attr, face->lface, sizeof face->lface);
   return face;
 }
@@ -3968,19 +4554,22 @@ free_realized_face (f, face)
 {
   if (face)
     {
-#ifdef HAVE_X_WINDOWS
-      if (FRAME_X_P (f))
+#ifdef HAVE_WINDOW_SYSTEM
+      if (FRAME_WINDOW_P (f))
        {
+         /* Free fontset of FACE if it is ASCII face.  */
+         if (face->fontset >= 0 && face == face->ascii_face)
+           free_face_fontset (f, face);
          if (face->gc)
            {
              x_free_gc (f, face->gc);
              face->gc = 0;
            }
-         
+
          free_face_colors (f, face);
          x_destroy_bitmap (f, face->stipple);
        }
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
       xfree (face);
     }
@@ -3996,9 +4585,9 @@ prepare_face_for_display (f, face)
      struct frame *f;
      struct face *face;
 {
-#ifdef HAVE_X_WINDOWS
-  xassert (FRAME_X_P (f));
-  
+#ifdef HAVE_WINDOW_SYSTEM
+  xassert (FRAME_WINDOW_P (f));
+
   if (face->gc == 0)
     {
       XGCValues xgcv;
@@ -4006,72 +4595,36 @@ prepare_face_for_display (f, face)
 
       xgcv.foreground = face->foreground;
       xgcv.background = face->background;
+#ifdef HAVE_X_WINDOWS
       xgcv.graphics_exposures = False;
-
+#endif
       /* The font of FACE may be null if we couldn't load it.  */
       if (face->font)
        {
+#ifdef HAVE_X_WINDOWS
          xgcv.font = face->font->fid;
+#endif
+#ifdef WINDOWSNT
+         xgcv.font = face->font;
+#endif
          mask |= GCFont;
        }
 
       BLOCK_INPUT;
+#ifdef HAVE_X_WINDOWS
       if (face->stipple)
        {
          xgcv.fill_style = FillOpaqueStippled;
          xgcv.stipple = x_bitmap_pixmap (f, face->stipple);
          mask |= GCFillStyle | GCStipple;
        }
-
+#endif
       face->gc = x_create_gc (f, mask, &xgcv);
       UNBLOCK_INPUT;
     }
-#endif
-}
-
-
-/* Non-zero if FACE is suitable for displaying ISO8859-1.  Used in
-   macro FACE_SUITABLE_FOR_CHARSET_P to avoid realizing a new face for
-   ISO8859-1 if the ASCII face suffices.  */
-
-int
-face_suitable_for_iso8859_1_p (face)
-     struct face *face;
-{
-  int len = strlen (face->font_name);
-  return len >= 9 && xstricmp (face->font_name + len - 9, "iso8859-1") == 0;
-}
-
-
-/* Value is non-zero if FACE is suitable for displaying characters
-   of CHARSET.  CHARSET < 0 means unibyte text.  */
-
-INLINE int
-face_suitable_for_charset_p (face, charset)
-     struct face *face;
-     int charset;
-{
-  int suitable_p = 0;
-  
-  if (charset < 0)
-    {
-      if (EQ (face->registry, Vface_default_registry)
-         || !NILP (Fequal (face->registry, Vface_default_registry)))
-       suitable_p = 1;
-    }
-  else if (face->charset == charset)
-    suitable_p = 1;
-  else if (face->charset == CHARSET_ASCII
-          && charset == charset_latin_iso8859_1)
-    suitable_p = face_suitable_for_iso8859_1_p (face);
-  else if (face->charset == charset_latin_iso8859_1
-          && charset == CHARSET_ASCII)
-    suitable_p = 1;
-
-  return suitable_p;
+#endif /* HAVE_WINDOW_SYSTEM */
 }
 
-
 \f
 /***********************************************************************
                              Face Cache
@@ -4106,9 +4659,9 @@ static void
 clear_face_gcs (c)
      struct face_cache *c;
 {
-  if (c && FRAME_X_P (c->f))
+  if (c && FRAME_WINDOW_P (c->f))
     {
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
       int i;
       for (i = BASIC_FACE_ID_SENTINEL; i < c->used; ++i)
        {
@@ -4119,7 +4672,7 @@ clear_face_gcs (c)
              face->gc = 0;
            }
        }
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
     }
 }
 
@@ -4138,26 +4691,76 @@ free_realized_faces (c)
       int i, size;
       struct frame *f = c->f;
 
+      /* We must block input here because we can't process X events
+        safely while only some faces are freed, or when the frame's
+        current matrix still references freed faces.  */
+      BLOCK_INPUT;
+
       for (i = 0; i < c->used; ++i)
        {
          free_realized_face (f, c->faces_by_id[i]);
          c->faces_by_id[i] = NULL;
        }
-      
+
       c->used = 0;
       size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
       bzero (c->buckets, size);
 
-      /* Must do a thorough redisplay the next time.  Mark current
-        matrices as invalid because they will reference faces freed
-        above.  This function is also called when a frame is
-        destroyed.  In this case, the root window of F is nil.  */
-      if (WINDOWP (f->root_window))
+      /* Must do a thorough redisplay the next time.  Mark current
+        matrices as invalid because they will reference faces freed
+        above.  This function is also called when a frame is
+        destroyed.  In this case, the root window of F is nil.  */
+      if (WINDOWP (f->root_window))
+       {
+         clear_current_matrices (f);
+         ++windows_or_buffers_changed;
+       }
+
+      UNBLOCK_INPUT;
+    }
+}
+
+
+/* Free all faces realized for multibyte characters on frame F that
+   has FONTSET.  */
+
+void
+free_realized_multibyte_face (f, fontset)
+     struct frame *f;
+     int fontset;
+{
+  struct face_cache *cache = FRAME_FACE_CACHE (f);
+  struct face *face;
+  int i;
+
+  /* We must block input here because we can't process X events safely
+     while only some faces are freed, or when the frame's current
+     matrix still references freed faces.  */
+  BLOCK_INPUT;
+
+  for (i = 0; i < cache->used; i++)
+    {
+      face = cache->faces_by_id[i];
+      if (face
+         && face != face->ascii_face
+         && face->fontset == fontset)
        {
-         clear_current_matrices (f);
-         ++windows_or_buffers_changed;
+         uncache_face (cache, face);
+         free_realized_face (f, face);
        }
     }
+
+  /* Must do a thorough redisplay the next time.  Mark current
+     matrices as invalid because they will reference faces freed
+     above.  This function is also called when a frame is destroyed.
+     In this case, the root window of F is nil.  */
+  if (WINDOWP (f->root_window))
+    {
+      clear_current_matrices (f);
+      ++windows_or_buffers_changed;
+    }
+
+  UNBLOCK_INPUT;
 }
 
 
@@ -4199,8 +4802,8 @@ 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 charset, even if
-   faces with the same attributes but for specific charsets exist.  */
+   otherwise lookup_face would find FACE for every character, even if
+   faces with the same attributes but for specific characters exist.  */
 
 static void
 cache_face (c, face, hash)
@@ -4244,7 +4847,7 @@ cache_face (c, face, hash)
     if (c->faces_by_id[i] == NULL)
       break;
   face->id = i;
-  
+
   /* Maybe enlarge C->faces_by_id.  */
   if (i == c->used && c->used == c->size)
     {
@@ -4268,7 +4871,7 @@ cache_face (c, face, hash)
     xassert (n == 1);
   }
 #endif /* GLYPH_DEBUG */
-  
+
   c->faces_by_id[i] = face;
   if (i == c->used)
     ++c->used;
@@ -4283,15 +4886,15 @@ uncache_face (c, face)
      struct face *face;
 {
   int i = face->hash % FACE_CACHE_BUCKETS_SIZE;
-  
+
   if (face->prev)
     face->prev->next = face->next;
   else
     c->buckets[i] = face->next;
-  
+
   if (face->next)
     face->next->prev = face->prev;
-  
+
   c->faces_by_id[face->id] = NULL;
   if (face->id == c->used)
     --c->used;
@@ -4299,63 +4902,67 @@ 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 characters of
-   CHARSET.  CHARSET < 0 means the face will be used to display
-   unibyte text.  The value of face-default-registry is used to choose
-   a font for the face in that case.  Value is the ID of the face
-   found.  If no suitable face is found, realize a new one.  */
+   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.  */
 
 INLINE int
-lookup_face (f, attr, charset)
+lookup_face (f, attr, c, base_face)
      struct frame *f;
      Lisp_Object *attr;
-     int charset;
+     int c;
+     struct face *base_face;
 {
-  struct face_cache *c = FRAME_FACE_CACHE (f);
+  struct face_cache *cache = FRAME_FACE_CACHE (f);
   unsigned hash;
   int i;
   struct face *face;
 
-  xassert (c != NULL);
+  xassert (cache != NULL);
   check_lface_attrs (attr);
 
   /* Look up ATTR in the face cache.  */
   hash = lface_hash (attr);
   i = hash % FACE_CACHE_BUCKETS_SIZE;
-  
-  for (face = c->buckets[i]; face; face = face->next)
+
+  for (face = cache->buckets[i]; face; face = face->next)
     if (face->hash == hash
        && (!FRAME_WINDOW_P (f)
-           || FACE_SUITABLE_FOR_CHARSET_P (face, charset))
+           || FACE_SUITABLE_FOR_CHAR_P (face, c))
        && lface_equal_p (face->lface, attr))
       break;
 
   /* If not found, realize a new face.  */
   if (face == NULL)
-    {
-      face = realize_face (c, attr, charset);
-      cache_face (c, face, hash);
-    }
+    face = realize_face (cache, attr, c, base_face, -1);
 
 #if GLYPH_DEBUG
   xassert (face == FACE_FROM_ID (f, face->id));
-  if (FRAME_X_P (f))
-    xassert (charset < 0 || FACE_SUITABLE_FOR_CHARSET_P (face, charset));
+
+/* 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;
 }
 
 
 /* Return the face id of the realized face for named face SYMBOL on
-   frame F suitable for displaying characters from CHARSET.  CHARSET <
-   0 means unibyte text.  */
+   frame F suitable for displaying character C.  */
 
 int
-lookup_named_face (f, symbol, charset)
+lookup_named_face (f, symbol, c)
      struct frame *f;
      Lisp_Object symbol;
-     int charset;
+     int c;
 {
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
@@ -4364,7 +4971,7 @@ lookup_named_face (f, symbol, charset)
   get_lface_attributes (f, symbol, symbol_attrs, 1);
   bcopy (default_face->lface, attrs, sizeof attrs);
   merge_face_vectors (symbol_attrs, attrs);
-  return lookup_face (f, attrs, charset);
+  return lookup_face (f, attrs, c, NULL);
 }
 
 
@@ -4377,11 +4984,11 @@ ascii_face_of_lisp_face (f, lface_id)
      int lface_id;
 {
   int face_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, CHARSET_ASCII);
+      face_id = lookup_named_face (f, face_name, 0);
     }
   else
     face_id = -1;
@@ -4398,8 +5005,8 @@ int
 smaller_face (f, face_id, steps)
      struct frame *f;
      int face_id, steps;
- {
-#ifdef HAVE_X_WINDOWS
+{
+#ifdef HAVE_WINDOW_SYSTEM
   struct face *face;
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
   int pt, last_pt, last_height;
@@ -4414,7 +5021,7 @@ smaller_face (f, face_id, steps)
   /* Try in increments of 1/2 pt.  */
   delta = steps < 0 ? 5 : -5;
   steps = abs (steps);
-  
+
   face = FACE_FROM_ID (f, face_id);
   bcopy (face->lface, attrs, sizeof attrs);
   pt = last_pt = XFASTINT (attrs[LFACE_HEIGHT_INDEX]);
@@ -4429,7 +5036,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, CHARSET_ASCII);
+      new_face_id = lookup_face (f, attrs, 0, NULL);
       new_face = FACE_FROM_ID (f, new_face_id);
 
       /* If height changes, count that as one step.  */
@@ -4443,11 +5050,11 @@ smaller_face (f, face_id, steps)
 
   return new_face_id;
 
-#else /* not HAVE_X_WINDOWS */
+#else /* not HAVE_WINDOW_SYSTEM */
 
   return face_id;
-  
-#endif /* not HAVE_X_WINDOWS */
+
+#endif /* not HAVE_WINDOW_SYSTEM */
 }
 
 
@@ -4460,7 +5067,7 @@ face_with_height (f, face_id, height)
      int face_id;
      int height;
 {
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   struct face *face;
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
 
@@ -4471,25 +5078,24 @@ 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, CHARSET_ASCII);
-#endif /* HAVE_X_WINDOWS */
-  
+  face_id = lookup_face (f, attrs, 0, NULL);
+#endif /* HAVE_WINDOW_SYSTEM */
+
   return face_id;
 }
 
 /* Return the face id of the realized face for named face SYMBOL on
-   frame F suitable for displaying characters from CHARSET (CHARSET <
-   0 means unibyte text), 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 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.  */
 
 int
-lookup_derived_face (f, symbol, charset, face_id)
+lookup_derived_face (f, symbol, c, face_id)
      struct frame *f;
      Lisp_Object symbol;
-     int charset;
+     int c;
      int face_id;
 {
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
@@ -4502,7 +5108,7 @@ lookup_derived_face (f, symbol, charset, face_id)
   get_lface_attributes (f, symbol, symbol_attrs, 1);
   bcopy (default_face->lface, attrs, sizeof attrs);
   merge_face_vectors (symbol_attrs, attrs);
-  return lookup_face (f, attrs, charset);
+  return lookup_face (f, attrs, c, default_face);
 }
 
 
@@ -4527,7 +5133,7 @@ Value is ORDER.")
   Lisp_Object list;
   int i;
   int indices[4];
-  
+
   CHECK_LIST (order, 0);
   bzero (indices, sizeof indices);
   i = 0;
@@ -4568,7 +5174,7 @@ Value is ORDER.")
       bcopy (indices, font_sort_order, sizeof font_sort_order);
       free_all_realized_faces (Qnil);
     }
-  
+
   return Qnil;
 }
 
@@ -4590,37 +5196,7 @@ be found.  Value is ALIST.")
 }
 
 
-#ifdef HAVE_X_WINDOWS
-
-/* Return the X registry and encoding of font name FONT_NAME on frame F.
-   Value is nil if not successful.  */
-
-static Lisp_Object
-deduce_unibyte_registry (f, font_name)
-     struct frame *f;
-     char *font_name;
-{
-  struct font_name font;
-  Lisp_Object registry = Qnil;
-  
-  font.name = STRDUPA (font_name);
-  if (split_font_name (f, &font, 0))
-    {
-      char *buffer;
-
-      /* Extract registry and encoding.  */
-      buffer = (char *) alloca (strlen (font.fields[XLFD_REGISTRY])
-                               + strlen (font.fields[XLFD_ENCODING])
-                               + 10);
-      strcpy (buffer, font.fields[XLFD_REGISTRY]);
-      strcat (buffer, "-");
-      strcat (buffer, font.fields[XLFD_ENCODING]);
-      registry = build_string (buffer);
-    }
-
-  return registry;
-}
-
+#ifdef HAVE_WINDOW_SYSTEM
 
 /* Value is non-zero if FONT is the name of a scalable font.  The
    X11R6 XLFD spec says that point size, pixel size, and average width
@@ -4633,7 +5209,14 @@ font_scalable_p (font)
      struct font_name *font;
 {
   char *s = font->fields[XLFD_AVGWIDTH];
-  return *s == '0' && *(s + 1) == '\0';
+  return (*s == '0' && *(s + 1) == '\0')
+#ifdef WINDOWSNT
+  /* Windows implementation of XLFD is slightly broken for backward
+     compatibility with previous broken versions, so test for
+     wildcards as well as 0. */
+  || *s == '*'
+#endif
+    ;
 }
 
 
@@ -4649,7 +5232,7 @@ better_font_p (values, font1, font2, compare_pt_p)
      int compare_pt_p;
 {
   int i;
-  
+
   for (i = 0; i < 4; ++i)
     {
       int xlfd_idx = font_sort_order[i];
@@ -4658,7 +5241,7 @@ better_font_p (values, font1, font2, compare_pt_p)
        {
          int delta1 = abs (values[i] - font1->numeric[xlfd_idx]);
          int delta2 = abs (values[i] - font2->numeric[xlfd_idx]);
-      
+
          if (delta1 > delta2)
            return 0;
          else if (delta1 < delta2)
@@ -4675,7 +5258,7 @@ better_font_p (values, font1, font2, compare_pt_p)
            }
        }
     }
-  
+
   return 0;
 }
 
@@ -4692,7 +5275,7 @@ exact_face_match_p (specified, font)
      struct font_name *font;
 {
   int i;
-  
+
   for (i = 0; i < 4; ++i)
     if (specified[i] != font->numeric[font_sort_order[i]])
       break;
@@ -4729,17 +5312,17 @@ build_scalable_font_name (f, font, specified_pt)
       pt = specified_pt;
       pixel_value = resy / 720.0 * pt;
     }
-  
+
   /* 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;
-  
+
   /* Set pixel size.  */
   sprintf (pixel_size, "%d", pixel_value);
   font->fields[XLFD_PIXEL_SIZE] = pixel_size;
   font->numeric[XLFD_PIXEL_SIZE] = pixel_value;
-  
+
   /* If font doesn't specify its resolution, use the
      resolution of the display.  */
   if (font->numeric[XLFD_RESY] == 0)
@@ -4749,7 +5332,7 @@ build_scalable_font_name (f, font, specified_pt)
       font->fields[XLFD_RESY] = buffer;
       font->numeric[XLFD_RESY] = resy;
     }
-  
+
   if (strcmp (font->fields[XLFD_RESX], "0") == 0)
     {
       char buffer[20];
@@ -4777,7 +5360,7 @@ may_use_scalable_font_p (font, name)
   else if (CONSP (Vscalable_fonts_allowed))
     {
       Lisp_Object tail, regexp;
-      
+
       for (tail = Vscalable_fonts_allowed; CONSP (tail); tail = XCDR (tail))
        {
          regexp = XCAR (tail);
@@ -4786,7 +5369,7 @@ may_use_scalable_font_p (font, name)
            return 1;
        }
     }
-  
+
   return 0;
 }
 
@@ -4819,7 +5402,7 @@ best_matching_font (f, attrs, fonts, nfonts)
   for (i = 0; i < DIM (font_sort_order); ++i)
     {
       int xlfd_idx = font_sort_order[i];
-  
+
       if (xlfd_idx == XLFD_SWIDTH)
        specified[i] = face_numeric_swidth (attrs[LFACE_SWIDTH_INDEX]);
       else if (xlfd_idx == XLFD_POINT_SIZE)
@@ -4836,7 +5419,7 @@ best_matching_font (f, attrs, fonts, nfonts)
 
   /* Set to 1 */
   exact_p = 0;
-  
+
   /* Start with the first non-scalable font in the list.  */
   for (i = 0; i < nfonts; ++i)
     if (!font_scalable_p (fonts + i))
@@ -4846,7 +5429,7 @@ best_matching_font (f, attrs, fonts, nfonts)
   if (i < nfonts)
     {
       best = fonts + i;
-      
+
       for (i = 1; i < nfonts; ++i)
        if (!font_scalable_p (fonts + i)
            && better_font_p (specified, fonts + i, best, 1))
@@ -4857,7 +5440,7 @@ best_matching_font (f, attrs, fonts, nfonts)
            if (exact_p)
              break;
          }
-      
+
     }
   else
     best = NULL;
@@ -4869,7 +5452,7 @@ best_matching_font (f, attrs, fonts, nfonts)
       /* A scalable font is better if
 
         1. its weight, slant, swidth attributes are better, or.
-        
+
         2. the best non-scalable font doesn't have the required
         point size, and the scalable fonts weight, slant, swidth
         isn't worse.  */
@@ -4880,7 +5463,7 @@ best_matching_font (f, attrs, fonts, nfonts)
        non_scalable_has_exact_height_p = 1;
       else
        non_scalable_has_exact_height_p = 0;
-      
+
       for (i = 0; i < nfonts; ++i)
        if (font_scalable_p (fonts + i))
          {
@@ -4896,26 +5479,26 @@ best_matching_font (f, attrs, fonts, nfonts)
     font_name = build_scalable_font_name (f, best, pt);
   else
     font_name = build_font_name (best);
-  
+
 #else /* !SCALABLE_FONTS */
-  
+
   /* Find the best non-scalable font.  */
   best = fonts;
-  
+
   for (i = 1; i < nfonts; ++i)
     {
       xassert (!font_scalable_p (fonts + i));
       if (better_font_p (specified, fonts + i, best, 1))
        best = fonts + i;
     }
-  
+
   font_name = build_font_name (best);
 
 #endif /* !SCALABLE_FONTS */
 
   /* Free font_name structures.  */
   free_font_names (fonts, nfonts);
-  
+
   return font_name;
 }
 
@@ -4929,187 +5512,118 @@ static int
 try_font_list (f, attrs, pattern, family, registry, fonts)
      struct frame *f;
      Lisp_Object *attrs;
-     char *pattern, *family, *registry;
+     Lisp_Object pattern, family, registry;
      struct font_name **fonts;
 {
   int nfonts;
 
-  if (family == NULL)
-    family = LSTRDUPA (attrs[LFACE_FAMILY_INDEX]);
-  
+  if (NILP (family) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
+    family = attrs[LFACE_FAMILY_INDEX];
+
   nfonts = font_list (f, pattern, family, registry, fonts);
-  
-  if (nfonts == 0)
+
+  if (nfonts == 0 && !NILP (family))
     {
       Lisp_Object alter;
-         
+
       /* Try alternative font families from
         Vface_alternative_font_family_alist.  */
-      alter = Fassoc (build_string (family),
-                     Vface_alternative_font_family_alist);
+      alter = Fassoc (family, Vface_alternative_font_family_alist);
       if (CONSP (alter))
        for (alter = XCDR (alter);
             CONSP (alter) && nfonts == 0;
             alter = XCDR (alter))
          {
            if (STRINGP (XCAR (alter)))
-             {
-               family = LSTRDUPA (XCAR (alter));
-               nfonts = font_list (f, NULL, family, registry, fonts);
-             }
+             nfonts = font_list (f, Qnil, XCAR (alter), registry, fonts);
          }
-         
+
       /* Try font family of the default face or "fixed".  */
       if (nfonts == 0)
        {
          struct face *dflt = FACE_FROM_ID (f, DEFAULT_FACE_ID);
          if (dflt)
-           family = LSTRDUPA (dflt->lface[LFACE_FAMILY_INDEX]);
+           family = dflt->lface[LFACE_FAMILY_INDEX];
          else
-           family = "fixed";
-         nfonts = font_list (f, NULL, family, registry, fonts);
+           family = build_string ("fixed");
+         nfonts = font_list (f, Qnil, family, registry, fonts);
        }
-         
+
       /* Try any family with the given registry.  */
       if (nfonts == 0)
-       nfonts = font_list (f, NULL, "*", registry, fonts);
+       nfonts = font_list (f, Qnil, Qnil, registry, fonts);
     }
 
   return nfonts;
 }
 
-  
-/* Return the registry and encoding pattern that fonts for CHARSET
-   should match.  Value is allocated from the heap.  */
-
-char *
-x_charset_registry (charset)
-     int charset;
-{
-  Lisp_Object prop, charset_plist;
-  char *registry;
-
-  /* Get registry and encoding from the charset's plist.  */
-  charset_plist = CHARSET_TABLE_INFO (charset, CHARSET_PLIST_IDX);
-  prop = Fplist_get (charset_plist, Qx_charset_registry);
-  
-  if (STRINGP (prop))
-    {
-      if (index (XSTRING (prop)->data, '-'))
-       registry = xstrdup (XSTRING (prop)->data);
-      else
-       {
-         /* If registry doesn't contain a `-', make it a pattern.  */
-         registry = (char *) xmalloc (STRING_BYTES (XSTRING (prop)) + 5);
-         strcpy (registry, XSTRING (prop)->data);
-         strcat (registry, "*-*");
-       }
-    }
-  else if (STRINGP (Vface_default_registry))
-    registry = xstrdup (XSTRING (Vface_default_registry)->data);
-  else
-    registry = xstrdup ("iso8859-1");
-
-  return registry;
-}
-
 
-/* Return the fontset id of the fontset name or alias name given by
-   the family attribute of ATTRS on frame F.  Value is -1 if the
-   family attribute of ATTRS doesn't name a fontset.  */
+/* Return the fontset id of the base fontset name or alias name given
+   by the fontset attribute of ATTRS.  Value is -1 if the fontset
+   attribute of ATTRS doesn't name a fontset.  */
 
 static int
-face_fontset (f, attrs)
-     struct frame *f;
+face_fontset (attrs)
      Lisp_Object *attrs;
 {
-  Lisp_Object name = attrs[LFACE_FAMILY_INDEX];
+  Lisp_Object name;
   int fontset;
-  
-  name = Fquery_fontset (name, Qnil);
-  if (NILP (name))
-    fontset = -1;
-  else
-    fontset = fs_query_fontset (f, XSTRING (name)->data);
 
-  return fontset;
+  name = attrs[LFACE_FONT_INDEX];
+  if (!STRINGP (name))
+    return -1;
+  return fs_query_fontset (name, 0);
 }
 
 
-/* Get the font to use for the face realizing the fully-specified Lisp
-   face ATTRS for charset CHARSET on frame F.  CHARSET < 0 means
-   unibyte text; UNIBYTE_REGISTRY is the registry and encoding to use
-   in this case.  Value is the font name which is allocated from the
-   heap (which means that it must be freed eventually).  */
+/* Choose a name of font to use on frame F to display character C with
+   Lisp face attributes specified by ATTRS.  The font name is
+   determined by the font-related attributes in ATTRS and the name
+   pattern for C in FONTSET.  Value is the font name which is
+   allocated from the heap and must be freed by the caller, or NULL if
+   we can get no information about the font name of C.  It is assured
+   that we always get some information for a single byte
+   character.  */
 
 static char *
-choose_face_font (f, attrs, charset, unibyte_registry)
+choose_face_font (f, attrs, fontset, c)
      struct frame *f;
      Lisp_Object *attrs;
-     int charset;
-     Lisp_Object unibyte_registry;
+     int fontset, c;
 {
+  Lisp_Object pattern;
+  char *font_name = NULL;
   struct font_name *fonts;
   int nfonts;
-  char *registry;
-
-  /* ATTRS must be fully-specified.  */
-  xassert (lface_fully_specified_p (attrs));
-
-  if (STRINGP (unibyte_registry))
-    registry = xstrdup (XSTRING (unibyte_registry)->data);
-  else
-    registry = x_charset_registry (charset);
-
-  nfonts = try_font_list (f, attrs, NULL, NULL, registry, &fonts);
-  xfree (registry);
-  return best_matching_font (f, attrs, fonts, 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))
+    {
+      xassert (!SINGLE_BYTE_CHAR_P (c));
+      return NULL;
+    }
+  /* If what we got is a name pattern, return it.  */
+  if (STRINGP (pattern))
+    return xstrdup (XSTRING (pattern)->data);
 
-/* Choose a font to use on frame F to display CHARSET using FONTSET
-   with Lisp face attributes specified by ATTRS.  CHARSET may be any
-   valid charset except CHARSET_COMPOSITION.  CHARSET < 0 means
-   unibyte text.  If the fontset doesn't contain a font pattern for
-   charset, use the pattern for CHARSET_ASCII.  Value is the font name
-   which is allocated from the heap and must be freed by the caller.  */
+  /* Family name may be specified both in ATTRS and car part of
+     PATTERN.  The former has higher priority if C is a single byte
+     character.  */
+  if (STRINGP (attrs[LFACE_FAMILY_INDEX])
+      && SINGLE_BYTE_CHAR_P (c))
+    XCAR (pattern) = Qnil;
 
-static char *
-choose_face_fontset_font (f, attrs, fontset, charset)
-     struct frame *f;
-     Lisp_Object *attrs;
-     int fontset, charset;
-{
-  char *pattern;
-  char *font_name = NULL;
-  struct fontset_info *fontset_info;
-  struct font_name *fonts;
-  int nfonts;
-  
-  xassert (charset != CHARSET_COMPOSITION);
-  xassert (fontset >= 0 && fontset < FRAME_FONTSET_DATA (f)->n_fontsets);
-
-  /* For unibyte text, use the ASCII font of the fontset.  Using the
-     ASCII font seems to be the most reasonable thing we can do in
-     this case.  */
-  if (charset < 0)
-    charset = CHARSET_ASCII;
-
-  /* Get the font name pattern to use for CHARSET from the fontset.  */
-  fontset_info = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-  pattern = fontset_info->fontname[charset];
-  if (!pattern)
-    pattern = fontset_info->fontname[CHARSET_ASCII];
-  xassert (pattern);
-
-  /* Get a list of fonts matching that pattern and choose the 
+  /* 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, pattern, NULL, NULL, &fonts);
+  nfonts = try_font_list (f, attrs, Qnil, XCAR (pattern), XCDR (pattern),
+                         &fonts);
   font_name = best_matching_font (f, attrs, fonts, nfonts);
   return font_name;
 }
 
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
 
 \f
@@ -5126,16 +5640,26 @@ realize_basic_faces (f)
      struct frame *f;
 {
   int success_p = 0;
-  
+
+  /* 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;
+
   if (realize_default_face (f))
     {
-      realize_named_face (f, Qmodeline, MODE_LINE_FACE_ID);
+      realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
       realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
-      realize_named_face (f, Qmargin, BITMAP_AREA_FACE_ID);
+      realize_named_face (f, Qfringe, BITMAP_AREA_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);
+      realize_named_face (f, Qcursor, CURSOR_FACE_ID);
+      realize_named_face (f, Qmouse, MOUSE_FACE_ID);
+      realize_named_face (f, Qmenu, MENU_FACE_ID);
       success_p = 1;
     }
 
+  UNBLOCK_INPUT;
   return success_p;
 }
 
@@ -5151,7 +5675,6 @@ realize_default_face (f)
   struct face_cache *c = FRAME_FACE_CACHE (f);
   Lisp_Object lface;
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
-  Lisp_Object unibyte_registry;
   Lisp_Object frame_font;
   struct face *face;
   int fontset;
@@ -5165,71 +5688,16 @@ realize_default_face (f)
       lface = Finternal_make_lisp_face (Qdefault, frame);
     }
 
-#ifdef HAVE_X_WINDOWS
-  if (FRAME_X_P (f))
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (f))
     {
       /* Set frame_font to the value of the `font' frame parameter.  */
       frame_font = Fassq (Qfont, f->param_alist);
       xassert (CONSP (frame_font) && STRINGP (XCDR (frame_font)));
       frame_font = XCDR (frame_font);
-  
-      fontset = fs_query_fontset (f, XSTRING (frame_font)->data);
-      if (fontset >= 0)
-       {
-         /* If frame_font is a fontset name, don't use that for
-            determining font-related attributes of the default face
-            because it is just an artificial name.  Use the ASCII font of
-            the fontset, instead.  */
-         struct font_info *font_info;
-         struct font_name font;
-
-         BLOCK_INPUT;
-         font_info = FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII,
-                                   NULL, fontset);
-         UNBLOCK_INPUT;
-         
-         /* Set weight etc. from the ASCII font.  */
-         if (!set_lface_from_font_name (f, lface, font_info->full_name, 0))
-           return 0;
-         
-         /* Remember registry and encoding of the frame font.  */
-         unibyte_registry = deduce_unibyte_registry (f, font_info->full_name);
-         if (STRINGP (unibyte_registry))
-           Vface_default_registry = unibyte_registry;
-         else
-           Vface_default_registry = build_string ("iso8859-1");
-         
-         /* But set the family to the fontset alias name.  Implementation
-            note: When a font is passed to Emacs via `-fn FONT', a
-            fontset is created in `x-win.el' whose name ends in
-            `fontset-startup'.  This fontset has an alias name that is
-            equal to frame_font.  */
-         xassert (STRINGP (frame_font));
-         font.name = LSTRDUPA (frame_font);
-         
-         if (!split_font_name (f, &font, 1)
-             || xstricmp (font.fields[XLFD_REGISTRY], "fontset") != 0
-             || xstricmp (font.fields[XLFD_ENCODING], "startup") != 0)
-           LFACE_FAMILY (lface) = frame_font;
-       }
-      else
-       {
-         /* Frame parameters contain a real font.  Fill default face
-            attributes from that font.  */
-         if (!set_lface_from_font_name (f, lface,
-                                        XSTRING (frame_font)->data, 0))
-           return 0;
-         
-         /* Remember registry and encoding of the frame font.  */
-         unibyte_registry
-           = deduce_unibyte_registry (f, XSTRING (frame_font)->data);
-         if (STRINGP (unibyte_registry))
-           Vface_default_registry = unibyte_registry;
-         else
-           Vface_default_registry = build_string ("iso8859-1");
-       }
+      set_lface_from_font_name (f, lface, frame_font, 0, 1);
     }
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
   if (!FRAME_WINDOW_P (f))
     {
@@ -5239,41 +5707,38 @@ realize_default_face (f)
       LFACE_WEIGHT (lface) = Qnormal;
       LFACE_SLANT (lface) = Qnormal;
     }
-      
+
   if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))
     LFACE_UNDERLINE (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_OVERLINE (lface)))
     LFACE_OVERLINE (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_STRIKE_THROUGH (lface)))
     LFACE_STRIKE_THROUGH (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_BOX (lface)))
     LFACE_BOX (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_INVERSE (lface)))
     LFACE_INVERSE (lface) = Qnil;
-      
+
   if (UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
     {
       /* This function is called so early that colors are not yet
         set in the frame parameter list.  */
       Lisp_Object color = Fassq (Qforeground_color, f->param_alist);
-      
+
       if (CONSP (color) && STRINGP (XCDR (color)))
        LFACE_FOREGROUND (lface) = XCDR (color);
-      else if (FRAME_X_P (f))
+      else if (FRAME_WINDOW_P (f))
        return 0;
       else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
-       /* Frame parameters for terminal frames usually don't contain
-          a color.  Use an empty string to indicate that the face
-          should use the (unknown) default color of the terminal.  */
-       LFACE_FOREGROUND (lface) = build_string ("");
+       LFACE_FOREGROUND (lface) = build_string (unspecified_fg);
       else
        abort ();
     }
-  
+
   if (UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
     {
       /* This function is called so early that colors are not yet
@@ -5281,17 +5746,14 @@ realize_default_face (f)
       Lisp_Object color = Fassq (Qbackground_color, f->param_alist);
       if (CONSP (color) && STRINGP (XCDR (color)))
        LFACE_BACKGROUND (lface) = XCDR (color);
-      else if (FRAME_X_P (f))
+      else if (FRAME_WINDOW_P (f))
        return 0;
       else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
-       /* Frame parameters for terminal frames usually don't contain
-          a color.  Use an empty string to indicate that the face
-          should use the (unknown) default color of the terminal.  */
-       LFACE_BACKGROUND (lface) = build_string ("");
+       LFACE_BACKGROUND (lface) = build_string (unspecified_bg);
       else
        abort ();
     }
-  
+
   if (UNSPECIFIEDP (LFACE_STIPPLE (lface)))
     LFACE_STIPPLE (lface) = Qnil;
 
@@ -5299,19 +5761,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, CHARSET_ASCII);
-
-  /* Remove the former default face.  */
-  if (c->used > DEFAULT_FACE_ID)
-    {
-      struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-      uncache_face (c, default_face);
-      free_realized_face (f, default_face);
-    }
-
-  /* Insert the new default face.  */
-  cache_face (c, face, lface_hash (attrs));
-  xassert (face->id == DEFAULT_FACE_ID);
+  face = realize_face (c, attrs, 0, NULL, DEFAULT_FACE_ID);
   return 1;
 }
 
@@ -5350,150 +5800,146 @@ realize_named_face (f, symbol, id)
   merge_face_vectors (symbol_attrs, attrs);
 
   /* Realize the face.  */
-  new_face = realize_face (c, attrs, CHARSET_ASCII);
-
-  /* Remove the former face.  */
-  if (c->used > id)
-    {
-      struct face *old_face = c->faces_by_id[id];
-      uncache_face (c, old_face);
-      free_realized_face (f, old_face);
-    }
-
-  /* Insert the new face.  */
-  cache_face (c, new_face, lface_hash (attrs));
-  xassert (new_face->id == id);
+  new_face = realize_face (c, attrs, 0, NULL, id);
 }
 
 
 /* Realize the fully-specified face with attributes ATTRS in face
-   cache C for character set CHARSET or for unibyte text if CHARSET <
-   0.  Value is a pointer to the newly created realized 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.  */
 
 static struct face *
-realize_face (c, attrs, charset)
-     struct face_cache *c;
+realize_face (cache, attrs, c, base_face, former_face_id)
+     struct face_cache *cache;
      Lisp_Object *attrs;
-     int charset;
+     int c;
+     struct face *base_face;
+     int former_face_id;
 {
   struct face *face;
-  
+
   /* LFACE must be fully specified.  */
-  xassert (c != NULL);
+  xassert (cache != NULL);
   check_lface_attrs (attrs);
 
-  if (FRAME_X_P (c->f))
-    face = realize_x_face (c, attrs, charset);
-  else if (FRAME_TERMCAP_P (c->f) || FRAME_MSDOS_P (c->f))
-    face = realize_tty_face (c, attrs, charset);
+  if (former_face_id >= 0 && cache->used > former_face_id)
+    {
+      /* Remove the former face.  */
+      struct face *former_face = cache->faces_by_id[former_face_id];
+      uncache_face (cache, former_face);
+      free_realized_face (cache->f, former_face);
+    }
+
+  if (FRAME_WINDOW_P (cache->f))
+    face = realize_x_face (cache, attrs, c, base_face);
+  else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
+    face = realize_tty_face (cache, attrs, c);
   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 with attributes ATTRS in face
-   cache C for character set CHARSET or for unibyte text if CHARSET <
-   0.  Do it for X frame C->f.  Value is a pointer to the newly
-   created realized 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.  */
 
 static struct face *
-realize_x_face (c, attrs, charset)
-     struct face_cache *c;
+realize_x_face (cache, attrs, c, base_face)
+     struct face_cache *cache;
      Lisp_Object *attrs;
-     int charset;
+     int c;
+     struct face *base_face;
 {
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   struct face *face, *default_face;
-  struct frame *f = c->f;
+  struct frame *f;
   Lisp_Object stipple, overline, strike_through, box;
-  Lisp_Object unibyte_registry;
-  struct gcpro gcpro1;
-
-  xassert (FRAME_X_P (f));
 
-  /* If realizing a face for use in unibyte text, get the X registry
-     and encoding to use from Vface_default_registry.  */
-  if (charset < 0)
-    unibyte_registry = (STRINGP (Vface_default_registry)
-                       ? Vface_default_registry
-                       : build_string ("iso8859-1"));
-  else
-    unibyte_registry = Qnil;
-  GCPRO1 (unibyte_registry);
+  xassert (FRAME_WINDOW_P (cache->f));
+  xassert (SINGLE_BYTE_CHAR_P (c)
+          || base_face);
 
   /* Allocate a new realized face.  */
-  face = make_realized_face (attrs, charset, unibyte_registry);
+  face = make_realized_face (attrs);
+
+  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_CHARSET_P (default_face, charset)
+      && 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->registry = default_face->registry;
-    }
-  else if (charset >= 0)
-    {
-      /* For all charsets except CHARSET_COMPOSITION, we use our own
-        font selection functions to choose a best matching font for
-        the specified face attributes.  If the face specifies a
-        fontset alias name, the fontset determines the font name
-        pattern, otherwise we construct a font pattern from face
-        attributes and charset.
-
-        If charset is CHARSET_COMPOSITION, we always construct a face
-        with a fontset, even if the face doesn't specify a fontset alias
-        (we use fontset-standard in that case).  When the composite
-        character is displayed in xterm.c, a suitable concrete font is
-        loaded in x_get_char_font_and_encoding.  */
-      
-      char *font_name = NULL;
-      int fontset = face_fontset (f, attrs);
-
-      if (charset == CHARSET_COMPOSITION)
-       fontset = max (0, fontset);
-      else if (fontset < 0)
-       font_name = choose_face_font (f, attrs, charset, Qnil);
-      else
-       {
-         font_name = choose_face_fontset_font (f, attrs, fontset, charset);
-         fontset = -1;
-       }
-      
-      load_face_font_or_fontset (f, face, font_name, fontset);
-      xfree (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);
     }
   else
     {
-      /* Unibyte case, and font is not equal to that of the default
-        face.  UNIBYTE_REGISTRY is the X registry and encoding the
-        font should have.  What is a reasonable thing to do if the
-        user specified a fontset alias name for the face in this
-        case?  We choose a font by taking the ASCII font of the
-        fontset, but using UNIBYTE_REGISTRY for its registry and
-        encoding.  */
-      
-      char *font_name = NULL;
-      int fontset = face_fontset (f, attrs);
-      
-      if (fontset < 0)
-       font_name = choose_face_font (f, attrs, charset, unibyte_registry);
-      else
-       font_name = choose_face_fontset_font (f, attrs, fontset, charset);
-      
-      load_face_font_or_fontset (f, face, font_name, -1);
-      xfree (font_name);
+      /* If the face attribute ATTRS specifies a fontset, use it as
+        the base of a new realized fontset.  Otherwise, use the same
+        base fontset as of the default face.  The base determines
+        registry and encoding of a font.  It may also determine
+        foundry and family.  The other fields of font name pattern
+        are constructed from ATTRS.  */
+      int fontset = face_fontset (attrs);
+
+      if ((fontset == -1) && default_face)
+       fontset = default_face->fontset;
+      face->fontset = make_fontset_for_ascii_face (f, fontset);
+      face->font = NULL;       /* to force realize_face to load font */
     }
 
   /* Load colors, and set remaining attributes.  */
-  
+
   load_face_colors (f, face, attrs);
 
   /* Set up box.  */
@@ -5563,9 +6009,9 @@ realize_x_face (c, attrs, charset)
     }
 
   /* Text underline, overline, strike-through.  */
-  
+
   if (EQ (attrs[LFACE_UNDERLINE_INDEX], Qt))
-    { 
+    {
       /* Use default color (same as foreground color).  */
       face->underline_p = 1;
       face->underline_defaulted_p = 1;
@@ -5621,37 +6067,39 @@ realize_x_face (c, attrs, charset)
   if (!NILP (stipple))
     face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h);
 
-  UNGCPRO;
-  xassert (face->fontset < 0 || face->charset == CHARSET_COMPOSITION);
-  xassert (FACE_SUITABLE_FOR_CHARSET_P (face, charset));
+  xassert (FACE_SUITABLE_FOR_CHAR_P (face, c));
   return face;
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 }
 
 
 /* Realize the fully-specified face with attributes ATTRS in face
-   cache C for character set CHARSET or for unibyte text if CHARSET <
-   0.  Do it for TTY frame C->f.  Value is a pointer to the newly
-   created realized face.  */
+   cache CACHE for character C.  Do it for TTY frame CACHE->f.  Value is a
+   pointer to the newly created realized face.  */
 
 static struct face *
-realize_tty_face (c, attrs, charset)
-     struct face_cache *c;
+realize_tty_face (cache, attrs, c)
+     struct face_cache *cache;
      Lisp_Object *attrs;
-     int charset;
+     int c;
 {
   struct face *face;
   int weight, slant;
   Lisp_Object color;
+  Lisp_Object tty_defined_color_alist
+    = find_symbol_value (intern ("tty-defined-color-alist"));
+  Lisp_Object tty_color_alist = intern ("tty-color-alist");
+  Lisp_Object frame;
+  int face_colors_defaulted = 0;
 
   /* Frame must be a termcap frame.  */
-  xassert (FRAME_TERMCAP_P (c->f) || FRAME_MSDOS_P (c->f));
-  
+  xassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
+
   /* Allocate a new realized face.  */
-  face = make_realized_face (attrs, charset, Qnil);
-  face->font_name = FRAME_MSDOS_P (c->f) ? "ms-dos" : "tty";
+  face = make_realized_face (attrs);
+  face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
 
-  /* Map face attributes to TTY appearances.  We map slant to 
+  /* Map face attributes to TTY appearances.  We map slant to
      dimmed text because we want italic text to appear differently
      and because dimmed text is probably used infrequently.  */
   weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
@@ -5667,109 +6115,137 @@ realize_tty_face (c, attrs, charset)
     face->tty_reverse_p = 1;
 
   /* Map color names to color indices.  */
-  face->foreground = face->background = FACE_TTY_DEFAULT_COLOR;
+  face->foreground = FACE_TTY_DEFAULT_FG_COLOR;
+  face->background = FACE_TTY_DEFAULT_BG_COLOR;
 
+  XSETFRAME (frame, cache->f);
   color = attrs[LFACE_FOREGROUND_INDEX];
-  if (XSTRING (color)->size
-      && (color = Fassoc (color, Vface_tty_color_alist),
+  if (STRINGP (color)
+      && XSTRING (color)->size
+      && CONSP (tty_defined_color_alist)
+      && (color = Fassoc (color, call1 (tty_color_alist, frame)),
          CONSP (color)))
-    face->foreground = XINT (XCDR (color));
+    /* Associations in tty-defined-color-alist are of the form
+       (NAME INDEX R G B).  We need the INDEX part.  */
+    face->foreground = XINT (XCAR (XCDR (color)));
 
-#ifdef MSDOS
-  if (FRAME_MSDOS_P (c->f) && face->foreground == FACE_TTY_DEFAULT_COLOR)
+  if (face->foreground == FACE_TTY_DEFAULT_FG_COLOR
+      && STRINGP (attrs[LFACE_FOREGROUND_INDEX]))
     {
-      face->foreground = load_color (c->f, face,
+      face->foreground = load_color (cache->f, face,
                                     attrs[LFACE_FOREGROUND_INDEX],
                                     LFACE_FOREGROUND_INDEX);
+
+#if defined (MSDOS) || defined (WINDOWSNT)
       /* If the foreground of the default face is the default color,
         use the foreground color defined by the frame.  */
-      if (face->foreground == FACE_TTY_DEFAULT_COLOR)
+#ifdef MSDOS
+      if (FRAME_MSDOS_P (cache->f))
        {
-         face->foreground = FRAME_FOREGROUND_PIXEL (f);
-         attrs[LFACE_FOREGROUND_INDEX] =
-           build_string (msdos_stdcolor_name (face->foreground));
+#endif /* MSDOS */
+
+         if (face->foreground == FACE_TTY_DEFAULT_FG_COLOR
+             || face->foreground == FACE_TTY_DEFAULT_COLOR)
+           {
+              face->foreground = FRAME_FOREGROUND_PIXEL (cache->f);
+             attrs[LFACE_FOREGROUND_INDEX] =
+               tty_color_name (cache->f, face->foreground);
+             face_colors_defaulted = 1;
+           }
+         else if (face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
+           {
+             face->foreground = FRAME_BACKGROUND_PIXEL (cache->f);
+             attrs[LFACE_FOREGROUND_INDEX] =
+               tty_color_name (cache->f, face->foreground);
+             face_colors_defaulted = 1;
+           }
+#ifdef MSDOS
        }
-    }
 #endif
+#endif /* MSDOS or WINDOWSNT */
+    }
 
   color = attrs[LFACE_BACKGROUND_INDEX];
-  if (XSTRING (color)->size
-      && (color = Fassoc (color, Vface_tty_color_alist),
+  if (STRINGP (color)
+      && XSTRING (color)->size
+      && CONSP (tty_defined_color_alist)
+      && (color = Fassoc (color, call1 (tty_color_alist, frame)),
          CONSP (color)))
-    face->background = XINT (XCDR (color));
+    /* Associations in tty-defined-color-alist are of the form
+       (NAME INDEX R G B).  We need the INDEX part.  */
+    face->background = XINT (XCAR (XCDR (color)));
 
-#ifdef MSDOS
-  if (FRAME_MSDOS_P (c->f) && face->background == FACE_TTY_DEFAULT_COLOR)
+  if (face->background == FACE_TTY_DEFAULT_BG_COLOR
+      && STRINGP (attrs[LFACE_BACKGROUND_INDEX]))
     {
-      face->background = load_color (c->f, face,
+      face->background = load_color (cache->f, face,
                                     attrs[LFACE_BACKGROUND_INDEX],
                                     LFACE_BACKGROUND_INDEX);
+#if defined (MSDOS) || defined (WINDOWSNT)
       /* If the background of the default face is the default color,
         use the background color defined by the frame.  */
-      if (face->background == FACE_TTY_DEFAULT_COLOR)
+#ifdef MSDOS
+      if (FRAME_MSDOS_P (cache->f))
        {
-         face->background = FRAME_BACKGROUND_PIXEL (f);
-         attrs[LFACE_BACKGROUND_INDEX] =
-           build_string (msdos_stdcolor_name (face->background));
+#endif /* MSDOS */
+
+         if (face->background == FACE_TTY_DEFAULT_BG_COLOR
+             || face->background == FACE_TTY_DEFAULT_COLOR)
+           {
+             face->background = FRAME_BACKGROUND_PIXEL (cache->f);
+             attrs[LFACE_BACKGROUND_INDEX] =
+               tty_color_name (cache->f, face->background);
+             face_colors_defaulted = 1;
+           }
+         else if (face->background == FACE_TTY_DEFAULT_FG_COLOR)
+           {
+             face->background = FRAME_FOREGROUND_PIXEL (cache->f);
+             attrs[LFACE_BACKGROUND_INDEX] =
+               tty_color_name (cache->f, face->background);
+             face_colors_defaulted = 1;
+           }
+#ifdef MSDOS
        }
+#endif
+#endif /* MSDOS or WINDOWSNT */
     }
 
-  /* Swap colors if face is inverse-video.  */
-  if (face->tty_reverse_p)
+  /* 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.  */
+  if (face->tty_reverse_p && !face_colors_defaulted)
     {
       unsigned long tem = face->foreground;
 
       face->foreground = face->background;
       face->background = tem;
     }
-#endif
-
-  return face;
-}
-
 
-DEFUN ("face-register-tty-color", Fface_register_tty_color,
-       Sface_register_tty_color, 2, 2, 0,
-  "Say that COLOR is color number NUMBER on the terminal.\n\
-COLOR is a string, the color name.  Value is COLOR.")
-  (color, number)
-     Lisp_Object color, number;
-{
-  Lisp_Object entry;
-  
-  CHECK_STRING (color, 0);
-  CHECK_NUMBER (number, 1);
-  entry = Fassoc (color, Vface_tty_color_alist);
-  if (NILP (entry))
-    Vface_tty_color_alist = Fcons (Fcons (color, number),
-                                  Vface_tty_color_alist);
-  else
-    Fsetcdr (entry, number);
-  return color;
-}
+  if (tty_suppress_bold_inverse_default_colors_p
+      && face->tty_bold_p
+      && face->background == FACE_TTY_DEFAULT_FG_COLOR
+      && face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
+    face->tty_bold_p = 0;
 
-
-DEFUN ("face-clear-tty-colors", Fface_clear_tty_colors,
-       Sface_clear_tty_colors, 0, 0, 0,
-  "Unregister all registered tty colors.")
-  ()
-{
-  return Vface_tty_color_alist = Qnil;
+  return face;
 }
 
 
-DEFUN ("tty-defined-colors", Ftty_defined_colors,
-       Stty_defined_colors, 0, 0, 0,
-  "Return a list of registered tty colors.")
-  ()
+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)
+     Lisp_Object suppress;
 {
-  Lisp_Object list, colors;
-
-  colors = Qnil;
-  for (list = Vface_tty_color_alist; CONSP (list); list = XCDR (list))
-    colors = Fcons (XCAR (XCAR (list)), colors);
-
-  return colors;
+  tty_suppress_bold_inverse_default_colors_p = !NILP (suppress);
+  ++face_change_count;
+  return suppress;
 }
 
 
@@ -5788,19 +6264,22 @@ compute_char_face (f, ch, prop)
      Lisp_Object prop;
 {
   int face_id;
-  int charset = (NILP (current_buffer->enable_multibyte_characters)
-                ? -1
-                : CHAR_CHARSET (ch));
-  
+
+  if (NILP (current_buffer->enable_multibyte_characters))
+    ch = -1;
+
   if (NILP (prop))
-    face_id = FACE_FOR_CHARSET (f, DEFAULT_FACE_ID, charset);
+    {
+      struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+      face_id = FACE_FOR_CHAR (f, face, ch);
+    }
   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);
       merge_face_vector_with_property (f, attrs, prop);
-      face_id = lookup_face (f, attrs, charset);
+      face_id = lookup_face (f, attrs, ch, NULL);
     }
 
   return face_id;
@@ -5820,9 +6299,7 @@ compute_char_face (f, ch, prop)
 
    If MOUSE is non-zero, use the character's mouse-face, not its face.
 
-   The face returned is suitable for displaying CHARSET_ASCII if
-   current_buffer->enable_multibyte_characters is non-nil.  Otherwise,
-   the face is suitable for displaying unibyte text.  */
+   The face returned is suitable for displaying ASCII characters.  */
 
 int
 face_at_buffer_position (w, pos, region_beg, region_end,
@@ -5874,7 +6351,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
     len = 40;
     overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
     noverlays = overlays_at (pos, 0, &overlay_vec, &len,
-                            &next_overlay, NULL);
+                            &next_overlay, NULL, 0);
 
     /* If there are more than 40, make enough space for all, and try
        again.  */
@@ -5883,7 +6360,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
        len = noverlays;
        overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
        noverlays = overlays_at (pos, 0, &overlay_vec, &len,
-                                &next_overlay, NULL);
+                                &next_overlay, NULL, 0);
       }
 
     if (next_overlay < endpos)
@@ -5893,14 +6370,11 @@ face_at_buffer_position (w, pos, region_beg, region_end,
   *endptr = endpos;
 
   default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
-  
+
   /* Optimize common cases where we can use the default face.  */
   if (noverlays == 0
       && NILP (prop)
-      && !(pos >= region_beg && pos < region_end)
-      && (multibyte_p
-         || !FRAME_WINDOW_P (f)
-         || FACE_SUITABLE_FOR_CHARSET_P (default_face, -1)))
+      && !(pos >= region_beg && pos < region_end))
     return DEFAULT_FACE_ID;
 
   /* Begin with attributes from the default face.  */
@@ -5932,7 +6406,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
     {
       Lisp_Object region_face = lface_from_face_name (f, Qregion, 0);
       merge_face_vectors (XVECTOR (region_face)->contents, attrs);
+
       if (region_end < endpos)
        endpos = region_end;
     }
@@ -5940,13 +6414,13 @@ face_at_buffer_position (w, pos, region_beg, region_end,
   *endptr = endpos;
 
   /* Look up a realized face with the given face attributes,
-     or realize a new one.  Charset is ignored for tty frames.  */
-  return lookup_face (f, attrs, multibyte_p ? CHARSET_ASCII : -1);
+     or realize a new one for ASCII characters.  */
+  return lookup_face (f, attrs, 0, NULL);
 }
 
 
 /* Compute the face at character position POS in Lisp string STRING on
-   window W, for charset CHARSET_ASCII.
+   window W, for ASCII characters.
 
    If STRING is an overlay string, it comes from position BUFPOS in
    current_buffer, otherwise BUFPOS is zero to indicate that STRING is
@@ -5956,14 +6430,13 @@ face_at_buffer_position (w, pos, region_beg, region_end,
    id of the basic face to merge with.  It is usually equal to
    DEFAULT_FACE_ID but can be MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID
    for strings displayed in the mode or top line.
-   
+
    Set *ENDPTR to the next position where to check for faces in
    STRING; -1 if the face is constant from POS to the end of the
    string.
 
    Value is the id of the face to use.  The face returned is suitable
-   for displaying CHARSET_ASCII if STRING is multibyte.  Otherwise,
-   the face is suitable for displaying unibyte text.  */
+   for displaying ASCII characters.  */
 
 int
 face_at_string_position (w, string, pos, bufpos, region_beg,
@@ -6016,7 +6489,7 @@ face_at_string_position (w, string, pos, bufpos, region_beg,
             if we don't have fonts, so we can stop here if not working
             on a window-system frame.  */
          || !FRAME_WINDOW_P (f)
-         || FACE_SUITABLE_FOR_CHARSET_P (base_face, -1)))
+         || FACE_SUITABLE_FOR_CHAR_P (base_face, 0)))
     return base_face->id;
 
   /* Begin with attributes from the base face.  */
@@ -6036,8 +6509,8 @@ 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.  */
-  return lookup_face (f, attrs, multibyte_p ? CHARSET_ASCII : -1);
+     or realize a new one for ASCII characters.  */
+  return lookup_face (f, attrs, 0, NULL);
 }
 
 
@@ -6087,7 +6560,7 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
   if (NILP (n))
     {
       int i;
-      
+
       fprintf (stderr, "font selection order: ");
       for (i = 0; i < DIM (font_sort_order); ++i)
        fprintf (stderr, "%d ", font_sort_order[i]);
@@ -6096,20 +6569,20 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, "")
       fprintf (stderr, "alternative fonts: ");
       debug_print (Vface_alternative_font_family_alist);
       fprintf (stderr, "\n");
-       
-      for (i = 0; i < FRAME_FACE_CACHE (selected_frame)->used; ++i)
+
+      for (i = 0; i < FRAME_FACE_CACHE (SELECTED_FRAME ())->used; ++i)
        Fdump_face (make_number (i));
     }
   else
     {
       struct face *face;
       CHECK_NUMBER (n, 0);
-      face = FACE_FROM_ID (selected_frame, XINT (n));
+      face = FACE_FROM_ID (SELECTED_FRAME (), XINT (n));
       if (face == NULL)
        error ("Not a valid face");
       dump_realized_face (face);
     }
-  
+
   return Qnil;
 }
 
@@ -6137,8 +6610,10 @@ syms_of_xfaces ()
 {
   Qface = intern ("face");
   staticpro (&Qface);
-  Qpixmap_spec_p = intern ("pixmap-spec-p");
-  staticpro (&Qpixmap_spec_p);
+  Qbitmap_spec_p = intern ("bitmap-spec-p");
+  staticpro (&Qbitmap_spec_p);
+  Qframe_update_face_colors = intern ("frame-update-face-colors");
+  staticpro (&Qframe_update_face_colors);
 
   /* Lisp face attribute keywords.  */
   QCfamily = intern (":family");
@@ -6152,7 +6627,7 @@ syms_of_xfaces ()
   QCunderline = intern (":underline");
   staticpro (&QCunderline);
   QCinverse_video = intern (":inverse-video");
-  staticpro (&QCinverse_video); 
+  staticpro (&QCinverse_video);
   QCreverse_video = intern (":reverse-video");
   staticpro (&QCreverse_video);
   QCforeground = intern (":foreground");
@@ -6236,29 +6711,44 @@ syms_of_xfaces ()
   Qunspecified = intern ("unspecified");
   staticpro (&Qunspecified);
 
-  Qx_charset_registry = intern ("x-charset-registry");
-  staticpro (&Qx_charset_registry);
+  Qface_alias = intern ("face-alias");
+  staticpro (&Qface_alias);
   Qdefault = intern ("default");
   staticpro (&Qdefault);
-  Qmodeline = intern ("modeline");
-  staticpro (&Qmodeline);
   Qtool_bar = intern ("tool-bar");
   staticpro (&Qtool_bar);
   Qregion = intern ("region");
   staticpro (&Qregion);
-  Qmargin = intern ("margin");
-  staticpro (&Qmargin);
+  Qfringe = intern ("fringe");
+  staticpro (&Qfringe);
   Qheader_line = intern ("header-line");
   staticpro (&Qheader_line);
+  Qscroll_bar = intern ("scroll-bar");
+  staticpro (&Qscroll_bar);
+  Qmenu = intern ("menu");
+  staticpro (&Qmenu);
+  Qcursor = intern ("cursor");
+  staticpro (&Qcursor);
+  Qborder = intern ("border");
+  staticpro (&Qborder);
+  Qmouse = intern ("mouse");
+  staticpro (&Qmouse);
+  Qtty_color_desc = intern ("tty-color-desc");
+  staticpro (&Qtty_color_desc);
+  Qtty_color_by_index = intern ("tty-color-by-index");
+  staticpro (&Qtty_color_by_index);
+
+  Vface_alternative_font_family_alist = Qnil;
+  staticpro (&Vface_alternative_font_family_alist);
 
   defsubr (&Sinternal_make_lisp_face);
   defsubr (&Sinternal_lisp_face_p);
   defsubr (&Sinternal_set_lisp_face_attribute);
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   defsubr (&Sinternal_set_lisp_face_attribute_from_resource);
-  defsubr (&Sface_color_gray_p);
-  defsubr (&Sface_color_supported_p);
 #endif
+  defsubr (&Scolor_gray_p);
+  defsubr (&Scolor_supported_p);
   defsubr (&Sinternal_get_lisp_face_attribute);
   defsubr (&Sinternal_lisp_face_attribute_values);
   defsubr (&Sinternal_lisp_face_equal_p);
@@ -6274,6 +6764,11 @@ syms_of_xfaces ()
   defsubr (&Sshow_face_resources);
 #endif /* GLYPH_DEBUG */
   defsubr (&Sclear_face_cache);
+  defsubr (&Stty_suppress_bold_inverse_default_colors);
+
+#if defined DEBUG_X_COLORS && defined HAVE_X_WINDOWS
+  defsubr (&Sdump_colors);
+#endif
 
   DEFVAR_LISP ("font-list-limit", &Vfont_list_limit,
     "*Limit for font matching.\n\
@@ -6284,7 +6779,7 @@ that number of fonts when searching for a matching font.");
   DEFVAR_LISP ("face-new-frame-defaults", &Vface_new_frame_defaults,
     "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\
@@ -6292,40 +6787,28 @@ instead of shades of gray for a face background color.\n\
 See `set-face-stipple' for possible values for this variable.");
   Vface_default_stipple = build_string ("gray3");
 
-  DEFVAR_LISP ("face-default-registry", &Vface_default_registry,
-    "Default registry and encoding to use.\n\
-This registry and encoding is used for unibyte text.  It is set up\n\
-from the specified frame font when Emacs starts. (For internal use only.)");
-  Vface_default_registry = Qnil;
-
-  DEFVAR_LISP ("face-alternative-font-family-alist",
-              &Vface_alternative_font_family_alist, "");
-  Vface_alternative_font_family_alist = Qnil;
-
 #if SCALABLE_FONTS
-  
+
   DEFVAR_LISP ("scalable-fonts-allowed", &Vscalable_fonts_allowed,
     "Allowed scalable fonts.\n\
 A value of nil means don't allow any scalable fonts.\n\
 A value of t means allow any scalable font.\n\
 Otherwise, value must be a list of regular expressions.  A font may be\n\
 scaled if its name matches a regular expression in the list.");
+#ifdef WINDOWSNT
+  /* Windows uses mainly truetype fonts, so disallowing scalable fonts
+     by default limits the fonts available severely. */
+  Vscalable_fonts_allowed = Qt;
+#else
   Vscalable_fonts_allowed = Qnil;
-  
+#endif
 #endif /* SCALABLE_FONTS */
 
-#ifdef HAVE_X_WINDOWS
-  defsubr (&Spixmap_spec_p);
+#ifdef HAVE_WINDOW_SYSTEM
+  defsubr (&Sbitmap_spec_p);
   defsubr (&Sx_list_fonts);
   defsubr (&Sinternal_face_x_get_resource);
-  defsubr (&Sx_font_list);
+  defsubr (&Sx_family_fonts);
   defsubr (&Sx_font_family_list);
-#endif /* HAVE_X_WINDOWS */
-
-  /* TTY face support.  */
-  defsubr (&Sface_register_tty_color);
-  defsubr (&Sface_clear_tty_colors);
-  defsubr (&Stty_defined_colors);
-  Vface_tty_color_alist = Qnil;
-  staticpro (&Vface_tty_color_alist);
+#endif /* HAVE_WINDOW_SYSTEM */
 }