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