]> code.delx.au - gnu-emacs/blob - src/xfaces.c
(compute_glyph_face_1): New function.
[gnu-emacs] / src / xfaces.c
1 /* "Face" primitives.
2 Copyright (C) 1993, 1994 Free Software Foundation.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /* This is derived from work by Lucid (some parts very loosely so). */
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24
25 #include <config.h>
26 #include "lisp.h"
27
28 #ifdef HAVE_X_WINDOWS
29
30 #include "xterm.h"
31 #include "buffer.h"
32 #include "dispextern.h"
33 #include "frame.h"
34 #include "blockinput.h"
35 #include "window.h"
36
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. */
41 #ifdef XOS_NEEDS_TIME_H
42
43 #include <time.h>
44 #undef USG
45 #include <X11/Xos.h>
46 #define USG
47 #define __TIMEVAL__
48
49 #else
50
51 #include <X11/Xos.h>
52
53 #endif
54
55 \f
56 /* An explanation of the face data structures. */
57
58 /* ========================= Face Data Structures =========================
59
60 Let FACE-NAME be a symbol naming a face.
61
62 Let FACE-VECTOR be (assq FACE-NAME (frame-face-alist FRAME))
63 FACE-VECTOR is either nil, or a vector of the form
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.
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.
125
126 Some subtleties:
127
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
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
145 We're often applying intern_face to faces in computed_faces -
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
156 /* A table of display faces. */
157 static struct face **face_vector;
158 /* The length in use of the table. */
159 static int nfaces;
160 /* The allocated length of the table. */
161 static int nfaces_allocated;
162
163 /* The number of face-id's in use (same for all frames). */
164 int next_face_id;
165
166 /* The number of the face to use to indicate the region. */
167 int region_face;
168
169 /* This is what appears in a slot in a face to signify that the face
170 does not specify that display aspect. */
171 #define FACE_DEFAULT (~0)
172
173 Lisp_Object Qface, Qmouse_face;
174
175 static void build_face ( /* FRAME_PTR, struct face * */ );
176 int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
177
178 struct face *intern_face ( /* FRAME_PTR, struct face * */ );
179 static int new_computed_face ( /* FRAME_PTR, struct face * */ );
180 static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
181 static void ensure_face_ready ( /* FRAME_PTR, int id */ );
182 void recompute_basic_faces ( /* FRAME_PTR f */ );
183 \f
184 /* Allocating, copying, and comparing struct faces. */
185
186 /* Allocate a new face */
187 static struct face *
188 allocate_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 }
198
199 /* Make a new face that's a copy of an existing one. */
200 static struct face *
201 copy_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;
209 result->stipple = face->stipple;
210 result->underline = face->underline;
211
212 return result;
213 }
214
215 static int
216 face_eql (face1, face2)
217 struct face *face1, *face2;
218 {
219 return ( face1->font == face2->font
220 && face1->foreground == face2->foreground
221 && face1->background == face2->background
222 && face1->stipple == face2->stipple
223 && face1->underline == face2->underline);
224 }
225 \f
226 /* Interning faces in the `face_vector' cache, and clearing that cache. */
227
228 /* Return the unique display face corresponding to the user-level face FACE.
229 If there isn't one, make one, and find a slot in the face_vector to
230 put it in. */
231 static struct face *
232 get_cached_face (f, face)
233 struct frame *f;
234 struct face *face;
235 {
236 int i, empty = -1;
237 struct face *result;
238
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
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 {
252 face->cached_index = i;
253 return face_vector[i];
254 }
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
279 face->cached_index = empty;
280 return result;
281 }
282
283 /* Given a computed face, return an equivalent display face
284 (one which has a graphics context). */
285
286 struct face *
287 intern_face (f, face)
288 struct frame *f;
289 struct face *face;
290 {
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
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
311 /* Get a specialized display face. */
312 return get_cached_face (f, face);
313 }
314
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
320 void
321 clear_face_vector ()
322 {
323 Lisp_Object rest;
324 Display *dpy = x_current_display;
325 int i;
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];
332 if (face->gc)
333 XFreeGC (dpy, face->gc);
334 xfree (face);
335 }
336 nfaces = 0;
337
338 UNBLOCK_INPUT;
339 }
340 \f
341 /* Allocating and freeing X resources for display faces. */
342
343 /* Make a graphics context for face FACE, which is on frame F,
344 if that can be done. */
345 static void
346 build_face (f, face)
347 struct frame *f;
348 struct face *face;
349 {
350 GC gc;
351 XGCValues xgcv;
352 unsigned long mask;
353
354 BLOCK_INPUT;
355
356 if (face->foreground != FACE_DEFAULT)
357 xgcv.foreground = face->foreground;
358 else
359 xgcv.foreground = f->display.x->foreground_pixel;
360
361 if (face->background != FACE_DEFAULT)
362 xgcv.background = face->background;
363 else
364 xgcv.background = f->display.x->background_pixel;
365
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;
370
371 xgcv.graphics_exposures = 0;
372
373 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
374 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
375 mask, &xgcv);
376
377 #if 0
378 if (face->stipple && face->stipple != FACE_DEFAULT)
379 XSetStipple (x_current_display, gc, face->stipple);
380 #endif
381
382 face->gc = gc;
383
384 UNBLOCK_INPUT;
385 }
386
387 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
388
389 static XFontStruct *
390 load_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
410 static void
411 unload_font (f, font)
412 struct frame *f;
413 XFontStruct *font;
414 {
415 if (!font || font == ((XFontStruct *) FACE_DEFAULT))
416 return;
417
418 BLOCK_INPUT;
419 XFreeFont (x_current_display, font);
420 UNBLOCK_INPUT;
421 }
422
423 static unsigned long
424 load_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
454 static void
455 unload_color (f, pixel)
456 struct frame *f;
457 unsigned long pixel;
458 {
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
466 Colormap cmap;
467 Display *dpy = x_current_display;
468 if (pixel == FACE_DEFAULT
469 || pixel == BLACK_PIX_DEFAULT
470 || pixel == WHITE_PIX_DEFAULT)
471 return;
472 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
473 BLOCK_INPUT;
474 XFreeColors (dpy, cmap, &pixel, 1, 0);
475 UNBLOCK_INPUT;
476 #endif
477 }
478 \f
479 /* Managing parameter face arrays for frames. */
480
481 void
482 init_frame_faces (f)
483 FRAME_PTR f;
484 {
485 ensure_face_ready (f, 0);
486 ensure_face_ready (f, 1);
487
488 FRAME_N_COMPUTED_FACES (f) = 0;
489 FRAME_SIZE_COMPUTED_FACES (f) = 0;
490
491 new_computed_face (f, FRAME_PARAM_FACES (f)[0]);
492 new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
493 recompute_basic_faces (f);
494
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;
515 int n_faces = FRAME_N_PARAM_FACES (XFRAME (result));
516 struct face **faces = FRAME_PARAM_FACES (XFRAME (result));
517
518 for (i = 2; i < n_faces; i++)
519 if (faces[i])
520 ensure_face_ready (f, i);
521 }
522 }
523 }
524
525
526 /* Called from Fdelete_frame. */
527 void
528 free_frame_faces (f)
529 struct frame *f;
530 {
531 Display *dpy = x_current_display;
532 int i;
533
534 BLOCK_INPUT;
535
536 for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
537 {
538 struct face *face = FRAME_PARAM_FACES (f) [i];
539 if (face)
540 {
541 if (face->gc)
542 XFreeGC (dpy, face->gc);
543 unload_font (f, face->font);
544 unload_color (f, face->foreground);
545 unload_color (f, face->background);
546 #if 0
547 unload_pixmap (f, face->stipple);
548 #endif
549 xfree (face);
550 }
551 }
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;
561
562 UNBLOCK_INPUT;
563 }
564 \f
565 /* Interning faces in a frame's face array. */
566
567 static int
568 new_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)
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 *)));
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. */
594 static int
595 intern_computed_face (f, new_face)
596 struct frame *f;
597 struct face *new_face;
598 {
599 int len = FRAME_N_COMPUTED_FACES (f);
600 int i;
601
602 /* Search for a computed face already on F equivalent to FACE. */
603 for (i = 0; i < len; i++)
604 {
605 if (! FRAME_COMPUTED_FACES (f)[i])
606 abort ();
607 if (face_eql (new_face, FRAME_COMPUTED_FACES (f)[i]))
608 return i;
609 }
610
611 /* We didn't find one; add a new one. */
612 return new_computed_face (f, new_face);
613 }
614
615 /* Make parameter face id ID valid on frame F. */
616
617 static void
618 ensure_face_ready (f, id)
619 struct frame *f;
620 int id;
621 {
622 if (FRAME_N_PARAM_FACES (f) <= id)
623 {
624 int n = id + 10;
625 int i;
626 if (!FRAME_N_PARAM_FACES (f))
627 FRAME_PARAM_FACES (f)
628 = (struct face **) xmalloc (sizeof (struct face *) * n);
629 else
630 FRAME_PARAM_FACES (f)
631 = (struct face **) xrealloc (FRAME_PARAM_FACES (f),
632 sizeof (struct face *) * n);
633
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;
637 }
638
639 if (FRAME_PARAM_FACES (f) [id] == 0)
640 FRAME_PARAM_FACES (f) [id] = allocate_face ();
641 }
642 \f
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.
646 We assume that they're both character-cell fonts. */
647
648 int
649 same_size_fonts (font1, font2)
650 XFontStruct *font1, *font2;
651 {
652 XCharStruct *bounds1 = &font1->min_bounds;
653 XCharStruct *bounds2 = &font2->min_bounds;
654
655 return (bounds1->width == bounds2->width);
656 }
657
658 /* Update the line_height of frame F according to the biggest font in
659 any face. Return nonzero if if line_height changes. */
660
661 int
662 frame_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++)
669 if (f->display.x->param_faces[i] != 0
670 && f->display.x->param_faces[i]->font != (XFontStruct *) FACE_DEFAULT)
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)
678 return 0;
679
680 f->display.x->line_height = biggest;
681 return 1;
682 }
683 \f
684 /* Modify face TO by copying from FROM all properties which have
685 nondefault settings. */
686
687 static void
688 merge_faces (from, to)
689 struct face *from, *to;
690 {
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. */
693 if (from->font != (XFontStruct *) FACE_DEFAULT
694 && same_size_fonts (from->font, to->font))
695 to->font = from->font;
696 if (from->foreground != FACE_DEFAULT)
697 to->foreground = from->foreground;
698 if (from->background != FACE_DEFAULT)
699 to->background = from->background;
700 if (from->stipple != FACE_DEFAULT)
701 to->stipple = from->stipple;
702 if (from->underline)
703 to->underline = from->underline;
704 }
705
706 /* Set up the basic set of facial parameters, based on the frame's
707 data; all faces are deltas applied to this. */
708
709 static void
710 compute_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;
720 face->stipple = 0;
721 face->underline = 0;
722
723 /* Avoid a face comparison by making this invalid. */
724 face->cached_index = -1;
725 }
726
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
731 int
732 compute_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);
743
744 return intern_computed_face (f, &face);
745 }
746
747 /* Return the face ID to use to display a special glyph which selects
748 FACE_CODE as the face ID, assuming that ordinarily the face would
749 be CURRENT_FACE. F is the frame. */
750
751 int
752 compute_glyph_face_1 (f, face_name, current_face)
753 struct frame *f;
754 Lisp_Object face_name;
755 int current_face;
756 {
757 struct face face;
758
759 face = *FRAME_COMPUTED_FACES (f)[current_face];
760
761 if (!NILP (face_name))
762 {
763 int facecode = face_name_id_number (f, face_name);
764 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
765 && FRAME_PARAM_FACES (f) [facecode] != 0)
766 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
767 }
768
769 return intern_computed_face (f, &face);
770 }
771 \f
772 /* Return the face ID associated with a buffer position POS.
773 Store into *ENDPTR the position at which a different face is needed.
774 This does not take account of glyphs that specify their own face codes.
775 F is the frame in use for display, and W is a window displaying
776 the current buffer.
777
778 REGION_BEG, REGION_END delimit the region, so it can be highlighted.
779
780 LIMIT is a position not to scan beyond. That is to limit
781 the time this function can take.
782
783 If MOUSE is nonzero, use the character's mouse-face, not its face. */
784
785 int
786 compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
787 struct frame *f;
788 struct window *w;
789 int pos;
790 int region_beg, region_end;
791 int *endptr;
792 int limit;
793 int mouse;
794 {
795 struct face face;
796 Lisp_Object prop, position;
797 int i, j, noverlays;
798 int facecode;
799 Lisp_Object *overlay_vec;
800 Lisp_Object frame;
801 int endpos;
802 Lisp_Object propname;
803
804 /* W must display the current buffer. We could write this function
805 to use the frame and buffer of W, but right now it doesn't. */
806 if (XBUFFER (w->buffer) != current_buffer)
807 abort ();
808
809 XSET (frame, Lisp_Frame, f);
810
811 endpos = ZV;
812 if (pos < region_beg && region_beg < endpos)
813 endpos = region_beg;
814
815 XFASTINT (position) = pos;
816
817 if (mouse)
818 propname = Qmouse_face;
819 else
820 propname = Qface;
821
822 prop = Fget_text_property (position, propname, w->buffer);
823
824 {
825 Lisp_Object limit1, end;
826
827 XFASTINT (limit1) = (limit < endpos ? limit : endpos);
828 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
829 if (INTEGERP (end))
830 endpos = XINT (end);
831 }
832
833 {
834 int next_overlay;
835 int len;
836
837 /* First try with room for 40 overlays. */
838 len = 40;
839 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
840
841 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
842
843 /* If there are more than 40,
844 make enough space for all, and try again. */
845 if (noverlays > len)
846 {
847 len = noverlays;
848 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
849 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
850 }
851
852 if (next_overlay < endpos)
853 endpos = next_overlay;
854 }
855
856 *endptr = endpos;
857
858 /* Optimize the default case. */
859 if (noverlays == 0 && NILP (prop)
860 && !(pos >= region_beg && pos < region_end))
861 return 0;
862
863 compute_base_face (f, &face);
864
865 if (!NILP (prop))
866 {
867 facecode = face_name_id_number (f, prop);
868 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
869 && FRAME_PARAM_FACES (f) [facecode] != 0)
870 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
871 }
872
873 noverlays = sort_overlays (overlay_vec, noverlays, w);
874
875 /* Now merge the overlay data in that order. */
876 for (i = 0; i < noverlays; i++)
877 {
878 prop = Foverlay_get (overlay_vec[i], propname);
879 if (!NILP (prop))
880 {
881 Lisp_Object oend;
882 int oendpos;
883
884 facecode = face_name_id_number (f, prop);
885 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
886 && FRAME_PARAM_FACES (f) [facecode] != 0)
887 merge_faces (FRAME_PARAM_FACES (f)[facecode], &face);
888
889 oend = OVERLAY_END (overlay_vec[i]);
890 oendpos = OVERLAY_POSITION (oend);
891 if (oendpos < endpos)
892 endpos = oendpos;
893 }
894 }
895
896 if (pos >= region_beg && pos < region_end)
897 {
898 if (region_end < endpos)
899 endpos = region_end;
900 if (region_face >= 0 && region_face < next_face_id)
901 merge_faces (FRAME_PARAM_FACES (f)[region_face], &face);
902 }
903
904 *endptr = endpos;
905
906 return intern_computed_face (f, &face);
907 }
908 \f
909 /* Recompute the GC's for the default and modeline faces.
910 We call this after changing frame parameters on which those GC's
911 depend. */
912
913 void
914 recompute_basic_faces (f)
915 FRAME_PTR f;
916 {
917 /* If the frame's faces haven't been initialized yet, don't worry about
918 this stuff. */
919 if (FRAME_N_PARAM_FACES (f) < 2)
920 return;
921
922 BLOCK_INPUT;
923
924 if (FRAME_DEFAULT_FACE (f)->gc)
925 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
926 if (FRAME_MODE_LINE_FACE (f)->gc)
927 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
928
929 compute_base_face (f, FRAME_DEFAULT_FACE (f));
930 compute_base_face (f, FRAME_MODE_LINE_FACE (f));
931
932 merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f));
933 merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f));
934
935 build_face (f, FRAME_DEFAULT_FACE (f));
936 build_face (f, FRAME_MODE_LINE_FACE (f));
937
938 UNBLOCK_INPUT;
939 }
940
941
942 \f
943 /* Lisp interface. */
944
945 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
946 "")
947 (frame)
948 Lisp_Object frame;
949 {
950 CHECK_FRAME (frame, 0);
951 return XFRAME (frame)->face_alist;
952 }
953
954 DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
955 2, 2, 0, "")
956 (frame, value)
957 Lisp_Object frame, value;
958 {
959 CHECK_FRAME (frame, 0);
960 XFRAME (frame)->face_alist = value;
961 return value;
962 }
963
964
965 DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
966 "Create face number FACE-ID on all frames.")
967 (face_id)
968 Lisp_Object face_id;
969 {
970 Lisp_Object rest;
971 int id = XINT (face_id);
972
973 CHECK_NUMBER (face_id, 0);
974 if (id < 0 || id >= next_face_id)
975 error ("Face id out of range");
976
977 for (rest = Vframe_list; !NILP (rest); rest = XCONS (rest)->cdr)
978 {
979 struct frame *f = XFRAME (XCONS (rest)->car);
980 if (FRAME_X_P (f))
981 ensure_face_ready (f, id);
982 }
983 return Qnil;
984 }
985
986
987 DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
988 Sset_face_attribute_internal, 4, 4, 0, "")
989 (face_id, attr_name, attr_value, frame)
990 Lisp_Object face_id, attr_name, attr_value, frame;
991 {
992 struct face *face;
993 struct frame *f;
994 int magic_p;
995 int id;
996
997 CHECK_FRAME (frame, 0);
998 CHECK_NUMBER (face_id, 0);
999 CHECK_SYMBOL (attr_name, 0);
1000
1001 f = XFRAME (frame);
1002 id = XINT (face_id);
1003 if (id < 0 || id >= next_face_id)
1004 error ("Face id out of range");
1005
1006 if (! FRAME_X_P (f))
1007 return Qnil;
1008
1009 ensure_face_ready (f, id);
1010 face = FRAME_PARAM_FACES (f) [XFASTINT (face_id)];
1011
1012 if (EQ (attr_name, intern ("font")))
1013 {
1014 XFontStruct *font = load_font (f, attr_value);
1015 if (face->font != f->display.x->font)
1016 unload_font (f, face->font);
1017 face->font = font;
1018 if (frame_update_line_height (f))
1019 x_set_window_size (f, 0, f->width, f->height);
1020 }
1021 else if (EQ (attr_name, intern ("foreground")))
1022 {
1023 unsigned long new_color = load_color (f, attr_value);
1024 unload_color (f, face->foreground);
1025 face->foreground = new_color;
1026 }
1027 else if (EQ (attr_name, intern ("background")))
1028 {
1029 unsigned long new_color = load_color (f, attr_value);
1030 unload_color (f, face->background);
1031 face->background = new_color;
1032 }
1033 #if 0
1034 else if (EQ (attr_name, intern ("background-pixmap")))
1035 {
1036 unsigned int w, h, d;
1037 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h, &d, 0);
1038 unload_pixmap (f, face->stipple);
1039 if (NILP (attr_value))
1040 new_pixmap = 0;
1041 face->stipple = new_pixmap;
1042 face->pixmap_w = w;
1043 face->pixmap_h = h;
1044 /* face->pixmap_depth = d; */
1045 }
1046 #endif /* 0 */
1047 else if (EQ (attr_name, intern ("underline")))
1048 {
1049 int new = !NILP (attr_value);
1050 face->underline = new;
1051 }
1052 else
1053 error ("unknown face attribute");
1054
1055 if (id == 0 || id == 1)
1056 recompute_basic_faces (f);
1057
1058 /* If we're modifying either of the frame's display faces, that
1059 means that we're changing the parameters of a fixed face code;
1060 since the color/font/whatever is changed but the face ID hasn't,
1061 redisplay won't know to redraw the affected sections. Give it a
1062 kick. */
1063 if (id == 0 || id == 1)
1064 SET_FRAME_GARBAGED (f);
1065 else
1066 /* Otherwise, it's enough to tell it to redisplay the text. */
1067 windows_or_buffers_changed = 1;
1068
1069 return Qnil;
1070 }
1071
1072 DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
1073 0, 0, 0, "")
1074 ()
1075 {
1076 return make_number (next_face_id++);
1077 }
1078
1079 /* Return the face id for name NAME on frame FRAME.
1080 (It should be the same for all frames,
1081 but it's as easy to use the "right" frame to look it up
1082 as to use any other one.) */
1083
1084 int
1085 face_name_id_number (f, name)
1086 FRAME_PTR f;
1087 Lisp_Object name;
1088 {
1089 Lisp_Object tem;
1090
1091 tem = Fcdr (assq_no_quit (name, f->face_alist));
1092 if (NILP (tem))
1093 return 0;
1094 CHECK_VECTOR (tem, 0);
1095 tem = XVECTOR (tem)->contents[2];
1096 CHECK_NUMBER (tem, 0);
1097 return XINT (tem);
1098 }
1099 \f
1100 /* Emacs initialization. */
1101
1102 void
1103 syms_of_xfaces ()
1104 {
1105 Qface = intern ("face");
1106 staticpro (&Qface);
1107 Qmouse_face = intern ("mouse-face");
1108 staticpro (&Qmouse_face);
1109
1110 DEFVAR_INT ("region-face", &region_face,
1111 "Face number to use to highlight the region\n\
1112 The region is highlighted with this face\n\
1113 when Transient Mark mode is enabled and the mark is active.");
1114
1115 defsubr (&Sframe_face_alist);
1116 defsubr (&Sset_frame_face_alist);
1117 defsubr (&Smake_face_internal);
1118 defsubr (&Sset_face_attribute_internal);
1119 defsubr (&Sinternal_next_face_id);
1120 }
1121
1122 #endif /* HAVE_X_WINDOWS */
1123