(display_text_line): Use the face properties of the overlay arrow, if any.
[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"
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
6f134486 173Lisp_Object Qface, Qmouse_face;
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))
90e6242c
RS
251 {
252 face->cached_index = i;
253 return face_vector[i];
254 }
c115973b
JB
255 if (face_vector[i] == 0)
256 empty = i;
257 }
258
259 /* If no empty slots, make one. */
260 if (empty < 0 && nfaces == nfaces_allocated)
261 {
262 int newsize = nfaces + 20;
263 face_vector
264 = (struct face **) xrealloc (face_vector,
265 newsize * sizeof (struct face *));
266 nfaces_allocated = newsize;
267 }
268
269 if (empty < 0)
270 empty = nfaces++;
271
272 /* Put a new display face in the empty slot. */
273 result = copy_face (face);
274 face_vector[empty] = result;
275
276 /* Make a graphics context for it. */
277 build_face (f, result);
278
90e6242c 279 face->cached_index = empty;
c115973b
JB
280 return result;
281}
282
7b00de84 283/* Given a computed face, return an equivalent display face
cb637678
JB
284 (one which has a graphics context). */
285
286struct face *
287intern_face (f, face)
288 struct frame *f;
289 struct face *face;
290{
cb637678
JB
291 /* If it's equivalent to the default face, use that. */
292 if (face_eql (face, FRAME_DEFAULT_FACE (f)))
293 {
294 if (!FRAME_DEFAULT_FACE (f)->gc)
295 build_face (f, FRAME_DEFAULT_FACE (f));
296 return FRAME_DEFAULT_FACE (f);
297 }
298
299 /* If it's equivalent to the mode line face, use that. */
300 if (face_eql (face, FRAME_MODE_LINE_FACE (f)))
301 {
302 if (!FRAME_MODE_LINE_FACE (f)->gc)
303 build_face (f, FRAME_MODE_LINE_FACE (f));
304 return FRAME_MODE_LINE_FACE (f);
305 }
306
f6b98e0b
JB
307 /* If it's not one of the frame's default faces, it shouldn't have a GC. */
308 if (face->gc)
309 abort ();
310
cb637678
JB
311 /* Get a specialized display face. */
312 return get_cached_face (f, face);
313}
314
c115973b
JB
315/* Clear out face_vector and start anew.
316 This should be done from time to time just to avoid
317 keeping too many graphics contexts in face_vector
318 that are no longer needed. */
319
320void
321clear_face_vector ()
322{
323 Lisp_Object rest;
324 Display *dpy = x_current_display;
f211082d 325 int i;
c115973b
JB
326
327 BLOCK_INPUT;
328 /* Free the display faces in the face_vector. */
329 for (i = 0; i < nfaces; i++)
330 {
331 struct face *face = face_vector[i];
f211082d
JB
332 if (face->gc)
333 XFreeGC (dpy, face->gc);
c115973b
JB
334 xfree (face);
335 }
336 nfaces = 0;
337
338 UNBLOCK_INPUT;
339}
340\f
cb637678
JB
341/* Allocating and freeing X resources for display faces. */
342
f211082d
JB
343/* Make a graphics context for face FACE, which is on frame F,
344 if that can be done. */
c115973b
JB
345static void
346build_face (f, face)
cb637678
JB
347 struct frame *f;
348 struct face *face;
c115973b
JB
349{
350 GC gc;
351 XGCValues xgcv;
352 unsigned long mask;
353
660ed669
JB
354 BLOCK_INPUT;
355
f211082d
JB
356 if (face->foreground != FACE_DEFAULT)
357 xgcv.foreground = face->foreground;
358 else
660ed669
JB
359 xgcv.foreground = f->display.x->foreground_pixel;
360
f211082d
JB
361 if (face->background != FACE_DEFAULT)
362 xgcv.background = face->background;
363 else
660ed669
JB
364 xgcv.background = f->display.x->background_pixel;
365
f211082d
JB
366 if (face->font && (int) face->font != FACE_DEFAULT)
367 xgcv.font = face->font->fid;
368 else
369 xgcv.font = f->display.x->font->fid;
660ed669 370
c115973b 371 xgcv.graphics_exposures = 0;
660ed669 372
c115973b
JB
373 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
374 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
375 mask, &xgcv);
660ed669 376
c115973b 377#if 0
f211082d
JB
378 if (face->stipple && face->stipple != FACE_DEFAULT)
379 XSetStipple (x_current_display, gc, face->stipple);
c115973b 380#endif
660ed669 381
f211082d 382 face->gc = gc;
660ed669
JB
383
384 UNBLOCK_INPUT;
c115973b 385}
cb637678
JB
386
387/* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
388
389static XFontStruct *
390load_font (f, name)
391 struct frame *f;
392 Lisp_Object name;
393{
394 XFontStruct *font;
395
396 if (NILP (name))
397 return (XFontStruct *) FACE_DEFAULT;
398
399 CHECK_STRING (name, 0);
400 BLOCK_INPUT;
401 font = XLoadQueryFont (x_current_display, (char *) XSTRING (name)->data);
402 UNBLOCK_INPUT;
403
404 if (! font)
405 Fsignal (Qerror, Fcons (build_string ("undefined font"),
406 Fcons (name, Qnil)));
407 return font;
408}
409
410static void
411unload_font (f, font)
412 struct frame *f;
413 XFontStruct *font;
414{
415 if (!font || font == ((XFontStruct *) FACE_DEFAULT))
416 return;
660ed669
JB
417
418 BLOCK_INPUT;
cb637678 419 XFreeFont (x_current_display, font);
660ed669 420 UNBLOCK_INPUT;
cb637678
JB
421}
422
423static unsigned long
424load_color (f, name)
425 struct frame *f;
426 Lisp_Object name;
427{
428 Display *dpy = x_current_display;
429 Colormap cmap;
430 XColor color;
431 int result;
432
433 if (NILP (name))
434 return FACE_DEFAULT;
435
436 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
437
438 CHECK_STRING (name, 0);
439 BLOCK_INPUT;
440 result = XParseColor (dpy, cmap, (char *) XSTRING (name)->data, &color);
441 UNBLOCK_INPUT;
442 if (! result)
443 Fsignal (Qerror, Fcons (build_string ("undefined color"),
444 Fcons (name, Qnil)));
445 BLOCK_INPUT;
446 result = XAllocColor (dpy, cmap, &color);
447 UNBLOCK_INPUT;
448 if (! result)
449 Fsignal (Qerror, Fcons (build_string ("X server cannot allocate color"),
450 Fcons (name, Qnil)));
451 return (unsigned long) color.pixel;
452}
453
454static void
455unload_color (f, pixel)
456 struct frame *f;
7a4d2269 457 unsigned long pixel;
cb637678 458{
1d9fd7fe
JB
459 /* Since faces get built by copying parameters from other faces, the
460 allocation counts for the colors get all screwed up. I don't see
461 any solution that will take less than 10 minutes, and it's better
462 to have a color leak than a crash, so I'm just dyking this out.
463 This isn't really a color leak, anyway - if we ask for it again,
464 we'll get the same pixel. */
465#if 0
cb637678
JB
466 Colormap cmap;
467 Display *dpy = x_current_display;
32dc0866
JB
468 if (pixel == FACE_DEFAULT
469 || pixel == BLACK_PIX_DEFAULT
470 || pixel == WHITE_PIX_DEFAULT)
cb637678
JB
471 return;
472 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
473 BLOCK_INPUT;
474 XFreeColors (dpy, cmap, &pixel, 1, 0);
475 UNBLOCK_INPUT;
1d9fd7fe 476#endif
cb637678
JB
477}
478\f
7b00de84 479/* Managing parameter face arrays for frames. */
cb637678 480
cb637678
JB
481void
482init_frame_faces (f)
660ed669 483 FRAME_PTR f;
cb637678
JB
484{
485 ensure_face_ready (f, 0);
cb637678 486 ensure_face_ready (f, 1);
660ed669 487
fffc2367
RS
488 FRAME_N_COMPUTED_FACES (f) = 0;
489 FRAME_SIZE_COMPUTED_FACES (f) = 0;
490
7b00de84
JB
491 new_computed_face (f, FRAME_PARAM_FACES (f)[0]);
492 new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
660ed669 493 recompute_basic_faces (f);
7b37f67b 494
1120eb5e
JB
495 /* Find another X frame. */
496 {
497 Lisp_Object tail, frame, result;
498
499 result = Qnil;
500 FOR_EACH_FRAME (tail, frame)
501 if (FRAME_X_P (XFRAME (frame))
502 && XFRAME (frame) != f)
503 {
504 result = frame;
505 break;
506 }
507
508 /* If we didn't find any X frames other than f, then we don't need
509 any faces other than 0 and 1, so we're okay. Otherwise, make
510 sure that all faces valid on the selected frame are also valid
511 on this new frame. */
512 if (FRAMEP (result))
513 {
514 int i;
7b00de84
JB
515 int n_faces = FRAME_N_PARAM_FACES (XFRAME (result));
516 struct face **faces = FRAME_PARAM_FACES (XFRAME (result));
1120eb5e
JB
517
518 for (i = 2; i < n_faces; i++)
519 if (faces[i])
520 ensure_face_ready (f, i);
521 }
522 }
cb637678
JB
523}
524
660ed669 525
cb637678
JB
526/* Called from Fdelete_frame. */
527void
528free_frame_faces (f)
529 struct frame *f;
530{
531 Display *dpy = x_current_display;
532 int i;
533
660ed669
JB
534 BLOCK_INPUT;
535
7b00de84 536 for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
cb637678 537 {
7b00de84 538 struct face *face = FRAME_PARAM_FACES (f) [i];
660ed669
JB
539 if (face)
540 {
541 if (face->gc)
542 XFreeGC (dpy, face->gc);
7b00de84
JB
543 unload_font (f, face->font);
544 unload_color (f, face->foreground);
545 unload_color (f, face->background);
cb637678 546#if 0
7b00de84 547 unload_pixmap (f, face->stipple);
cb637678 548#endif
660ed669
JB
549 xfree (face);
550 }
cb637678 551 }
7b00de84
JB
552 xfree (FRAME_PARAM_FACES (f));
553 FRAME_PARAM_FACES (f) = 0;
554 FRAME_N_PARAM_FACES (f) = 0;
555
556 /* All faces in FRAME_COMPUTED_FACES use resources copied from
557 FRAME_PARAM_FACES; we can free them without fuss. */
558 xfree (FRAME_COMPUTED_FACES (f));
559 FRAME_COMPUTED_FACES (f) = 0;
560 FRAME_N_COMPUTED_FACES (f) = 0;
660ed669
JB
561
562 UNBLOCK_INPUT;
cb637678 563}
c115973b 564\f
cb637678
JB
565/* Interning faces in a frame's face array. */
566
660ed669 567static int
7b00de84
JB
568new_computed_face (f, new_face)
569 struct frame *f;
570 struct face *new_face;
571{
572 int i = FRAME_N_COMPUTED_FACES (f);
573
574 if (i >= FRAME_SIZE_COMPUTED_FACES (f))
575 {
576 int new_size = i + 32;
577
578 FRAME_COMPUTED_FACES (f)
fffc2367
RS
579 = (struct face **) (FRAME_SIZE_COMPUTED_FACES (f) == 0
580 ? xmalloc (new_size * sizeof (struct face *))
581 : xrealloc (FRAME_COMPUTED_FACES (f),
582 new_size * sizeof (struct face *)));
7b00de84
JB
583 FRAME_SIZE_COMPUTED_FACES (f) = new_size;
584 }
585
586 i = FRAME_N_COMPUTED_FACES (f)++;
587 FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
588 return i;
589}
590
591
592/* Find a match for NEW_FACE in a FRAME's computed face array, and add
593 it if we don't find one. */
594static int
595intern_computed_face (f, new_face)
596 struct frame *f;
b6d40e46 597 struct face *new_face;
cb637678 598{
7b00de84 599 int len = FRAME_N_COMPUTED_FACES (f);
cb637678
JB
600 int i;
601
7b00de84 602 /* Search for a computed face already on F equivalent to FACE. */
cb637678
JB
603 for (i = 0; i < len; i++)
604 {
7b00de84
JB
605 if (! FRAME_COMPUTED_FACES (f)[i])
606 abort ();
607 if (face_eql (new_face, FRAME_COMPUTED_FACES (f)[i]))
cb637678
JB
608 return i;
609 }
610
611 /* We didn't find one; add a new one. */
7b00de84 612 return new_computed_face (f, new_face);
cb637678
JB
613}
614
7b00de84 615/* Make parameter face id ID valid on frame F. */
cb637678
JB
616
617static void
618ensure_face_ready (f, id)
619 struct frame *f;
620 int id;
621{
7b00de84 622 if (FRAME_N_PARAM_FACES (f) <= id)
cb637678
JB
623 {
624 int n = id + 10;
625 int i;
7b00de84
JB
626 if (!FRAME_N_PARAM_FACES (f))
627 FRAME_PARAM_FACES (f)
cb637678
JB
628 = (struct face **) xmalloc (sizeof (struct face *) * n);
629 else
7b00de84
JB
630 FRAME_PARAM_FACES (f)
631 = (struct face **) xrealloc (FRAME_PARAM_FACES (f),
cb637678
JB
632 sizeof (struct face *) * n);
633
7b00de84
JB
634 bzero (FRAME_PARAM_FACES (f) + FRAME_N_PARAM_FACES (f),
635 (n - FRAME_N_PARAM_FACES (f)) * sizeof (struct face *));
636 FRAME_N_PARAM_FACES (f) = n;
cb637678
JB
637 }
638
7b00de84
JB
639 if (FRAME_PARAM_FACES (f) [id] == 0)
640 FRAME_PARAM_FACES (f) [id] = allocate_face ();
cb637678
JB
641}
642\f
867dd159
RS
643/* Return non-zero if FONT1 and FONT2 have the same width.
644 We do not check the height, because we can now deal with
645 different heights.
660ed669 646 We assume that they're both character-cell fonts. */
867dd159 647
660ed669
JB
648int
649same_size_fonts (font1, font2)
650 XFontStruct *font1, *font2;
651{
652 XCharStruct *bounds1 = &font1->min_bounds;
653 XCharStruct *bounds2 = &font2->min_bounds;
654
46407861 655 return (bounds1->width == bounds2->width);
660ed669
JB
656}
657
729425b1 658/* Update the line_height of frame F according to the biggest font in
6717f691 659 any face. Return nonzero if if line_height changes. */
729425b1 660
6717f691 661int
729425b1
RS
662frame_update_line_height (f)
663 FRAME_PTR f;
664{
665 int i;
666 int biggest = FONT_HEIGHT (f->display.x->font);
667
668 for (i = 0; i < f->display.x->n_param_faces; i++)
867dd159
RS
669 if (f->display.x->param_faces[i] != 0
670 && f->display.x->param_faces[i]->font != (XFontStruct *) FACE_DEFAULT)
729425b1
RS
671 {
672 int height = FONT_HEIGHT (f->display.x->param_faces[i]->font);
673 if (height > biggest)
674 biggest = height;
675 }
676
677 if (biggest == f->display.x->line_height)
6717f691 678 return 0;
729425b1
RS
679
680 f->display.x->line_height = biggest;
6717f691 681 return 1;
729425b1 682}
867dd159 683\f
7b7739b1
JB
684/* Modify face TO by copying from FROM all properties which have
685 nondefault settings. */
867dd159 686
7b7739b1
JB
687static void
688merge_faces (from, to)
689 struct face *from, *to;
690{
867dd159
RS
691 /* Only merge the font if it's the same width as the base font.
692 Otherwise ignore it, since we can't handle it properly. */
68a97335 693 if (from->font != (XFontStruct *) FACE_DEFAULT
68a97335
JB
694 && same_size_fonts (from->font, to->font))
695 to->font = from->font;
7b7739b1
JB
696 if (from->foreground != FACE_DEFAULT)
697 to->foreground = from->foreground;
698 if (from->background != FACE_DEFAULT)
699 to->background = from->background;
f211082d
JB
700 if (from->stipple != FACE_DEFAULT)
701 to->stipple = from->stipple;
7b7739b1
JB
702 if (from->underline)
703 to->underline = from->underline;
704}
705
660ed669
JB
706/* Set up the basic set of facial parameters, based on the frame's
707 data; all faces are deltas applied to this. */
867dd159 708
660ed669
JB
709static void
710compute_base_face (f, face)
711 FRAME_PTR f;
712 struct face *face;
713{
714 struct x_display *d = f->display.x;
715
716 face->gc = 0;
717 face->foreground = d->foreground_pixel;
718 face->background = d->background_pixel;
719 face->font = d->font;
582080c1 720 face->stipple = 0;
660ed669 721 face->underline = 0;
582080c1
JB
722
723 /* Avoid a face comparison by making this invalid. */
724 face->cached_index = -1;
660ed669
JB
725}
726
867dd159
RS
727/* Return the face ID to use to display a special glyph which selects
728 FACE_CODE as the face ID, assuming that ordinarily the face would
729 be CURRENT_FACE. F is the frame. */
730
731int
732compute_glyph_face (f, face_code, current_face)
733 struct frame *f;
734 int face_code, current_face;
735{
736 struct face face;
737
738 face = *FRAME_COMPUTED_FACES (f)[current_face];
739
740 if (face_code >= 0 && face_code < FRAME_N_PARAM_FACES (f)
741 && FRAME_PARAM_FACES (f) [face_code] != 0)
742 merge_faces (FRAME_PARAM_FACES (f) [face_code], &face);
660ed669 743
867dd159
RS
744 return intern_computed_face (f, &face);
745}
746\f
cb637678 747/* Return the face ID associated with a buffer position POS.
7b7739b1
JB
748 Store into *ENDPTR the position at which a different face is needed.
749 This does not take account of glyphs that specify their own face codes.
f6b98e0b 750 F is the frame in use for display, and W is a window displaying
bc0db68d
RS
751 the current buffer.
752
b349f4fb
RS
753 REGION_BEG, REGION_END delimit the region, so it can be highlighted.
754
755 LIMIT is a position not to scan beyond. That is to limit
6f134486
RS
756 the time this function can take.
757
758 If MOUSE is nonzero, use the character's mouse-face, not its face. */
bc0db68d 759
cb637678 760int
6f134486 761compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
7b7739b1 762 struct frame *f;
f211082d 763 struct window *w;
7b7739b1 764 int pos;
bc0db68d 765 int region_beg, region_end;
7b7739b1 766 int *endptr;
b349f4fb 767 int limit;
6f134486 768 int mouse;
7b7739b1
JB
769{
770 struct face face;
b6d40e46 771 Lisp_Object prop, position;
7b7739b1
JB
772 int i, j, noverlays;
773 int facecode;
7b7739b1 774 Lisp_Object *overlay_vec;
f211082d 775 Lisp_Object frame;
f6b98e0b 776 int endpos;
6f134486 777 Lisp_Object propname;
f6b98e0b
JB
778
779 /* W must display the current buffer. We could write this function
780 to use the frame and buffer of W, but right now it doesn't. */
781 if (XBUFFER (w->buffer) != current_buffer)
782 abort ();
f211082d
JB
783
784 XSET (frame, Lisp_Frame, f);
7b7739b1 785
f6b98e0b 786 endpos = ZV;
bc0db68d
RS
787 if (pos < region_beg && region_beg < endpos)
788 endpos = region_beg;
f6b98e0b 789
7b7739b1 790 XFASTINT (position) = pos;
6f134486
RS
791
792 if (mouse)
793 propname = Qmouse_face;
794 else
795 propname = Qface;
796
797 prop = Fget_text_property (position, propname, w->buffer);
798
b6d40e46 799 {
b349f4fb 800 Lisp_Object limit1, end;
7b7739b1 801
b349f4fb 802 XFASTINT (limit1) = (limit < endpos ? limit : endpos);
6f134486 803 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
b6d40e46
JB
804 if (INTEGERP (end))
805 endpos = XINT (end);
806 }
807
808 {
f6b98e0b 809 int next_overlay;
9516fe94
RS
810 int len;
811
812 /* First try with room for 40 overlays. */
813 len = 40;
814 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
815
816 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
817
818 /* If there are more than 40,
819 make enough space for all, and try again. */
820 if (noverlays > len)
821 {
822 len = noverlays;
823 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
824 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
825 }
b6d40e46 826
f6b98e0b
JB
827 if (next_overlay < endpos)
828 endpos = next_overlay;
b6d40e46
JB
829 }
830
831 *endptr = endpos;
7b7739b1
JB
832
833 /* Optimize the default case. */
bc0db68d
RS
834 if (noverlays == 0 && NILP (prop)
835 && !(pos >= region_beg && pos < region_end))
cb637678 836 return 0;
7b7739b1 837
660ed669 838 compute_base_face (f, &face);
7b7739b1
JB
839
840 if (!NILP (prop))
841 {
1d9fd7fe 842 facecode = face_name_id_number (f, prop);
7b00de84
JB
843 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
844 && FRAME_PARAM_FACES (f) [facecode] != 0)
845 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
7b7739b1
JB
846 }
847
4d6ebff8 848 noverlays = sort_overlays (overlay_vec, noverlays, w);
7b7739b1
JB
849
850 /* Now merge the overlay data in that order. */
7b7739b1
JB
851 for (i = 0; i < noverlays; i++)
852 {
6f134486 853 prop = Foverlay_get (overlay_vec[i], propname);
7b7739b1
JB
854 if (!NILP (prop))
855 {
856 Lisp_Object oend;
857 int oendpos;
858
1d9fd7fe 859 facecode = face_name_id_number (f, prop);
7b00de84
JB
860 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
861 && FRAME_PARAM_FACES (f) [facecode] != 0)
6f134486 862 merge_faces (FRAME_PARAM_FACES (f)[facecode], &face);
7b7739b1 863
4d6ebff8 864 oend = OVERLAY_END (overlay_vec[i]);
7b7739b1 865 oendpos = OVERLAY_POSITION (oend);
f6b98e0b 866 if (oendpos < endpos)
7b7739b1
JB
867 endpos = oendpos;
868 }
869 }
870
bc0db68d
RS
871 if (pos >= region_beg && pos < region_end)
872 {
873 if (region_end < endpos)
874 endpos = region_end;
875 if (region_face >= 0 && region_face < next_face_id)
6f134486 876 merge_faces (FRAME_PARAM_FACES (f)[region_face], &face);
bc0db68d
RS
877 }
878
7b7739b1
JB
879 *endptr = endpos;
880
7b00de84 881 return intern_computed_face (f, &face);
f211082d 882}
867dd159 883\f
660ed669
JB
884/* Recompute the GC's for the default and modeline faces.
885 We call this after changing frame parameters on which those GC's
886 depend. */
fffc2367 887
660ed669
JB
888void
889recompute_basic_faces (f)
890 FRAME_PTR f;
891{
892 /* If the frame's faces haven't been initialized yet, don't worry about
893 this stuff. */
7b00de84 894 if (FRAME_N_PARAM_FACES (f) < 2)
660ed669
JB
895 return;
896
897 BLOCK_INPUT;
898
899 if (FRAME_DEFAULT_FACE (f)->gc)
900 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
660ed669
JB
901 if (FRAME_MODE_LINE_FACE (f)->gc)
902 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
7b00de84
JB
903
904 compute_base_face (f, FRAME_DEFAULT_FACE (f));
905 compute_base_face (f, FRAME_MODE_LINE_FACE (f));
906
907 merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f));
908 merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f));
909
910 build_face (f, FRAME_DEFAULT_FACE (f));
660ed669
JB
911 build_face (f, FRAME_MODE_LINE_FACE (f));
912
913 UNBLOCK_INPUT;
914}
915
916
c115973b 917\f
cb637678 918/* Lisp interface. */
c115973b
JB
919
920DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
921 "")
922 (frame)
923 Lisp_Object frame;
924{
925 CHECK_FRAME (frame, 0);
926 return XFRAME (frame)->face_alist;
927}
928
929DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
930 2, 2, 0, "")
931 (frame, value)
932 Lisp_Object frame, value;
933{
934 CHECK_FRAME (frame, 0);
935 XFRAME (frame)->face_alist = value;
936 return value;
937}
938
939
940DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
941 "Create face number FACE-ID on all frames.")
942 (face_id)
943 Lisp_Object face_id;
944{
945 Lisp_Object rest;
946 int id = XINT (face_id);
947
f211082d
JB
948 CHECK_NUMBER (face_id, 0);
949 if (id < 0 || id >= next_face_id)
950 error ("Face id out of range");
c115973b
JB
951
952 for (rest = Vframe_list; !NILP (rest); rest = XCONS (rest)->cdr)
953 {
954 struct frame *f = XFRAME (XCONS (rest)->car);
cb637678
JB
955 if (FRAME_X_P (f))
956 ensure_face_ready (f, id);
c115973b
JB
957 }
958 return Qnil;
959}
960
961
962DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
963 Sset_face_attribute_internal, 4, 4, 0, "")
964 (face_id, attr_name, attr_value, frame)
965 Lisp_Object face_id, attr_name, attr_value, frame;
966{
967 struct face *face;
968 struct frame *f;
969 int magic_p;
970 int id;
971
972 CHECK_FRAME (frame, 0);
f211082d 973 CHECK_NUMBER (face_id, 0);
c115973b
JB
974 CHECK_SYMBOL (attr_name, 0);
975
976 f = XFRAME (frame);
977 id = XINT (face_id);
f211082d
JB
978 if (id < 0 || id >= next_face_id)
979 error ("Face id out of range");
c115973b 980
b6d40e46 981 if (! FRAME_X_P (f))
b839cea0 982 return Qnil;
b6d40e46 983
c115973b 984 ensure_face_ready (f, id);
7b00de84 985 face = FRAME_PARAM_FACES (f) [XFASTINT (face_id)];
c115973b
JB
986
987 if (EQ (attr_name, intern ("font")))
988 {
f211082d 989 XFontStruct *font = load_font (f, attr_value);
ebc64af3
RS
990 if (face->font != f->display.x->font)
991 unload_font (f, face->font);
c115973b 992 face->font = font;
6717f691
RS
993 if (frame_update_line_height (f))
994 x_set_window_size (f, 0, f->width, f->height);
c115973b
JB
995 }
996 else if (EQ (attr_name, intern ("foreground")))
997 {
f211082d 998 unsigned long new_color = load_color (f, attr_value);
c115973b
JB
999 unload_color (f, face->foreground);
1000 face->foreground = new_color;
c115973b
JB
1001 }
1002 else if (EQ (attr_name, intern ("background")))
1003 {
f211082d 1004 unsigned long new_color = load_color (f, attr_value);
c115973b
JB
1005 unload_color (f, face->background);
1006 face->background = new_color;
c115973b
JB
1007 }
1008#if 0
1009 else if (EQ (attr_name, intern ("background-pixmap")))
1010 {
c115973b
JB
1011 unsigned int w, h, d;
1012 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h, &d, 0);
f211082d
JB
1013 unload_pixmap (f, face->stipple);
1014 if (NILP (attr_value))
1015 new_pixmap = 0;
1016 face->stipple = new_pixmap;
c115973b
JB
1017 face->pixmap_w = w;
1018 face->pixmap_h = h;
1019/* face->pixmap_depth = d; */
c115973b
JB
1020 }
1021#endif /* 0 */
1022 else if (EQ (attr_name, intern ("underline")))
1023 {
1024 int new = !NILP (attr_value);
1025 face->underline = new;
1026 }
1027 else
1028 error ("unknown face attribute");
1029
7b00de84
JB
1030 if (id == 0 || id == 1)
1031 recompute_basic_faces (f);
c115973b 1032
584d0634
JB
1033 /* If we're modifying either of the frame's display faces, that
1034 means that we're changing the parameters of a fixed face code;
1035 since the color/font/whatever is changed but the face ID hasn't,
1036 redisplay won't know to redraw the affected sections. Give it a
1037 kick. */
1038 if (id == 0 || id == 1)
1039 SET_FRAME_GARBAGED (f);
1040 else
1041 /* Otherwise, it's enough to tell it to redisplay the text. */
1042 windows_or_buffers_changed = 1;
1043
c115973b
JB
1044 return Qnil;
1045}
1046
1047DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
1048 0, 0, 0, "")
1049 ()
1050{
1051 return make_number (next_face_id++);
1052}
f211082d
JB
1053
1054/* Return the face id for name NAME on frame FRAME.
1055 (It should be the same for all frames,
1056 but it's as easy to use the "right" frame to look it up
1057 as to use any other one.) */
1058
1d9fd7fe
JB
1059int
1060face_name_id_number (f, name)
1061 FRAME_PTR f;
1062 Lisp_Object name;
f211082d
JB
1063{
1064 Lisp_Object tem;
1065
82411f65 1066 tem = Fcdr (assq_no_quit (name, f->face_alist));
b6d40e46
JB
1067 if (NILP (tem))
1068 return 0;
f211082d
JB
1069 CHECK_VECTOR (tem, 0);
1070 tem = XVECTOR (tem)->contents[2];
1071 CHECK_NUMBER (tem, 0);
1072 return XINT (tem);
1073}
c115973b 1074\f
cb637678
JB
1075/* Emacs initialization. */
1076
c115973b 1077void
f211082d 1078syms_of_xfaces ()
c115973b 1079{
f211082d
JB
1080 Qface = intern ("face");
1081 staticpro (&Qface);
6f134486
RS
1082 Qmouse_face = intern ("mouse-face");
1083 staticpro (&Qmouse_face);
f211082d 1084
bc0db68d
RS
1085 DEFVAR_INT ("region-face", &region_face,
1086 "Face number to use to highlight the region\n\
1087The region is highlighted with this face\n\
1088when Transient Mark mode is enabled and the mark is active.");
1089
c115973b
JB
1090 defsubr (&Sframe_face_alist);
1091 defsubr (&Sset_frame_face_alist);
1092 defsubr (&Smake_face_internal);
1093 defsubr (&Sset_face_attribute_internal);
1094 defsubr (&Sinternal_next_face_id);
1095}
cb637678
JB
1096
1097#endif /* HAVE_X_WINDOWS */
1098