diff src/xfaces.c @ 2730:139740855fa6

* xfaces.c (Fmake_face_internal): Do nothing for non-X frames. * dispextern.h (struct face): Add cached_index member. * xfaces.c (get_cached_face): Use it to avoid unnecessary searches of face_vector. * xfaces.c (intern_face): Renamed from get_display_face. * xfns.c (x_make_gc): After building the GC's for the frame, call init_frame_faces to set up the first two faces. * xfaces.c (init_frame_faces): Don't just try to copy the default and mode line faces from some other random frame; instead, consult the normal_gc and reverse_gc members of the frame, and build the faces based on their parameters. Adjust the face computation functions to return frame face ID's, not pointers to display faces; since we call these functions during display construction, we don't want the display faces yet. * xfaces.c (intern_frame_face): New function. (compute_char_face, compute_glyph_face): Apply intern_frame_face to the computed face, and return the frame face's ID, instead of calling intern_face and returning a pointer to a display frame. * xfaces.c: Describe the facial data structures. It took me a while to figure them out; perhaps this will save someone else the trouble. * xfaces.c (get_display_face): Use face_eql instead of writing it out.
author Jim Blandy <jimb@redhat.com>
date Mon, 10 May 1993 00:25:17 +0000
parents 78420d74d47f
children ddc49d5eee56
line wrap: on
line diff
--- a/src/xfaces.c	Mon May 10 00:23:47 1993 +0000
+++ b/src/xfaces.c	Mon May 10 00:25:17 1993 +0000
@@ -1,4 +1,4 @@
-/* "Face" primitives
+/* "Face" primitives.
    Copyright (C) 1992, 1993 Free Software Foundation.
 
 This file is part of GNU Emacs.
@@ -25,6 +25,8 @@
 #include "config.h"
 #include "lisp.h"
 
+#ifdef HAVE_X_WINDOWS
+
 #include "xterm.h"
 #include "buffer.h"
 #include "dispextern.h"
@@ -38,24 +40,89 @@
 /* #include <X11/Xmu/Drawing.h> */  /* Appears not to be used */
 #include <X11/Xos.h>
 
-/* We use face structures in two ways:
-   At the frame level, each frame has a vector of faces (FRAME_FACES).
-   Face number 0 is the default face (for normal text).
-   Face number 1 is the mode line face.
-   Higher face numbers have no built-in meaning.
-   The faces in these vectors are called "frame faces".
+
+/* An explanation of the face data structures.  */
+
+/* ========================= Face Data Structures =========================
+
+   All lisp code uses symbols as face names.
+
+   Each frame has a face_alist member (with the frame-face-alist and
+   set-frame-face-alist accessors), associating the face names with
+   vectors of the form 
+       [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
+   where
+       face is the symbol `face',
+       NAME is the symbol with which this vector is associated (a backpointer),
+       ID is the face ID, an integer used internally by the C code to identify
+           the face,
+       FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
+           to use with the face,
+       BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
+           use right now, and
+       UNDERLINE-P is non-nil if the face should be underlined.
+   (lisp/faces.el maintains these association lists.)
+
+   The frames' private alists hold the frame-local definitions for the
+   faces.  The lisp variable global-face-data contains the global
+   defaults for faces.  (See lisp/faces.el for this too.)
+
+   In the C code, we also have a `struct face' with the elements
+      `foreground', `background', `font', and `underline',
+   which specify its visual appearance, and elements
+      `gc' and `cached_index';
+   `gc' may be an X GC which has been built for the given display
+   parameters.  Faces with GC's are called `display faces'.  Whether
+   or not a face has a GC depends on what data structure the face is
+   in; we explain these more below.  (See src/dispextern.h.)
 
-   Faces number 0 and 1 have graphics contexts.
-   They can be used in the redisplay code directly.
-   Higher numbered frame faces do not have graphics contexts.
+   Each frame also has members called `faces' and `n_faces' (with the
+   accessors FRAME_FACES and FRAME_N_FACES), which define an array of
+   struct face pointers, indexed by face ID (element 2 of the
+   vector).  These are called "frame faces".
+      Element 0 is the default face --- the one used for normal text.
+      Element 1 is the modeline face.
+   These faces have their GC's set; the rest do not.  (See src/xterm.h.)
+
+   The global variables `face_vector' and `nfaces' define another
+   array of struct face pointers, with their GC's set.  This array
+   acts as a cache of GC's to be used by all frames.  The function
+   `intern_face', passed a struct face *, searches face_vector for a
+   struct face with the same parameters, adds a new one with a GC if
+   it doesn't find one, and returns it.  If you have a `struct face',
+   and you want a GC for it, call intern_face on that struct, and it
+   will return a `struct face *' with its GC set.  The faces in
+   face_vector are called `cached faces.' (See src/xfaces.c.)
 
-   There are also "cached faces".  They have graphics contexts.
-   They are kept in a C vector called face_vector.
+   The `GLYPH' data type is an unsigned integer type; the bottom byte
+   is a character code, and the byte above that is a face id.  The
+   `struct frame_glyphs' structure, used to describe frames' current
+   or desired contents, is essentially a matrix of GLYPHs; the face
+   ID's in a struct frame_glyphs are indices into FRAME_FACES.  (See
+   src/dispextern.h.)
 
-   A "display face" is a face with a graphics context.
-   It is either a frame face number 0 or 1,
-   or a cached face.  */
+   Some subtleties:
    
+   Since face_vector is just a cache --- there are no pointers into it
+   from the rest of the code, and everyone accesses it through
+   intern_face --- we could just free its GC's and throw the whole
+   thing away without breaking anything.  This gives us a simple way
+   to garbage-collect old GC's nobody's using any more - we can just
+   purge face_vector, and then let subsequent calls to intern_face
+   refill it as needed.  The function clear_face_vector performs this
+   purge.
+
+   We're often applying intern_face to faces in frames' local arrays -
+   for example, we do this while sending GLYPHs from a struct
+   frame_glyphs to X during redisplay.  It would be nice to avoid
+   searching all of face_vector every time we intern a frame's face.
+   So, when intern_face finds a match for FACE in face_vector, it
+   stores the index of the match in FACE's cached_index member, and
+   checks there first next time.  */
+   
+
+/* Definitions and declarations.  */
+
 /* A table of display faces.  */
 struct face **face_vector;
 /* The length in use of the table.  */
@@ -70,14 +137,28 @@
 
 Lisp_Object Qface, Qwindow, Qpriority;
 
-static struct face *allocate_face ();
 static void build_face ();
-static int sort_overlays ();
-static struct face *get_display_face ();
 static Lisp_Object face_name_id_number ();
+
+struct face *intern_face ();
+static void ensure_face_ready ();
 
+/* Allocating, copying, and comparing struct faces.  */
+
+/* Allocate a new face */
+static struct face *
+allocate_face ()
+{
+  struct face *result = (struct face *) xmalloc (sizeof (struct face));
+  bzero (result, sizeof (struct face));
+  result->font = (XFontStruct *) FACE_DEFAULT;
+  result->foreground = FACE_DEFAULT;
+  result->background = FACE_DEFAULT;
+  result->stipple = FACE_DEFAULT;
+  return result;
+}
+
 /* Make a new face that's a copy of an existing one.  */
-
 static struct face *
 copy_face (face)
      struct face *face;
@@ -97,18 +178,18 @@
 face_eql (face1, face2)
      struct face *face1, *face2;
 {
-  return (face1->font == face2->font
+  return (   face1->font       == face2->font
 	  && face1->foreground == face2->foreground
 	  && face1->background == face2->background
-	  && face1->stipple == face2->stipple
-	  && face1->underline == face2->underline);
+	  && face1->stipple    == face2->stipple
+	  && face1->underline  == face2->underline);
 }
+
+/* Interning faces in the `face_vector' cache, and clearing that cache.  */
 
 /* Return the unique display face corresponding to the user-level face FACE.
-
    If there isn't one, make one, and find a slot in the face_vector to
    put it in.  */
-
 static struct face *
 get_cached_face (f, face)
      struct frame *f;
@@ -117,6 +198,13 @@
   int i, empty = -1;
   struct face *result;
 
+  /* Perhaps FACE->cached_index is valid; this could happen if FACE is
+     in a frame's face list.  */
+  if (face->cached_index >= 0
+      && face->cached_index < nfaces
+      && face_eql (face_vector[face->cached_index], face))
+    return face_vector[face->cached_index];
+
   /* Look for an existing display face that does the job.
      Also find an empty slot if any.   */
   for (i = 0; i < nfaces; i++)
@@ -150,6 +238,40 @@
   return result;
 }
 
+/* Given a frame face, return an equivalent display face
+   (one which has a graphics context).  */
+
+struct face *
+intern_face (f, face)
+     struct frame *f;
+     struct face *face;
+{
+  struct face *result;
+
+  /* Does the face have a GC already?  */
+  if (face->gc)
+    return face;
+  
+  /* If it's equivalent to the default face, use that.  */
+  if (face_eql (face, FRAME_DEFAULT_FACE (f)))
+    {
+      if (!FRAME_DEFAULT_FACE (f)->gc)
+	build_face (f, FRAME_DEFAULT_FACE (f));
+      return FRAME_DEFAULT_FACE (f);
+    }
+  
+  /* If it's equivalent to the mode line face, use that.  */
+  if (face_eql (face, FRAME_MODE_LINE_FACE (f)))
+    {
+      if (!FRAME_MODE_LINE_FACE (f)->gc)
+	build_face (f, FRAME_MODE_LINE_FACE (f));
+      return FRAME_MODE_LINE_FACE (f);
+    }
+
+  /* Get a specialized display face.  */
+  return get_cached_face (f, face);
+}
+
 /* Clear out face_vector and start anew.
    This should be done from time to time just to avoid
    keeping too many graphics contexts in face_vector
@@ -176,13 +298,14 @@
   UNBLOCK_INPUT;
 }
 
+/* Allocating and freeing X resources for display faces.  */
+
 /* Make a graphics context for face FACE, which is on frame F,
    if that can be done.  */
-
 static void
 build_face (f, face)
-     struct frame* f;
-     struct face* face;
+     struct frame *f;
+     struct face *face;
 {
   GC gc;
   XGCValues xgcv;
@@ -210,10 +333,249 @@
 #endif
   face->gc = gc;
 }
+
+/* Allocating, freeing, and duplicating fonts, colors, and pixmaps.  */
+
+static XFontStruct *
+load_font (f, name)
+     struct frame *f;
+     Lisp_Object name;
+{
+  XFontStruct *font;
+
+  if (NILP (name))
+    return (XFontStruct *) FACE_DEFAULT;
+
+  CHECK_STRING (name, 0);
+  BLOCK_INPUT;
+  font = XLoadQueryFont (x_current_display, (char *) XSTRING (name)->data);
+  UNBLOCK_INPUT;
+
+  if (! font)
+    Fsignal (Qerror, Fcons (build_string ("undefined font"),
+			    Fcons (name, Qnil)));
+  return font;
+}
+
+static void
+unload_font (f, font)
+     struct frame *f;
+     XFontStruct *font;
+{
+  if (!font || font == ((XFontStruct *) FACE_DEFAULT))
+    return;
+  XFreeFont (x_current_display, font);
+}
+
+static unsigned long
+load_color (f, name)
+     struct frame *f;
+     Lisp_Object name;
+{
+  Display *dpy = x_current_display;
+  Colormap cmap;
+  XColor color;
+  int result;
+
+  if (NILP (name))
+    return FACE_DEFAULT;
+
+  cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
+
+  CHECK_STRING (name, 0);
+  BLOCK_INPUT;
+  result = XParseColor (dpy, cmap, (char *) XSTRING (name)->data, &color);
+  UNBLOCK_INPUT;
+  if (! result)
+    Fsignal (Qerror, Fcons (build_string ("undefined color"),
+			    Fcons (name, Qnil)));
+  BLOCK_INPUT;
+  result = XAllocColor (dpy, cmap, &color);
+  UNBLOCK_INPUT;
+  if (! result)
+    Fsignal (Qerror, Fcons (build_string ("X server cannot allocate color"),
+			    Fcons (name, Qnil)));
+  return (unsigned long) color.pixel;
+}
+
+static void
+unload_color (f, pixel)
+     struct frame *f;
+     Pixel pixel;
+{
+  Colormap cmap;
+  Display *dpy = x_current_display;
+  if (pixel == FACE_DEFAULT)
+    return;
+  cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
+  BLOCK_INPUT;
+  XFreeColors (dpy, cmap, &pixel, 1, 0);
+  UNBLOCK_INPUT;
+}
 
+/* Initializing face arrays for frames. */
+
+/* Set up faces 0 and 1 based on the normal text and modeline GC's.  */
+void
+init_frame_faces (f)
+     struct frame *f;
+{
+  ensure_face_ready (f, 0);
+  {
+    XGCValues gcv;
+    struct face *face = FRAME_FACES (f) [0];
+
+    XGetGCValues (x_current_display, f->display.x->normal_gc,
+		  GCForeground | GCBackground | GCFont, &gcv);
+    face->gc         = f->display.x->normal_gc;
+    face->foreground = gcv.foreground;
+    face->background = gcv.background;
+    face->font       = XQueryFont (x_current_display, gcv.font);
+    face->stipple = 0;
+    face->underline = 0;
+  }
+
+  ensure_face_ready (f, 1);
+  {
+    XGCValues gcv;
+    struct face *face = FRAME_FACES (f) [1];
+
+    XGetGCValues (x_current_display, f->display.x->reverse_gc,
+		  GCForeground | GCBackground | GCFont, &gcv);
+    face->gc         = f->display.x->reverse_gc;
+    face->foreground = gcv.foreground;
+    face->background = gcv.background;
+    face->font       = XQueryFont (x_current_display, gcv.font);
+    face->stipple = 0;
+    face->underline = 0;
+  }
+}
+
+#if 0
+void
+init_frame_faces (f)
+     struct frame *f;
+{
+  struct frame *other_frame = 0;
+  Lisp_Object rest;
+
+  for (rest = Vframe_list; !NILP (rest); rest = Fcdr (rest))
+    {
+      struct frame *f2 = XFRAME (Fcar (rest));
+      if (f2 != f && FRAME_X_P (f2))
+	{
+	  other_frame = f2;
+	  break;
+	}
+    }
+
+  if (other_frame)
+    {
+      /* Make sure this frame's face vector is as big as the others.  */
+      FRAME_N_FACES (f) = FRAME_N_FACES (other_frame);
+      FRAME_FACES (f)
+	= (struct face **) xmalloc (FRAME_N_FACES (f) * sizeof (struct face *));
+
+      /* Make sure the frame has the two basic faces.  */
+      FRAME_DEFAULT_FACE (f)
+	= copy_face (FRAME_DEFAULT_FACE (other_frame));
+      FRAME_MODE_LINE_FACE (f)
+	= copy_face (FRAME_MODE_LINE_FACE (other_frame));
+    }
+}
+#endif
+
+
+/* Called from Fdelete_frame.  */
+void
+free_frame_faces (f)
+     struct frame *f;
+{
+  Display *dpy = x_current_display;
+  int i;
+
+  for (i = 0; i < FRAME_N_FACES (f); i++)
+    {
+      struct face *face = FRAME_FACES (f) [i];
+      if (! face)
+        continue;
+      if (face->gc)
+	XFreeGC (dpy, face->gc);
+      unload_font (f, face->font);
+      unload_color (f, face->foreground);
+      unload_color (f, face->background);
+#if 0
+      unload_pixmap (f, face->stipple);
+#endif
+      xfree (face);
+    }
+  xfree (FRAME_FACES (f));
+  FRAME_FACES (f) = 0;
+  FRAME_N_FACES (f) = 0;
+}
+
+/* Interning faces in a frame's face array.  */
+
+/* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't
+   find one.  */
+int
+intern_frame_face (new_face, frame)
+     struct face *new_face;
+     struct frame *frame;
+{
+  int len = FRAME_N_FACES (frame);
+  int i;
+
+  /* Search for a face already on FRAME equivalent to FACE.  */
+  for (i = 0; i < len; i++)
+    {
+      struct face *frame_face = FRAME_FACES (frame)[i];
+      
+      if (frame_face && face_eql (new_face, frame_face))
+	return i;
+    }
+
+  /* We didn't find one; add a new one.  */
+  i = next_face_id++;
+
+  ensure_face_ready (frame, i);
+  bcopy (new_face, FRAME_FACES (frame)[i], sizeof (new_face));
+
+  return i;
+}
+
+/* Make face id ID valid on frame F.  */
+
+static void
+ensure_face_ready (f, id)
+     struct frame *f;
+     int id;
+{
+  if (FRAME_N_FACES (f) <= id)
+    {
+      int n = id + 10;
+      int i;
+      if (!FRAME_N_FACES (f))
+	FRAME_FACES (f)
+	  = (struct face **) xmalloc (sizeof (struct face *) * n);
+      else
+	FRAME_FACES (f)
+	  = (struct face **) xrealloc (FRAME_FACES (f),
+				       sizeof (struct face *) * n);
+
+      bzero (FRAME_FACES (f) + FRAME_N_FACES (f),
+	     (n - FRAME_N_FACES (f)) * sizeof (struct face *));
+      FRAME_N_FACES (f) = n;
+    }
+
+  if (FRAME_FACES (f) [id] == 0)
+    FRAME_FACES (f) [id] = allocate_face ();
+}
+
+/* Computing faces appropriate for a given piece of text in a buffer.  */
+
 /* Modify face TO by copying from FROM all properties which have
    nondefault settings.  */
-
 static void 
 merge_faces (from, to)
      struct face *from, *to;
@@ -239,12 +601,24 @@
   int priority;
 };
 
-/* Return the display face associated with a buffer position POS.
+static int
+sort_overlays (s1, s2)
+     struct sortvec *s1, *s2;
+{
+  if (s1->priority != s2->priority)
+    return s1->priority - s2->priority;
+  if (s1->beg != s2->beg)
+    return s1->beg - s2->beg;
+  if (s1->end != s2->end)
+    return s2->end - s1->end;
+  return 0;
+}
+
+/* Return the face ID associated with a buffer position POS.
    Store into *ENDPTR the position at which a different face is needed.
    This does not take account of glyphs that specify their own face codes.
    F is the frame in use for display, and W is the window.  */
-
-struct face *
+int
 compute_char_face (f, w, pos, endptr)
      struct frame *f;
      struct window *w;
@@ -273,7 +647,7 @@
 
   /* Optimize the default case.  */
   if (noverlays == 0 && NILP (prop))
-    return FRAME_DEFAULT_FACE (f);
+    return 0;
 
   bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (struct face));
 
@@ -351,28 +725,13 @@
 
   *endptr = endpos;
 
-  return get_display_face (f, &face);
+  return intern_frame_face (f, &face);
 }
 
-static int
-sort_overlays (s1, s2)
-     struct sortvec *s1, *s2;
-{
-  if (s1->priority != s2->priority)
-    return s1->priority - s2->priority;
-  if (s1->beg != s2->beg)
-    return s1->beg - s2->beg;
-  if (s1->end != s2->end)
-    return s2->end - s1->end;
-  return 0;
-}
-
-/* Return the display face to use to display a special glyph
-   which selects FACE_CODE as the face ID,
-   assuming that ordinarily the face would be BASIC_FACE.
-   F is the frame.  */
-
-struct face *
+/* Return the face ID to use to display a special glyph which selects
+   FACE_CODE as the face ID, assuming that ordinarily the face would
+   be BASIC_FACE.  F is the frame.  */
+int
 compute_glyph_face (f, basic_face, face_code)
      struct frame *f;
      struct face *basic_face;
@@ -386,243 +745,10 @@
       && FRAME_FACES (f) [face_code] != 0)
     merge_faces (FRAME_FACES (f) [face_code], &face);
 
-  return get_display_face (f, &face);
-}
-
-/* Given a frame face, return an equivalent display face
-   (one which has a graphics context).  */
-
-static struct face *
-get_display_face (f, face)
-     struct frame *f;
-     struct face *face;
-{
-  struct face *result;
-
-  /* Does the face have a GC already?  */
-  if (face->gc)
-    return face;
-  
-  /* If it's equivalent to the default face, use that.  */
-  if (face->font == FRAME_DEFAULT_FACE (f)->font
-      && face->foreground == FRAME_DEFAULT_FACE (f)->foreground
-      && face->background == FRAME_DEFAULT_FACE (f)->background
-      && face->stipple == FRAME_DEFAULT_FACE (f)->stipple
-      && face->underline == FRAME_DEFAULT_FACE (f)->underline)
-    {
-      if (!FRAME_DEFAULT_FACE (f)->gc)
-	build_face (f, FRAME_DEFAULT_FACE (f));
-      return FRAME_DEFAULT_FACE (f);
-    }
-
-  /* If it's equivalent to the mode line face, use that.  */
-  if (face->font == FRAME_MODE_LINE_FACE (f)->font
-      && face->foreground == FRAME_MODE_LINE_FACE (f)->foreground
-      && face->background == FRAME_MODE_LINE_FACE (f)->background
-      && face->stipple == FRAME_MODE_LINE_FACE (f)->stipple
-      && face->underline == FRAME_MODE_LINE_FACE (f)->underline)
-    {
-      if (!FRAME_MODE_LINE_FACE (f)->gc)
-	build_face (f, FRAME_MODE_LINE_FACE (f));
-      return FRAME_MODE_LINE_FACE (f);
-    }
-
-  /* Get a specialized display face.  */
-  return get_cached_face (f, face);
-}
-
-
-/* Allocate a new face */
-static struct face *
-allocate_face ()
-{
-  struct face *result = (struct face *) xmalloc (sizeof (struct face));
-  bzero (result, sizeof (struct face));
-  result->font = (XFontStruct *) FACE_DEFAULT;
-  result->foreground = FACE_DEFAULT;
-  result->background = FACE_DEFAULT;
-  result->stipple = FACE_DEFAULT;
-  return result;
-}
-
-/* Make face id ID valid on frame F.  */
-
-void
-ensure_face_ready (f, id)
-     struct frame *f;
-     int id;
-{
-  if (FRAME_N_FACES (f) <= id)
-    {
-      int n = id + 10;
-      int i;
-      if (!FRAME_N_FACES (f))
-	FRAME_FACES (f)
-	  = (struct face **) xmalloc (sizeof (struct face *) * n);
-      else
-	FRAME_FACES (f)
-	  = (struct face **) xrealloc (FRAME_FACES (f),
-				       sizeof (struct face *) * n);
-
-      bzero (FRAME_FACES (f) + FRAME_N_FACES (f),
-	     (n - FRAME_N_FACES (f)) * sizeof (struct face *));
-      FRAME_N_FACES (f) = n;
-    }
-
-  if (FRAME_FACES (f) [id] == 0)
-    FRAME_FACES (f) [id] = allocate_face ();
+  return intern_frame_face (f, &face);
 }
 
-/* Allocating, freeing, and duplicating fonts, colors, and pixmaps.  */
-
-#ifdef HAVE_X_WINDOWS
-
-static XFontStruct *
-load_font (f, name)
-     struct frame *f;
-     Lisp_Object name;
-{
-  XFontStruct *font;
-
-  if (NILP (name))
-    return (XFontStruct *) FACE_DEFAULT;
-
-  CHECK_STRING (name, 0);
-  BLOCK_INPUT;
-  font = XLoadQueryFont (x_current_display, (char *) XSTRING (name)->data);
-  UNBLOCK_INPUT;
-
-  if (! font)
-    Fsignal (Qerror, Fcons (build_string ("undefined font"),
-			    Fcons (name, Qnil)));
-  return font;
-}
-
-static void
-unload_font (f, font)
-     struct frame *f;
-     XFontStruct *font;
-{
-  if (!font || font == ((XFontStruct *) FACE_DEFAULT))
-    return;
-  XFreeFont (x_current_display, font);
-}
-
-static unsigned long
-load_color (f, name)
-     struct frame *f;
-     Lisp_Object name;
-{
-  Display *dpy = x_current_display;
-  Colormap cmap;
-  XColor color;
-  int result;
-
-  if (NILP (name))
-    return FACE_DEFAULT;
-
-  cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
-
-  CHECK_STRING (name, 0);
-  BLOCK_INPUT;
-  result = XParseColor (dpy, cmap, (char *) XSTRING (name)->data, &color);
-  UNBLOCK_INPUT;
-  if (! result)
-    Fsignal (Qerror, Fcons (build_string ("undefined color"),
-			    Fcons (name, Qnil)));
-  BLOCK_INPUT;
-  result = XAllocColor (dpy, cmap, &color);
-  UNBLOCK_INPUT;
-  if (! result)
-    Fsignal (Qerror, Fcons (build_string ("X server cannot allocate color"),
-			    Fcons (name, Qnil)));
-  return (unsigned long) color.pixel;
-}
-
-static void
-unload_color (f, pixel)
-     struct frame *f;
-     Pixel pixel;
-{
-  Colormap cmap;
-  Display *dpy = x_current_display;
-  if (pixel == FACE_DEFAULT)
-    return;
-  cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
-  BLOCK_INPUT;
-  XFreeColors (dpy, cmap, &pixel, 1, 0);
-  UNBLOCK_INPUT;
-}
-
-#endif /* HAVE_X_WINDOWS */
-
-
-/* frames */
-
-void
-init_frame_faces (f)
-     struct frame *f;
-{
-  struct frame *other_frame = 0;
-  Lisp_Object rest;
-
-  for (rest = Vframe_list; !NILP (rest); rest = Fcdr (rest))
-    {
-      struct frame *f2 = XFRAME (Fcar (rest));
-      if (f2 != f && FRAME_X_P (f2))
-	{
-	  other_frame = f2;
-	  break;
-	}
-    }
-
-  if (other_frame)
-    {
-      /* Make sure this frame's face vector is as big as the others.  */
-      FRAME_N_FACES (f) = FRAME_N_FACES (other_frame);
-      FRAME_FACES (f)
-	= (struct face **) xmalloc (FRAME_N_FACES (f) * sizeof (struct face *));
-
-      /* Make sure the frame has the two basic faces.  */
-      FRAME_DEFAULT_FACE (f)
-	= copy_face (FRAME_DEFAULT_FACE (other_frame));
-      FRAME_MODE_LINE_FACE (f)
-	= copy_face (FRAME_MODE_LINE_FACE (other_frame));
-    }
-}
-
-
-/* Called from Fdelete_frame?  */
-
-void
-free_screen_faces (f)
-     struct frame *f;
-{
-  Display *dpy = x_current_display;
-  int i;
-
-  for (i = 0; i < FRAME_N_FACES (f); i++)
-    {
-      struct face *face = FRAME_FACES (f) [i];
-      if (! face)
-        continue;
-      if (face->gc)
-	XFreeGC (dpy, face->gc);
-      unload_font (f, face->font);
-      unload_color (f, face->foreground);
-      unload_color (f, face->background);
-#if 0
-      unload_pixmap (f, face->stipple);
-#endif
-      xfree (face);
-    }
-  xfree (FRAME_FACES (f));
-  FRAME_FACES (f) = 0;
-  FRAME_N_FACES (f) = 0;
-}
-
-
-/* Lisp interface */
+/* Lisp interface. */
 
 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
        "")
@@ -659,7 +785,8 @@
   for (rest = Vframe_list; !NILP (rest); rest = XCONS (rest)->cdr)
     {
       struct frame *f = XFRAME (XCONS (rest)->car);
-      ensure_face_ready (f, id);
+      if (FRAME_X_P (f))
+	ensure_face_ready (f, id);
     }
   return Qnil;
 }
@@ -774,6 +901,8 @@
   return XINT (tem);
 }
 
+/* Emacs initialization.  */
+
 void
 syms_of_xfaces ()
 {
@@ -790,3 +919,6 @@
   defsubr (&Sset_face_attribute_internal);
   defsubr (&Sinternal_next_face_id);
 }
+
+#endif /* HAVE_X_WINDOWS */
+