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