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