Update FSF's address in the preamble.
[bpt/emacs.git] / src / xfaces.c
CommitLineData
cb637678 1/* "Face" primitives.
3a22ee35 2 Copyright (C) 1993, 1994 Free Software Foundation.
7b7739b1 3
c115973b
JB
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
7b7739b1 8the Free Software Foundation; either version 2, or (at your option)
c115973b
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
c115973b 20
357f32fc 21/* This is derived from work by Lucid (some parts very loosely so). */
7b7739b1 22
c115973b
JB
23#include <sys/types.h>
24#include <sys/stat.h>
25
18160b98 26#include <config.h>
c115973b
JB
27#include "lisp.h"
28
87485d6f 29#ifdef HAVE_FACES
cb637678 30
87485d6f 31#ifdef HAVE_X_WINDOWS
c115973b 32#include "xterm.h"
87485d6f
MW
33#endif
34#ifdef MSDOS
35#include "dosfns.h"
36#endif
c115973b 37#include "buffer.h"
f211082d 38#include "dispextern.h"
7b7739b1 39#include "frame.h"
357f32fc 40#include "blockinput.h"
b6d40e46 41#include "window.h"
bde7c500 42#include "intervals.h"
c115973b 43
87485d6f 44#ifdef HAVE_X_WINDOWS
657070ac
JB
45/* Compensate for bug in Xos.h on some systems, on which it requires
46 time.h. On some such systems, Xos.h tries to redefine struct
47 timeval and struct timezone if USG is #defined while it is
48 #included. */
6233db35 49#ifdef XOS_NEEDS_TIME_H
657070ac 50
e11d186d 51#include <time.h>
657070ac
JB
52#undef USG
53#include <X11/Xos.h>
54#define USG
e11d186d 55#define __TIMEVAL__
e11d186d 56
657070ac 57#else
7a4d2269 58
c115973b
JB
59#include <X11/Xos.h>
60
657070ac 61#endif
87485d6f 62#endif /* HAVE_X_WINDOWS */
cb637678
JB
63\f
64/* An explanation of the face data structures. */
65
66/* ========================= Face Data Structures =========================
67
7b00de84 68 Let FACE-NAME be a symbol naming a face.
cb637678 69
7b00de84
JB
70 Let FACE-VECTOR be (assq FACE-NAME (frame-face-alist FRAME))
71 FACE-VECTOR is either nil, or a vector of the form
cb637678
JB
72 [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
73 where
74 face is the symbol `face',
75 NAME is the symbol with which this vector is associated (a backpointer),
76 ID is the face ID, an integer used internally by the C code to identify
77 the face,
78 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
79 to use with the face,
80 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
81 use right now, and
82 UNDERLINE-P is non-nil if the face should be underlined.
7b00de84
JB
83 If any of these elements are nil, that parameter is considered
84 unspecified; parameters from faces specified by lower-priority
85 overlays or text properties, or the parameters of the frame itself,
86 can show through. (lisp/faces.el maintains these lists.)
87
88 (assq FACE-NAME global-face-data) returns a vector describing the
89 global parameters for that face.
90
7556890b 91 Let PARAM-FACE be FRAME->output_data.x->param_faces[Faref (FACE-VECTOR, 2)].
7b00de84
JB
92 PARAM_FACE is a struct face whose members are the Xlib analogues of
93 the parameters in FACE-VECTOR. If an element of FACE-VECTOR is
94 nil, then the corresponding member of PARAM_FACE is FACE_DEFAULT.
95 These faces are called "parameter faces", because they're the ones
96 lisp manipulates to control what gets displayed. Elements 0 and 1
7556890b 97 of FRAME->output_data.x->param_faces are special - they describe the
7b00de84 98 default and mode line faces. None of the faces in param_faces have
8e6208c5 99 GC's. (See src/dispextern.h for the definition of struct face.
7b00de84
JB
100 lisp/faces.el maintains the isomorphism between face_alist and
101 param_faces.)
102
103 The functions compute_char_face and compute_glyph_face find and
104 combine the parameter faces associated with overlays and text
105 properties. The resulting faces are called "computed faces"; none
106 of their members are FACE_DEFAULT; they are completely specified.
107 They then call intern_compute_face to search
7556890b 108 FRAME->output_data.x->computed_faces for a matching face, add one if
7b00de84 109 none is found, and return the index into
7556890b 110 FRAME->output_data.x->computed_faces. FRAME's glyph matrices use these
7b00de84
JB
111 indices to record the faces of the matrix characters, and the X
112 display hooks consult compute_faces to decide how to display these
113 characters. Elements 0 and 1 of computed_faces always describe the
114 default and mode-line faces.
115
cd0bb842
RS
116 Each computed face belongs to a particular frame.
117
42120bc7
RS
118 Computed faces have graphics contexts some of the time.
119 intern_face builds a GC for a specified computed face
120 if it doesn't have one already.
121 clear_face_cache clears out the GCs of all computed faces.
122 This is done from time to time so that we don't hold on to
123 lots of GCs that are no longer needed.
7b00de84 124
195f798e
RS
125 If a computed face has 0 as its font,
126 it is unused, and can be reused by new_computed_face.
127
7b00de84
JB
128 Constraints:
129
130 Symbols naming faces must have associations on all frames; for any
131 FRAME, for all FACE-NAME, if (assq FACE-NAME (frame-face-alist
132 FRAME)) is non-nil, it must be non-nil for all frames.
133
134 Analogously, indices into param_faces must be valid on all frames;
135 if param_faces[i] is a non-zero face pointer on one frame, then it
136 must be filled in on all frames. Code assumes that face ID's can
137 be used on any frame.
cb637678
JB
138
139 Some subtleties:
7b7739b1 140
7b00de84
JB
141 Why do we keep param_faces and computed_faces separate?
142 computed_faces contains an element for every combination of facial
143 parameters we have ever displayed. indices into param_faces have
144 to be valid on all frames. If they were the same array, then that
145 array would grow very large on all frames, because any facial
146 combination displayed on any frame would need to be a valid entry
42120bc7 147 on all frames. */
cb637678
JB
148\f
149/* Definitions and declarations. */
150
c115973b 151/* The number of face-id's in use (same for all frames). */
f8758da5 152static int next_face_id;
c115973b 153
bc0db68d 154/* The number of the face to use to indicate the region. */
f8758da5 155static int region_face;
bc0db68d 156
9516fe94
RS
157/* This is what appears in a slot in a face to signify that the face
158 does not specify that display aspect. */
7b7739b1
JB
159#define FACE_DEFAULT (~0)
160
6f134486 161Lisp_Object Qface, Qmouse_face;
cd0bb842 162Lisp_Object Qpixmap_spec_p;
f211082d 163
415445e2 164int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
cb637678 165
415445e2 166struct face *intern_face ( /* FRAME_PTR, struct face * */ );
7b00de84
JB
167static int new_computed_face ( /* FRAME_PTR, struct face * */ );
168static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
415445e2 169static void ensure_face_ready ( /* FRAME_PTR, int id */ );
254a1b66 170void recompute_basic_faces ( /* FRAME_PTR f */ );
c115973b 171\f
cb637678
JB
172/* Allocating, copying, and comparing struct faces. */
173
174/* Allocate a new face */
175static struct face *
176allocate_face ()
177{
178 struct face *result = (struct face *) xmalloc (sizeof (struct face));
179 bzero (result, sizeof (struct face));
180 result->font = (XFontStruct *) FACE_DEFAULT;
181 result->foreground = FACE_DEFAULT;
182 result->background = FACE_DEFAULT;
183 result->stipple = FACE_DEFAULT;
184 return result;
185}
c115973b 186
cb637678 187/* Make a new face that's a copy of an existing one. */
c115973b
JB
188static struct face *
189copy_face (face)
190 struct face *face;
191{
192 struct face *result = allocate_face ();
193
194 result->font = face->font;
195 result->foreground = face->foreground;
196 result->background = face->background;
f211082d 197 result->stipple = face->stipple;
c115973b 198 result->underline = face->underline;
cd0bb842
RS
199 result->pixmap_h = face->pixmap_h;
200 result->pixmap_w = face->pixmap_w;
c115973b
JB
201
202 return result;
203}
204
205static int
206face_eql (face1, face2)
207 struct face *face1, *face2;
208{
cb637678 209 return ( face1->font == face2->font
c115973b
JB
210 && face1->foreground == face2->foreground
211 && face1->background == face2->background
cb637678
JB
212 && face1->stipple == face2->stipple
213 && face1->underline == face2->underline);
c115973b 214}
cb637678 215\f
42120bc7 216/* Managing graphics contexts of faces. */
c115973b 217
87485d6f 218#ifdef HAVE_X_WINDOWS
42120bc7 219/* Given a computed face, construct its graphics context if necessary. */
cb637678
JB
220
221struct face *
222intern_face (f, face)
223 struct frame *f;
224 struct face *face;
c115973b
JB
225{
226 GC gc;
227 XGCValues xgcv;
228 unsigned long mask;
229
42120bc7
RS
230 if (face->gc)
231 return face;
232
660ed669
JB
233 BLOCK_INPUT;
234
f211082d
JB
235 if (face->foreground != FACE_DEFAULT)
236 xgcv.foreground = face->foreground;
237 else
7556890b 238 xgcv.foreground = f->output_data.x->foreground_pixel;
660ed669 239
f211082d
JB
240 if (face->background != FACE_DEFAULT)
241 xgcv.background = face->background;
242 else
7556890b 243 xgcv.background = f->output_data.x->background_pixel;
660ed669 244
3f000d8c 245 if (face->font && face->font != (XFontStruct *) FACE_DEFAULT)
f211082d
JB
246 xgcv.font = face->font->fid;
247 else
7556890b 248 xgcv.font = f->output_data.x->font->fid;
660ed669 249
c115973b 250 xgcv.graphics_exposures = 0;
660ed669 251
c115973b 252 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
cd0bb842 253 if (face->stipple && face->stipple != FACE_DEFAULT)
95887807
RS
254 {
255 xgcv.fill_style = FillStippled;
256 xgcv.stipple = x_bitmap_pixmap (f, face->stipple);
257 mask |= GCFillStyle | GCStipple;
258 }
cd0bb842 259
42120bc7 260 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
c115973b 261 mask, &xgcv);
660ed669 262
f211082d 263 face->gc = gc;
660ed669
JB
264
265 UNBLOCK_INPUT;
42120bc7
RS
266
267 return face;
c115973b 268}
cb637678 269
42120bc7
RS
270/* Clear out all graphics contexts for all computed faces
271 except for the default and mode line faces.
272 This should be done from time to time just to avoid
273 keeping too many graphics contexts that are no longer needed. */
274
275void
276clear_face_cache ()
277{
278 Lisp_Object tail, frame;
279
280 BLOCK_INPUT;
281 FOR_EACH_FRAME (tail, frame)
282 {
283 FRAME_PTR f = XFRAME (frame);
284 if (FRAME_X_P (f))
285 {
286 int i;
287 Display *dpy = FRAME_X_DISPLAY (f);
288
289 for (i = 2; i < FRAME_N_COMPUTED_FACES (f); i++)
290 {
291 struct face *face = FRAME_COMPUTED_FACES (f) [i];
292 if (face->gc)
293 XFreeGC (dpy, face->gc);
294 face->gc = 0;
295 }
296 }
297 }
298
299 UNBLOCK_INPUT;
300}
301\f
cd0bb842
RS
302/* Allocating, freeing, and duplicating fonts, colors, and pixmaps.
303
304 These functions operate on param faces only.
305 Computed faces get their fonts, colors and pixmaps
306 by merging param faces. */
cb637678
JB
307
308static XFontStruct *
309load_font (f, name)
310 struct frame *f;
311 Lisp_Object name;
312{
313 XFontStruct *font;
314
315 if (NILP (name))
316 return (XFontStruct *) FACE_DEFAULT;
317
318 CHECK_STRING (name, 0);
319 BLOCK_INPUT;
42120bc7 320 font = XLoadQueryFont (FRAME_X_DISPLAY (f), (char *) XSTRING (name)->data);
cb637678
JB
321 UNBLOCK_INPUT;
322
323 if (! font)
324 Fsignal (Qerror, Fcons (build_string ("undefined font"),
325 Fcons (name, Qnil)));
326 return font;
327}
328
329static void
330unload_font (f, font)
331 struct frame *f;
332 XFontStruct *font;
333{
195f798e
RS
334 int len = FRAME_N_COMPUTED_FACES (f);
335 int i;
336
cb637678
JB
337 if (!font || font == ((XFontStruct *) FACE_DEFAULT))
338 return;
660ed669
JB
339
340 BLOCK_INPUT;
195f798e
RS
341 /* Invalidate any computed faces which use this font,
342 and free their GC's if they have any. */
f3400cf9 343 for (i = 2; i < len; i++)
195f798e
RS
344 {
345 struct face *face = FRAME_COMPUTED_FACES (f)[i];
346 if (face->font == font)
347 {
348 Display *dpy = FRAME_X_DISPLAY (f);
349 if (face->gc)
350 XFreeGC (dpy, face->gc);
351 face->gc = 0;
f3400cf9 352 /* This marks the computed face as available to reuse. */
195f798e
RS
353 face->font = 0;
354 }
355 }
356
42120bc7 357 XFreeFont (FRAME_X_DISPLAY (f), font);
660ed669 358 UNBLOCK_INPUT;
cb637678
JB
359}
360
361static unsigned long
362load_color (f, name)
363 struct frame *f;
364 Lisp_Object name;
365{
cb637678
JB
366 XColor color;
367 int result;
368
369 if (NILP (name))
370 return FACE_DEFAULT;
371
cb637678 372 CHECK_STRING (name, 0);
34dda5f4
KH
373 /* if the colormap is full, defined_color will return a best match
374 to the values in an an existing cell. */
a992f9d9 375 result = defined_color(f, (char *) XSTRING (name)->data, &color, 1);
cb637678
JB
376 if (! result)
377 Fsignal (Qerror, Fcons (build_string ("undefined color"),
378 Fcons (name, Qnil)));
cb637678
JB
379 return (unsigned long) color.pixel;
380}
381
382static void
383unload_color (f, pixel)
384 struct frame *f;
7a4d2269 385 unsigned long pixel;
cb637678
JB
386{
387 Colormap cmap;
42120bc7 388 Display *dpy = FRAME_X_DISPLAY (f);
828e66d1
RS
389 int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
390
32dc0866 391 if (pixel == FACE_DEFAULT
0704eec9
RS
392 || pixel == BLACK_PIX_DEFAULT (f)
393 || pixel == WHITE_PIX_DEFAULT (f))
cb637678 394 return;
42120bc7 395 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy));
828e66d1
RS
396
397 /* If display has an immutable color map, freeing colors is not
398 necessary and some servers don't allow it. So don't do it. */
399 if (! (class == StaticColor || class == StaticGray || class == TrueColor))
400 {
195f798e
RS
401 int len = FRAME_N_COMPUTED_FACES (f);
402 int i;
403
828e66d1 404 BLOCK_INPUT;
195f798e
RS
405 /* Invalidate any computed faces which use this color,
406 and free their GC's if they have any. */
f3400cf9 407 for (i = 2; i < len; i++)
195f798e
RS
408 {
409 struct face *face = FRAME_COMPUTED_FACES (f)[i];
410 if (face->foreground == pixel
411 || face->background == pixel)
412 {
413 Display *dpy = FRAME_X_DISPLAY (f);
414 if (face->gc)
415 XFreeGC (dpy, face->gc);
416 face->gc = 0;
f3400cf9 417 /* This marks the computed face as available to reuse. */
195f798e
RS
418 face->font = 0;
419 }
420 }
421
828e66d1
RS
422 XFreeColors (dpy, cmap, &pixel, 1, (unsigned long)0);
423 UNBLOCK_INPUT;
424 }
cd0bb842
RS
425}
426
427DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
ed791d5b
EN
428 "Return t if OBJECT is a valid pixmap specification.")
429 (object)
430 Lisp_Object object;
cd0bb842
RS
431{
432 Lisp_Object height, width;
433
ed791d5b
EN
434 return ((STRINGP (object)
435 || (CONSP (object)
436 && CONSP (XCONS (object)->cdr)
437 && CONSP (XCONS (XCONS (object)->cdr)->cdr)
438 && NILP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->cdr)
439 && (width = XCONS (object)->car, INTEGERP (width))
440 && (height = XCONS (XCONS (object)->cdr)->car, INTEGERP (height))
441 && STRINGP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)
cd0bb842
RS
442 && XINT (width) > 0
443 && XINT (height) > 0
444 /* The string must have enough bits for width * height. */
ed791d5b 445 && ((XSTRING (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)->size
68be917d 446 * (BITS_PER_INT / sizeof (int)))
e1befa75 447 >= XFASTINT (width) * XFASTINT (height))))
cd0bb842
RS
448 ? Qt : Qnil);
449}
450
451/* Load a bitmap according to NAME (which is either a file name
452 or a pixmap spec). Return the bitmap_id (see xfns.c)
453 or get an error if NAME is invalid.
454
455 Store the bitmap width in *W_PTR and height in *H_PTR. */
456
457static long
458load_pixmap (f, name, w_ptr, h_ptr)
7812a96f 459 FRAME_PTR f;
cd0bb842
RS
460 Lisp_Object name;
461 unsigned int *w_ptr, *h_ptr;
462{
463 int bitmap_id;
464 Lisp_Object tem;
465
466 if (NILP (name))
467 return FACE_DEFAULT;
468
469 tem = Fpixmap_spec_p (name);
470 if (NILP (tem))
471 wrong_type_argument (Qpixmap_spec_p, name);
472
473 BLOCK_INPUT;
474
475 if (CONSP (name))
476 {
477 /* Decode a bitmap spec into a bitmap. */
478
479 int h, w;
480 Lisp_Object bits;
481
482 w = XINT (Fcar (name));
483 h = XINT (Fcar (Fcdr (name)));
484 bits = Fcar (Fcdr (Fcdr (name)));
485
486 bitmap_id = x_create_bitmap_from_data (f, XSTRING (bits)->data,
487 w, h);
488 }
489 else
490 {
491 /* It must be a string -- a file name. */
492 bitmap_id = x_create_bitmap_from_file (f, name);
493 }
494 UNBLOCK_INPUT;
495
7812a96f
RS
496 if (bitmap_id < 0)
497 Fsignal (Qerror, Fcons (build_string ("invalid or undefined bitmap"),
cd0bb842
RS
498 Fcons (name, Qnil)));
499
500 *w_ptr = x_bitmap_width (f, bitmap_id);
501 *h_ptr = x_bitmap_height (f, bitmap_id);
502
503 return bitmap_id;
cb637678 504}
87485d6f
MW
505
506#else /* !HAVE_X_WINDOWS */
507
508/* Stubs for MSDOS when not under X. */
509
510struct face *
511intern_face (f, face)
512 struct frame *f;
513 struct face *face;
514{
515 return face;
516}
517
518void
519clear_face_cache ()
520{
521 /* No action. */
522}
523
87485d6f
MW
524#ifdef MSDOS
525unsigned long
526load_color (f, name)
527 FRAME_PTR f;
528 Lisp_Object name;
529{
530 Lisp_Object result;
531
532 if (NILP (name))
533 return FACE_DEFAULT;
534
535 CHECK_STRING (name, 0);
536 result = call1 (Qmsdos_color_translate, name);
537 if (INTEGERP (result))
538 return XINT (result);
539 else
540 Fsignal (Qerror, Fcons (build_string ("undefined color"),
541 Fcons (name, Qnil)));
542}
543#endif
544#endif /* !HAVE_X_WINDOWS */
545
cb637678 546\f
7b00de84 547/* Managing parameter face arrays for frames. */
cb637678 548
cb637678
JB
549void
550init_frame_faces (f)
660ed669 551 FRAME_PTR f;
cb637678
JB
552{
553 ensure_face_ready (f, 0);
cb637678 554 ensure_face_ready (f, 1);
660ed669 555
fffc2367
RS
556 FRAME_N_COMPUTED_FACES (f) = 0;
557 FRAME_SIZE_COMPUTED_FACES (f) = 0;
558
7b00de84
JB
559 new_computed_face (f, FRAME_PARAM_FACES (f)[0]);
560 new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
660ed669 561 recompute_basic_faces (f);
7b37f67b 562
87485d6f 563#ifdef MULTI_FRAME
1120eb5e
JB
564 /* Find another X frame. */
565 {
566 Lisp_Object tail, frame, result;
567
568 result = Qnil;
569 FOR_EACH_FRAME (tail, frame)
570 if (FRAME_X_P (XFRAME (frame))
571 && XFRAME (frame) != f)
572 {
573 result = frame;
574 break;
575 }
576
577 /* If we didn't find any X frames other than f, then we don't need
578 any faces other than 0 and 1, so we're okay. Otherwise, make
579 sure that all faces valid on the selected frame are also valid
580 on this new frame. */
581 if (FRAMEP (result))
582 {
583 int i;
7b00de84
JB
584 int n_faces = FRAME_N_PARAM_FACES (XFRAME (result));
585 struct face **faces = FRAME_PARAM_FACES (XFRAME (result));
1120eb5e
JB
586
587 for (i = 2; i < n_faces; i++)
588 if (faces[i])
589 ensure_face_ready (f, i);
590 }
591 }
87485d6f 592#endif /* MULTI_FRAME */
cb637678
JB
593}
594
660ed669 595
cb637678 596/* Called from Fdelete_frame. */
cd0bb842 597
cb637678
JB
598void
599free_frame_faces (f)
600 struct frame *f;
601{
42120bc7 602 Display *dpy = FRAME_X_DISPLAY (f);
cb637678
JB
603 int i;
604
660ed669
JB
605 BLOCK_INPUT;
606
7b00de84 607 for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
cb637678 608 {
7b00de84 609 struct face *face = FRAME_PARAM_FACES (f) [i];
660ed669
JB
610 if (face)
611 {
7b00de84
JB
612 unload_font (f, face->font);
613 unload_color (f, face->foreground);
614 unload_color (f, face->background);
cd0bb842 615 x_destroy_bitmap (f, face->stipple);
660ed669
JB
616 xfree (face);
617 }
cb637678 618 }
7b00de84
JB
619 xfree (FRAME_PARAM_FACES (f));
620 FRAME_PARAM_FACES (f) = 0;
621 FRAME_N_PARAM_FACES (f) = 0;
622
623 /* All faces in FRAME_COMPUTED_FACES use resources copied from
42120bc7
RS
624 FRAME_PARAM_FACES; we can free them without fuss.
625 But we do free the GCs and the face objects themselves. */
626 for (i = 0; i < FRAME_N_COMPUTED_FACES (f); i++)
627 {
628 struct face *face = FRAME_COMPUTED_FACES (f) [i];
629 if (face)
630 {
631 if (face->gc)
632 XFreeGC (dpy, face->gc);
633 xfree (face);
634 }
635 }
7b00de84
JB
636 xfree (FRAME_COMPUTED_FACES (f));
637 FRAME_COMPUTED_FACES (f) = 0;
638 FRAME_N_COMPUTED_FACES (f) = 0;
660ed669
JB
639
640 UNBLOCK_INPUT;
cb637678 641}
c115973b 642\f
cb637678
JB
643/* Interning faces in a frame's face array. */
644
660ed669 645static int
7b00de84
JB
646new_computed_face (f, new_face)
647 struct frame *f;
648 struct face *new_face;
649{
195f798e
RS
650 int len = FRAME_N_COMPUTED_FACES (f);
651 int i;
652
653 /* Search for an unused computed face in the middle of the table. */
654 for (i = 0; i < len; i++)
655 {
656 struct face *face = FRAME_COMPUTED_FACES (f)[i];
657 if (face->font == 0)
658 {
659 FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
660 return i;
661 }
662 }
7b00de84
JB
663
664 if (i >= FRAME_SIZE_COMPUTED_FACES (f))
665 {
666 int new_size = i + 32;
667
668 FRAME_COMPUTED_FACES (f)
fffc2367
RS
669 = (struct face **) (FRAME_SIZE_COMPUTED_FACES (f) == 0
670 ? xmalloc (new_size * sizeof (struct face *))
671 : xrealloc (FRAME_COMPUTED_FACES (f),
672 new_size * sizeof (struct face *)));
7b00de84
JB
673 FRAME_SIZE_COMPUTED_FACES (f) = new_size;
674 }
675
676 i = FRAME_N_COMPUTED_FACES (f)++;
677 FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
678 return i;
679}
680
681
682/* Find a match for NEW_FACE in a FRAME's computed face array, and add
683 it if we don't find one. */
684static int
685intern_computed_face (f, new_face)
686 struct frame *f;
b6d40e46 687 struct face *new_face;
cb637678 688{
7b00de84 689 int len = FRAME_N_COMPUTED_FACES (f);
cb637678
JB
690 int i;
691
7b00de84 692 /* Search for a computed face already on F equivalent to FACE. */
cb637678
JB
693 for (i = 0; i < len; i++)
694 {
7b00de84
JB
695 if (! FRAME_COMPUTED_FACES (f)[i])
696 abort ();
697 if (face_eql (new_face, FRAME_COMPUTED_FACES (f)[i]))
cb637678
JB
698 return i;
699 }
700
701 /* We didn't find one; add a new one. */
7b00de84 702 return new_computed_face (f, new_face);
cb637678
JB
703}
704
7b00de84 705/* Make parameter face id ID valid on frame F. */
cb637678
JB
706
707static void
708ensure_face_ready (f, id)
709 struct frame *f;
710 int id;
711{
7b00de84 712 if (FRAME_N_PARAM_FACES (f) <= id)
cb637678
JB
713 {
714 int n = id + 10;
715 int i;
7b00de84
JB
716 if (!FRAME_N_PARAM_FACES (f))
717 FRAME_PARAM_FACES (f)
cb637678
JB
718 = (struct face **) xmalloc (sizeof (struct face *) * n);
719 else
7b00de84
JB
720 FRAME_PARAM_FACES (f)
721 = (struct face **) xrealloc (FRAME_PARAM_FACES (f),
cb637678
JB
722 sizeof (struct face *) * n);
723
7b00de84
JB
724 bzero (FRAME_PARAM_FACES (f) + FRAME_N_PARAM_FACES (f),
725 (n - FRAME_N_PARAM_FACES (f)) * sizeof (struct face *));
726 FRAME_N_PARAM_FACES (f) = n;
cb637678
JB
727 }
728
7b00de84
JB
729 if (FRAME_PARAM_FACES (f) [id] == 0)
730 FRAME_PARAM_FACES (f) [id] = allocate_face ();
cb637678
JB
731}
732\f
87485d6f 733#ifdef HAVE_X_WINDOWS
867dd159
RS
734/* Return non-zero if FONT1 and FONT2 have the same width.
735 We do not check the height, because we can now deal with
736 different heights.
660ed669 737 We assume that they're both character-cell fonts. */
867dd159 738
660ed669
JB
739int
740same_size_fonts (font1, font2)
741 XFontStruct *font1, *font2;
742{
743 XCharStruct *bounds1 = &font1->min_bounds;
744 XCharStruct *bounds2 = &font2->min_bounds;
745
46407861 746 return (bounds1->width == bounds2->width);
660ed669
JB
747}
748
729425b1 749/* Update the line_height of frame F according to the biggest font in
6717f691 750 any face. Return nonzero if if line_height changes. */
729425b1 751
6717f691 752int
729425b1
RS
753frame_update_line_height (f)
754 FRAME_PTR f;
755{
756 int i;
7556890b 757 int biggest = FONT_HEIGHT (f->output_data.x->font);
729425b1 758
7556890b
RS
759 for (i = 0; i < f->output_data.x->n_param_faces; i++)
760 if (f->output_data.x->param_faces[i] != 0
761 && f->output_data.x->param_faces[i]->font != (XFontStruct *) FACE_DEFAULT)
729425b1 762 {
7556890b 763 int height = FONT_HEIGHT (f->output_data.x->param_faces[i]->font);
729425b1
RS
764 if (height > biggest)
765 biggest = height;
766 }
767
7556890b 768 if (biggest == f->output_data.x->line_height)
6717f691 769 return 0;
729425b1 770
7556890b 771 f->output_data.x->line_height = biggest;
6717f691 772 return 1;
729425b1 773}
87485d6f 774#endif /* not HAVE_X_WINDOWS */
867dd159 775\f
7b7739b1
JB
776/* Modify face TO by copying from FROM all properties which have
777 nondefault settings. */
867dd159 778
7b7739b1
JB
779static void
780merge_faces (from, to)
781 struct face *from, *to;
782{
867dd159
RS
783 /* Only merge the font if it's the same width as the base font.
784 Otherwise ignore it, since we can't handle it properly. */
68a97335 785 if (from->font != (XFontStruct *) FACE_DEFAULT
68a97335
JB
786 && same_size_fonts (from->font, to->font))
787 to->font = from->font;
7b7739b1
JB
788 if (from->foreground != FACE_DEFAULT)
789 to->foreground = from->foreground;
790 if (from->background != FACE_DEFAULT)
791 to->background = from->background;
f211082d 792 if (from->stipple != FACE_DEFAULT)
cd0bb842
RS
793 {
794 to->stipple = from->stipple;
795 to->pixmap_h = from->pixmap_h;
796 to->pixmap_w = from->pixmap_w;
797 }
7b7739b1
JB
798 if (from->underline)
799 to->underline = from->underline;
800}
801
660ed669
JB
802/* Set up the basic set of facial parameters, based on the frame's
803 data; all faces are deltas applied to this. */
867dd159 804
660ed669
JB
805static void
806compute_base_face (f, face)
807 FRAME_PTR f;
808 struct face *face;
809{
660ed669 810 face->gc = 0;
cd0bb842
RS
811 face->foreground = FRAME_FOREGROUND_PIXEL (f);
812 face->background = FRAME_BACKGROUND_PIXEL (f);
813 face->font = FRAME_FONT (f);
582080c1 814 face->stipple = 0;
660ed669
JB
815 face->underline = 0;
816}
817
867dd159
RS
818/* Return the face ID to use to display a special glyph which selects
819 FACE_CODE as the face ID, assuming that ordinarily the face would
820 be CURRENT_FACE. F is the frame. */
821
822int
823compute_glyph_face (f, face_code, current_face)
824 struct frame *f;
825 int face_code, current_face;
826{
827 struct face face;
828
829 face = *FRAME_COMPUTED_FACES (f)[current_face];
830
831 if (face_code >= 0 && face_code < FRAME_N_PARAM_FACES (f)
832 && FRAME_PARAM_FACES (f) [face_code] != 0)
833 merge_faces (FRAME_PARAM_FACES (f) [face_code], &face);
660ed669 834
867dd159
RS
835 return intern_computed_face (f, &face);
836}
2e16580f
RS
837
838/* Return the face ID to use to display a special glyph which selects
839 FACE_CODE as the face ID, assuming that ordinarily the face would
840 be CURRENT_FACE. F is the frame. */
841
842int
843compute_glyph_face_1 (f, face_name, current_face)
844 struct frame *f;
845 Lisp_Object face_name;
846 int current_face;
847{
848 struct face face;
849
850 face = *FRAME_COMPUTED_FACES (f)[current_face];
851
852 if (!NILP (face_name))
853 {
854 int facecode = face_name_id_number (f, face_name);
855 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
856 && FRAME_PARAM_FACES (f) [facecode] != 0)
857 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
858 }
859
860 return intern_computed_face (f, &face);
861}
867dd159 862\f
cb637678 863/* Return the face ID associated with a buffer position POS.
7b7739b1
JB
864 Store into *ENDPTR the position at which a different face is needed.
865 This does not take account of glyphs that specify their own face codes.
f6b98e0b 866 F is the frame in use for display, and W is a window displaying
bc0db68d
RS
867 the current buffer.
868
b349f4fb
RS
869 REGION_BEG, REGION_END delimit the region, so it can be highlighted.
870
871 LIMIT is a position not to scan beyond. That is to limit
6f134486
RS
872 the time this function can take.
873
874 If MOUSE is nonzero, use the character's mouse-face, not its face. */
bc0db68d 875
cb637678 876int
6f134486 877compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
7b7739b1 878 struct frame *f;
f211082d 879 struct window *w;
7b7739b1 880 int pos;
bc0db68d 881 int region_beg, region_end;
7b7739b1 882 int *endptr;
b349f4fb 883 int limit;
6f134486 884 int mouse;
7b7739b1
JB
885{
886 struct face face;
b6d40e46 887 Lisp_Object prop, position;
7b7739b1
JB
888 int i, j, noverlays;
889 int facecode;
7b7739b1 890 Lisp_Object *overlay_vec;
f211082d 891 Lisp_Object frame;
f6b98e0b 892 int endpos;
6f134486 893 Lisp_Object propname;
f6b98e0b
JB
894
895 /* W must display the current buffer. We could write this function
896 to use the frame and buffer of W, but right now it doesn't. */
897 if (XBUFFER (w->buffer) != current_buffer)
898 abort ();
f211082d 899
ac22a6c4 900 XSETFRAME (frame, f);
7b7739b1 901
f6b98e0b 902 endpos = ZV;
bc0db68d
RS
903 if (pos < region_beg && region_beg < endpos)
904 endpos = region_beg;
f6b98e0b 905
e0979810 906 XSETFASTINT (position, pos);
6f134486
RS
907
908 if (mouse)
909 propname = Qmouse_face;
910 else
911 propname = Qface;
912
913 prop = Fget_text_property (position, propname, w->buffer);
914
b6d40e46 915 {
b349f4fb 916 Lisp_Object limit1, end;
7b7739b1 917
e0979810 918 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
6f134486 919 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
b6d40e46
JB
920 if (INTEGERP (end))
921 endpos = XINT (end);
922 }
923
924 {
f6b98e0b 925 int next_overlay;
9516fe94
RS
926 int len;
927
928 /* First try with room for 40 overlays. */
929 len = 40;
930 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
931
7af31819
RS
932 noverlays = overlays_at (pos, 0, &overlay_vec, &len,
933 &next_overlay, (int *) 0);
9516fe94
RS
934
935 /* If there are more than 40,
936 make enough space for all, and try again. */
937 if (noverlays > len)
938 {
939 len = noverlays;
940 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
82277c2f 941 noverlays = overlays_at (pos, 0, &overlay_vec, &len,
7af31819 942 &next_overlay, (int *) 0);
9516fe94 943 }
b6d40e46 944
f6b98e0b
JB
945 if (next_overlay < endpos)
946 endpos = next_overlay;
b6d40e46
JB
947 }
948
949 *endptr = endpos;
7b7739b1
JB
950
951 /* Optimize the default case. */
bc0db68d
RS
952 if (noverlays == 0 && NILP (prop)
953 && !(pos >= region_beg && pos < region_end))
cb637678 954 return 0;
7b7739b1 955
660ed669 956 compute_base_face (f, &face);
7b7739b1 957
4699e6d2
RS
958 if (CONSP (prop))
959 {
960 /* We have a list of faces, merge them in reverse order */
60573a90
RS
961 Lisp_Object length;
962 int len;
4699e6d2
RS
963 Lisp_Object *faces;
964
60573a90
RS
965 length = Fsafe_length (prop);
966 len = XFASTINT (length);
967
4699e6d2
RS
968 /* Put them into an array */
969 faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
970 for (j = 0; j < len; j++)
971 {
972 faces[j] = Fcar (prop);
973 prop = Fcdr (prop);
974 }
975 /* So that we can merge them in the reverse order */
976 for (j = len - 1; j >= 0; j--)
977 {
978 facecode = face_name_id_number (f, faces[j]);
979 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
980 && FRAME_PARAM_FACES (f) [facecode] != 0)
981 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
982 }
983 }
984 else if (!NILP (prop))
7b7739b1 985 {
1d9fd7fe 986 facecode = face_name_id_number (f, prop);
7b00de84
JB
987 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
988 && FRAME_PARAM_FACES (f) [facecode] != 0)
989 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
7b7739b1
JB
990 }
991
4d6ebff8 992 noverlays = sort_overlays (overlay_vec, noverlays, w);
7b7739b1
JB
993
994 /* Now merge the overlay data in that order. */
7b7739b1
JB
995 for (i = 0; i < noverlays; i++)
996 {
6f134486 997 prop = Foverlay_get (overlay_vec[i], propname);
4699e6d2
RS
998 if (CONSP (prop))
999 {
1000 /* We have a list of faces, merge them in reverse order */
60573a90
RS
1001 Lisp_Object length;
1002 int len;
4699e6d2 1003 Lisp_Object *faces;
60573a90
RS
1004
1005 length = Fsafe_length (prop);
1006 len = XFASTINT (length);
4699e6d2
RS
1007
1008 /* Put them into an array */
1009 faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
1010 for (j = 0; j < len; j++)
1011 {
1012 faces[j] = Fcar (prop);
1013 prop = Fcdr (prop);
1014 }
1015 /* So that we can merge them in the reverse order */
1016 for (j = len - 1; j >= 0; j--)
1017 {
1018 facecode = face_name_id_number (f, faces[j]);
1019 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
1020 && FRAME_PARAM_FACES (f) [facecode] != 0)
1021 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
1022 }
1023 }
1024 else if (!NILP (prop))
7b7739b1
JB
1025 {
1026 Lisp_Object oend;
1027 int oendpos;
1028
1d9fd7fe 1029 facecode = face_name_id_number (f, prop);
7b00de84
JB
1030 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
1031 && FRAME_PARAM_FACES (f) [facecode] != 0)
6f134486 1032 merge_faces (FRAME_PARAM_FACES (f)[facecode], &face);
7b7739b1 1033
4d6ebff8 1034 oend = OVERLAY_END (overlay_vec[i]);
7b7739b1 1035 oendpos = OVERLAY_POSITION (oend);
f6b98e0b 1036 if (oendpos < endpos)
7b7739b1
JB
1037 endpos = oendpos;
1038 }
1039 }
1040
bc0db68d
RS
1041 if (pos >= region_beg && pos < region_end)
1042 {
1043 if (region_end < endpos)
1044 endpos = region_end;
1045 if (region_face >= 0 && region_face < next_face_id)
6f134486 1046 merge_faces (FRAME_PARAM_FACES (f)[region_face], &face);
bc0db68d
RS
1047 }
1048
7b7739b1
JB
1049 *endptr = endpos;
1050
7b00de84 1051 return intern_computed_face (f, &face);
f211082d 1052}
867dd159 1053\f
660ed669
JB
1054/* Recompute the GC's for the default and modeline faces.
1055 We call this after changing frame parameters on which those GC's
1056 depend. */
fffc2367 1057
660ed669
JB
1058void
1059recompute_basic_faces (f)
1060 FRAME_PTR f;
1061{
1062 /* If the frame's faces haven't been initialized yet, don't worry about
1063 this stuff. */
7b00de84 1064 if (FRAME_N_PARAM_FACES (f) < 2)
660ed669
JB
1065 return;
1066
1067 BLOCK_INPUT;
1068
1069 if (FRAME_DEFAULT_FACE (f)->gc)
42120bc7 1070 XFreeGC (FRAME_X_DISPLAY (f), FRAME_DEFAULT_FACE (f)->gc);
660ed669 1071 if (FRAME_MODE_LINE_FACE (f)->gc)
42120bc7 1072 XFreeGC (FRAME_X_DISPLAY (f), FRAME_MODE_LINE_FACE (f)->gc);
7b00de84
JB
1073
1074 compute_base_face (f, FRAME_DEFAULT_FACE (f));
1075 compute_base_face (f, FRAME_MODE_LINE_FACE (f));
1076
1077 merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f));
1078 merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f));
1079
42120bc7
RS
1080 intern_face (f, FRAME_DEFAULT_FACE (f));
1081 intern_face (f, FRAME_MODE_LINE_FACE (f));
660ed669
JB
1082
1083 UNBLOCK_INPUT;
1084}
1085
1086
c115973b 1087\f
cb637678 1088/* Lisp interface. */
c115973b
JB
1089
1090DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
1091 "")
1092 (frame)
1093 Lisp_Object frame;
1094{
1095 CHECK_FRAME (frame, 0);
1096 return XFRAME (frame)->face_alist;
1097}
1098
1099DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
1100 2, 2, 0, "")
1101 (frame, value)
1102 Lisp_Object frame, value;
1103{
1104 CHECK_FRAME (frame, 0);
1105 XFRAME (frame)->face_alist = value;
1106 return value;
1107}
1108
1109
1110DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
1111 "Create face number FACE-ID on all frames.")
1112 (face_id)
1113 Lisp_Object face_id;
1114{
87485d6f 1115 Lisp_Object rest, frame;
c115973b
JB
1116 int id = XINT (face_id);
1117
f211082d
JB
1118 CHECK_NUMBER (face_id, 0);
1119 if (id < 0 || id >= next_face_id)
1120 error ("Face id out of range");
c115973b 1121
87485d6f 1122 FOR_EACH_FRAME (rest, frame)
c115973b 1123 {
87485d6f
MW
1124 if (FRAME_X_P (XFRAME (frame)))
1125 ensure_face_ready (XFRAME (frame), id);
c115973b
JB
1126 }
1127 return Qnil;
1128}
1129
1130
1131DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
1132 Sset_face_attribute_internal, 4, 4, 0, "")
1133 (face_id, attr_name, attr_value, frame)
1134 Lisp_Object face_id, attr_name, attr_value, frame;
1135{
1136 struct face *face;
1137 struct frame *f;
1138 int magic_p;
1139 int id;
53dfb388 1140 int garbaged = 0;
c115973b
JB
1141
1142 CHECK_FRAME (frame, 0);
f211082d 1143 CHECK_NUMBER (face_id, 0);
c115973b
JB
1144 CHECK_SYMBOL (attr_name, 0);
1145
1146 f = XFRAME (frame);
1147 id = XINT (face_id);
f211082d
JB
1148 if (id < 0 || id >= next_face_id)
1149 error ("Face id out of range");
c115973b 1150
b6d40e46 1151 if (! FRAME_X_P (f))
b839cea0 1152 return Qnil;
b6d40e46 1153
c115973b 1154 ensure_face_ready (f, id);
7b00de84 1155 face = FRAME_PARAM_FACES (f) [XFASTINT (face_id)];
c115973b
JB
1156
1157 if (EQ (attr_name, intern ("font")))
1158 {
87485d6f 1159#if defined (MSDOS) && !defined (HAVE_X_WINDOWS)
88d9cecb
RS
1160 /* The one and only font. Must *not* be zero (which
1161 is taken to mean an unused face nowadays). */
1162 face->font = (XFontStruct *)1 ;
87485d6f 1163#else
f211082d 1164 XFontStruct *font = load_font (f, attr_value);
7556890b 1165 if (face->font != f->output_data.x->font)
ebc64af3 1166 unload_font (f, face->font);
c115973b 1167 face->font = font;
6717f691
RS
1168 if (frame_update_line_height (f))
1169 x_set_window_size (f, 0, f->width, f->height);
53dfb388
RS
1170 /* Must clear cache, since it might contain the font
1171 we just got rid of. */
1172 garbaged = 1;
87485d6f 1173#endif
c115973b
JB
1174 }
1175 else if (EQ (attr_name, intern ("foreground")))
1176 {
f211082d 1177 unsigned long new_color = load_color (f, attr_value);
c115973b
JB
1178 unload_color (f, face->foreground);
1179 face->foreground = new_color;
53dfb388 1180 garbaged = 1;
c115973b
JB
1181 }
1182 else if (EQ (attr_name, intern ("background")))
1183 {
f211082d 1184 unsigned long new_color = load_color (f, attr_value);
c115973b 1185 unload_color (f, face->background);
87485d6f
MW
1186#if defined (MSDOS) && !defined (HAVE_X_WINDOWS)
1187 new_color &= ~8; /* Bright would give blinking characters. */
1188#endif
c115973b 1189 face->background = new_color;
53dfb388 1190 garbaged = 1;
c115973b 1191 }
c115973b
JB
1192 else if (EQ (attr_name, intern ("background-pixmap")))
1193 {
cd0bb842
RS
1194 unsigned int w, h;
1195 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h);
1196 x_destroy_bitmap (f, face->stipple);
f211082d 1197 face->stipple = new_pixmap;
c115973b
JB
1198 face->pixmap_w = w;
1199 face->pixmap_h = h;
cd0bb842 1200 garbaged = 1;
c115973b 1201 }
c115973b
JB
1202 else if (EQ (attr_name, intern ("underline")))
1203 {
1204 int new = !NILP (attr_value);
1205 face->underline = new;
1206 }
1207 else
1208 error ("unknown face attribute");
1209
7b00de84
JB
1210 if (id == 0 || id == 1)
1211 recompute_basic_faces (f);
c115973b 1212
53dfb388
RS
1213 /* We must redraw the frame whenever any face font or color changes,
1214 because it's possible that a merged (display) face
1215 contains the font or color we just replaced.
1216 And we must inhibit any Expose events until the redraw is done,
1217 since they would try to use the invalid display faces. */
1218 if (garbaged)
584d0634 1219 SET_FRAME_GARBAGED (f);
584d0634 1220
c115973b
JB
1221 return Qnil;
1222}
1223
1224DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
1225 0, 0, 0, "")
1226 ()
1227{
1228 return make_number (next_face_id++);
1229}
f211082d
JB
1230
1231/* Return the face id for name NAME on frame FRAME.
1232 (It should be the same for all frames,
1233 but it's as easy to use the "right" frame to look it up
1234 as to use any other one.) */
1235
1d9fd7fe
JB
1236int
1237face_name_id_number (f, name)
1238 FRAME_PTR f;
1239 Lisp_Object name;
f211082d
JB
1240{
1241 Lisp_Object tem;
1242
82411f65 1243 tem = Fcdr (assq_no_quit (name, f->face_alist));
b6d40e46
JB
1244 if (NILP (tem))
1245 return 0;
f211082d
JB
1246 CHECK_VECTOR (tem, 0);
1247 tem = XVECTOR (tem)->contents[2];
1248 CHECK_NUMBER (tem, 0);
1249 return XINT (tem);
1250}
c115973b 1251\f
cb637678
JB
1252/* Emacs initialization. */
1253
c115973b 1254void
f211082d 1255syms_of_xfaces ()
c115973b 1256{
f211082d
JB
1257 Qface = intern ("face");
1258 staticpro (&Qface);
6f134486
RS
1259 Qmouse_face = intern ("mouse-face");
1260 staticpro (&Qmouse_face);
cd0bb842
RS
1261 Qpixmap_spec_p = intern ("pixmap-spec-p");
1262 staticpro (&Qpixmap_spec_p);
f211082d 1263
bc0db68d
RS
1264 DEFVAR_INT ("region-face", &region_face,
1265 "Face number to use to highlight the region\n\
1266The region is highlighted with this face\n\
1267when Transient Mark mode is enabled and the mark is active.");
1268
87485d6f 1269#ifdef HAVE_X_WINDOWS
cd0bb842 1270 defsubr (&Spixmap_spec_p);
87485d6f 1271#endif
c115973b
JB
1272 defsubr (&Sframe_face_alist);
1273 defsubr (&Sset_frame_face_alist);
1274 defsubr (&Smake_face_internal);
1275 defsubr (&Sset_face_attribute_internal);
1276 defsubr (&Sinternal_next_face_id);
1277}
cb637678 1278
87485d6f 1279#endif /* HAVE_FACES */