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