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