# HG changeset patch # User Jim Blandy # Date 736993517 0 # Node ID 139740855fa6f90099ee881ac5cfb92b3a967c8b # Parent 76afd3322533458a57cb16d2f86246f2223b6831 * 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. diff -r 76afd3322533 -r 139740855fa6 src/xfaces.c --- 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 */ /* Appears not to be used */ #include -/* 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 */ +