2 Copyright (C) 1993, 1994 Free Software Foundation.
4 This file is part of GNU Emacs.
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)
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.
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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* This is derived from work by Lucid (some parts very loosely so). */
23 #include <sys/types.h>
33 /* The number of face-id's in use (same for all frames). */
34 static int next_face_id
;
46 #include "dispextern.h"
47 #include "blockinput.h"
49 #include "intervals.h"
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
56 #ifdef XOS_NEEDS_TIME_H
69 #endif /* HAVE_X_WINDOWS */
71 /* An explanation of the face data structures. */
73 /* ========================= Face Data Structures =========================
75 Let FACE-NAME be a symbol naming a face.
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]
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
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
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.)
95 (assq FACE-NAME global-face-data) returns a vector describing the
96 global parameters for that face.
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
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.
123 Each computed face belongs to a particular frame.
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.
132 If a computed face has 0 as its font,
133 it is unused, and can be reused by new_computed_face.
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.
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.
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
156 /* Definitions and declarations. */
158 /* The number of the face to use to indicate the region. */
159 static int region_face
;
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)
165 Lisp_Object Qface
, Qmouse_face
;
166 Lisp_Object Qpixmap_spec_p
;
168 int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
170 struct face
*intern_face ( /* FRAME_PTR, struct face * */ );
171 static int new_computed_face ( /* FRAME_PTR, struct face * */ );
172 static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
173 static void ensure_face_ready ( /* FRAME_PTR, int id */ );
174 void recompute_basic_faces ( /* FRAME_PTR f */ );
176 /* Allocating, copying, and comparing struct faces. */
178 /* Allocate a new face */
182 struct face
*result
= (struct face
*) xmalloc (sizeof (struct face
));
183 bzero (result
, sizeof (struct face
));
184 result
->font
= (XFontStruct
*) FACE_DEFAULT
;
185 result
->fontset
= -1;
186 result
->foreground
= FACE_DEFAULT
;
187 result
->background
= FACE_DEFAULT
;
188 result
->stipple
= FACE_DEFAULT
;
192 /* Make a new face that's a copy of an existing one. */
197 struct face
*result
= allocate_face ();
199 result
->font
= face
->font
;
200 result
->fontset
= face
->fontset
;
201 result
->foreground
= face
->foreground
;
202 result
->background
= face
->background
;
203 result
->stipple
= face
->stipple
;
204 result
->underline
= face
->underline
;
205 result
->pixmap_h
= face
->pixmap_h
;
206 result
->pixmap_w
= face
->pixmap_w
;
212 face_eql (face1
, face2
)
213 struct face
*face1
, *face2
;
215 return ( face1
->font
== face2
->font
216 && face1
->fontset
== face2
->fontset
217 && face1
->foreground
== face2
->foreground
218 && face1
->background
== face2
->background
219 && face1
->stipple
== face2
->stipple
220 && face1
->underline
== face2
->underline
);
223 /* Managing graphics contexts of faces. */
225 #ifdef HAVE_X_WINDOWS
226 /* Given a computed face, construct its graphics context if necessary. */
229 intern_face (f
, face
)
242 if (face
->foreground
!= FACE_DEFAULT
)
243 xgcv
.foreground
= face
->foreground
;
245 xgcv
.foreground
= f
->output_data
.x
->foreground_pixel
;
247 if (face
->background
!= FACE_DEFAULT
)
248 xgcv
.background
= face
->background
;
250 xgcv
.background
= f
->output_data
.x
->background_pixel
;
252 if (face
->font
&& face
->font
!= (XFontStruct
*) FACE_DEFAULT
)
253 xgcv
.font
= face
->font
->fid
;
255 xgcv
.font
= f
->output_data
.x
->font
->fid
;
257 xgcv
.graphics_exposures
= 0;
259 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
260 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
262 xgcv
.fill_style
= FillStippled
;
263 xgcv
.stipple
= x_bitmap_pixmap (f
, face
->stipple
);
264 mask
|= GCFillStyle
| GCStipple
;
267 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
271 /* We used the following GC for all non-ASCII characters by changing
272 only GCfont each time. */
273 face
->non_ascii_gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
281 /* Clear out all graphics contexts for all computed faces
282 except for the default and mode line faces.
283 This should be done from time to time just to avoid
284 keeping too many graphics contexts that are no longer needed. */
289 Lisp_Object tail
, frame
;
292 FOR_EACH_FRAME (tail
, frame
)
294 FRAME_PTR f
= XFRAME (frame
);
298 Display
*dpy
= FRAME_X_DISPLAY (f
);
300 for (i
= 2; i
< FRAME_N_COMPUTED_FACES (f
); i
++)
302 struct face
*face
= FRAME_COMPUTED_FACES (f
) [i
];
305 XFreeGC (dpy
, face
->gc
);
306 XFreeGC (dpy
, face
->non_ascii_gc
);
316 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps.
318 These functions operate on param faces only.
319 Computed faces get their fonts, colors and pixmaps
320 by merging param faces. */
330 return (XFontStruct
*) FACE_DEFAULT
;
332 CHECK_STRING (name
, 0);
334 font
= XLoadQueryFont (FRAME_X_DISPLAY (f
), (char *) XSTRING (name
)->data
);
338 Fsignal (Qerror
, Fcons (build_string ("undefined font"),
339 Fcons (name
, Qnil
)));
344 unload_font (f
, font
)
348 int len
= FRAME_N_COMPUTED_FACES (f
);
351 if (!font
|| font
== ((XFontStruct
*) FACE_DEFAULT
))
355 /* Invalidate any computed faces which use this font,
356 and free their GC's if they have any. */
357 for (i
= 2; i
< len
; i
++)
359 struct face
*face
= FRAME_COMPUTED_FACES (f
)[i
];
360 if (face
->font
== font
)
362 Display
*dpy
= FRAME_X_DISPLAY (f
);
364 XFreeGC (dpy
, face
->gc
);
366 /* This marks the computed face as available to reuse. */
371 XFreeFont (FRAME_X_DISPLAY (f
), font
);
386 CHECK_STRING (name
, 0);
387 /* if the colormap is full, defined_color will return a best match
388 to the values in an an existing cell. */
389 result
= defined_color(f
, (char *) XSTRING (name
)->data
, &color
, 1);
391 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
392 Fcons (name
, Qnil
)));
393 return (unsigned long) color
.pixel
;
397 unload_color (f
, pixel
)
402 Display
*dpy
= FRAME_X_DISPLAY (f
);
403 int class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
405 if (pixel
== FACE_DEFAULT
406 || pixel
== BLACK_PIX_DEFAULT (f
)
407 || pixel
== WHITE_PIX_DEFAULT (f
))
409 cmap
= DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy
));
411 /* If display has an immutable color map, freeing colors is not
412 necessary and some servers don't allow it. So don't do it. */
413 if (! (class == StaticColor
|| class == StaticGray
|| class == TrueColor
))
415 int len
= FRAME_N_COMPUTED_FACES (f
);
419 /* Invalidate any computed faces which use this color,
420 and free their GC's if they have any. */
421 for (i
= 2; i
< len
; i
++)
423 struct face
*face
= FRAME_COMPUTED_FACES (f
)[i
];
424 if (face
->foreground
== pixel
425 || face
->background
== pixel
)
427 Display
*dpy
= FRAME_X_DISPLAY (f
);
429 XFreeGC (dpy
, face
->gc
);
431 /* This marks the computed face as available to reuse. */
436 XFreeColors (dpy
, cmap
, &pixel
, 1, (unsigned long)0);
441 DEFUN ("pixmap-spec-p", Fpixmap_spec_p
, Spixmap_spec_p
, 1, 1, 0,
442 "Return t if OBJECT is a valid pixmap specification.")
446 Lisp_Object height
, width
;
448 return ((STRINGP (object
)
450 && CONSP (XCONS (object
)->cdr
)
451 && CONSP (XCONS (XCONS (object
)->cdr
)->cdr
)
452 && NILP (XCONS (XCONS (XCONS (object
)->cdr
)->cdr
)->cdr
)
453 && (width
= XCONS (object
)->car
, INTEGERP (width
))
454 && (height
= XCONS (XCONS (object
)->cdr
)->car
, INTEGERP (height
))
455 && STRINGP (XCONS (XCONS (XCONS (object
)->cdr
)->cdr
)->car
)
458 /* The string must have enough bits for width * height. */
459 && ((XSTRING (XCONS (XCONS (XCONS (object
)->cdr
)->cdr
)->car
)->size
460 * (BITS_PER_INT
/ sizeof (int)))
461 >= XFASTINT (width
) * XFASTINT (height
))))
465 /* Load a bitmap according to NAME (which is either a file name
466 or a pixmap spec). Return the bitmap_id (see xfns.c)
467 or get an error if NAME is invalid.
469 Store the bitmap width in *W_PTR and height in *H_PTR. */
472 load_pixmap (f
, name
, w_ptr
, h_ptr
)
475 unsigned int *w_ptr
, *h_ptr
;
483 tem
= Fpixmap_spec_p (name
);
485 wrong_type_argument (Qpixmap_spec_p
, name
);
491 /* Decode a bitmap spec into a bitmap. */
496 w
= XINT (Fcar (name
));
497 h
= XINT (Fcar (Fcdr (name
)));
498 bits
= Fcar (Fcdr (Fcdr (name
)));
500 bitmap_id
= x_create_bitmap_from_data (f
, XSTRING (bits
)->data
,
505 /* It must be a string -- a file name. */
506 bitmap_id
= x_create_bitmap_from_file (f
, name
);
511 Fsignal (Qerror
, Fcons (build_string ("invalid or undefined bitmap"),
512 Fcons (name
, Qnil
)));
514 *w_ptr
= x_bitmap_width (f
, bitmap_id
);
515 *h_ptr
= x_bitmap_height (f
, bitmap_id
);
520 #else /* !HAVE_X_WINDOWS */
522 /* Stubs for MSDOS when not under X. */
525 intern_face (f
, face
)
549 CHECK_STRING (name
, 0);
550 result
= call1 (Qmsdos_color_translate
, name
);
551 if (INTEGERP (result
))
552 return XINT (result
);
554 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
555 Fcons (name
, Qnil
)));
558 #endif /* !HAVE_X_WINDOWS */
561 /* Managing parameter face arrays for frames. */
567 ensure_face_ready (f
, 0);
568 ensure_face_ready (f
, 1);
570 FRAME_N_COMPUTED_FACES (f
) = 0;
571 FRAME_SIZE_COMPUTED_FACES (f
) = 0;
573 new_computed_face (f
, FRAME_PARAM_FACES (f
)[0]);
574 new_computed_face (f
, FRAME_PARAM_FACES (f
)[1]);
575 recompute_basic_faces (f
);
577 /* Find another X frame. */
579 Lisp_Object tail
, frame
, result
;
582 FOR_EACH_FRAME (tail
, frame
)
583 if ((FRAME_MSDOS_P (XFRAME (frame
)) || FRAME_X_P (XFRAME (frame
)))
584 && XFRAME (frame
) != f
)
590 /* If we didn't find any X frames other than f, then we don't need
591 any faces other than 0 and 1, so we're okay. Otherwise, make
592 sure that all faces valid on the selected frame are also valid
593 on this new frame. */
597 int n_faces
= FRAME_N_PARAM_FACES (XFRAME (result
));
598 struct face
**faces
= FRAME_PARAM_FACES (XFRAME (result
));
600 for (i
= 2; i
< n_faces
; i
++)
602 ensure_face_ready (f
, i
);
608 /* Called from Fdelete_frame. */
614 Display
*dpy
= FRAME_X_DISPLAY (f
);
619 for (i
= 0; i
< FRAME_N_PARAM_FACES (f
); i
++)
621 struct face
*face
= FRAME_PARAM_FACES (f
) [i
];
624 if (face
->fontset
< 0)
625 unload_font (f
, face
->font
);
626 unload_color (f
, face
->foreground
);
627 unload_color (f
, face
->background
);
628 x_destroy_bitmap (f
, face
->stipple
);
632 xfree (FRAME_PARAM_FACES (f
));
633 FRAME_PARAM_FACES (f
) = 0;
634 FRAME_N_PARAM_FACES (f
) = 0;
636 /* All faces in FRAME_COMPUTED_FACES use resources copied from
637 FRAME_PARAM_FACES; we can free them without fuss.
638 But we do free the GCs and the face objects themselves. */
639 for (i
= 0; i
< FRAME_N_COMPUTED_FACES (f
); i
++)
641 struct face
*face
= FRAME_COMPUTED_FACES (f
) [i
];
646 XFreeGC (dpy
, face
->gc
);
647 XFreeGC (dpy
, face
->non_ascii_gc
);
652 xfree (FRAME_COMPUTED_FACES (f
));
653 FRAME_COMPUTED_FACES (f
) = 0;
654 FRAME_N_COMPUTED_FACES (f
) = 0;
659 /* Interning faces in a frame's face array. */
662 new_computed_face (f
, new_face
)
664 struct face
*new_face
;
666 int len
= FRAME_N_COMPUTED_FACES (f
);
669 /* Search for an unused computed face in the middle of the table. */
670 for (i
= 0; i
< len
; i
++)
672 struct face
*face
= FRAME_COMPUTED_FACES (f
)[i
];
675 FRAME_COMPUTED_FACES (f
)[i
] = copy_face (new_face
);
680 if (i
>= FRAME_SIZE_COMPUTED_FACES (f
))
682 int new_size
= i
+ 32;
684 FRAME_COMPUTED_FACES (f
)
685 = (struct face
**) (FRAME_SIZE_COMPUTED_FACES (f
) == 0
686 ? xmalloc (new_size
* sizeof (struct face
*))
687 : xrealloc (FRAME_COMPUTED_FACES (f
),
688 new_size
* sizeof (struct face
*)));
689 FRAME_SIZE_COMPUTED_FACES (f
) = new_size
;
692 i
= FRAME_N_COMPUTED_FACES (f
)++;
693 FRAME_COMPUTED_FACES (f
)[i
] = copy_face (new_face
);
698 /* Find a match for NEW_FACE in a FRAME's computed face array, and add
699 it if we don't find one. */
701 intern_computed_face (f
, new_face
)
703 struct face
*new_face
;
705 int len
= FRAME_N_COMPUTED_FACES (f
);
708 /* Search for a computed face already on F equivalent to FACE. */
709 for (i
= 0; i
< len
; i
++)
711 if (! FRAME_COMPUTED_FACES (f
)[i
])
713 if (face_eql (new_face
, FRAME_COMPUTED_FACES (f
)[i
]))
717 /* We didn't find one; add a new one. */
718 return new_computed_face (f
, new_face
);
721 /* Make parameter face id ID valid on frame F. */
724 ensure_face_ready (f
, id
)
728 if (FRAME_N_PARAM_FACES (f
) <= id
)
732 if (!FRAME_N_PARAM_FACES (f
))
733 FRAME_PARAM_FACES (f
)
734 = (struct face
**) xmalloc (sizeof (struct face
*) * n
);
736 FRAME_PARAM_FACES (f
)
737 = (struct face
**) xrealloc (FRAME_PARAM_FACES (f
),
738 sizeof (struct face
*) * n
);
740 bzero (FRAME_PARAM_FACES (f
) + FRAME_N_PARAM_FACES (f
),
741 (n
- FRAME_N_PARAM_FACES (f
)) * sizeof (struct face
*));
742 FRAME_N_PARAM_FACES (f
) = n
;
745 if (FRAME_PARAM_FACES (f
) [id
] == 0)
746 FRAME_PARAM_FACES (f
) [id
] = allocate_face ();
749 #ifdef HAVE_X_WINDOWS
750 /* Return non-zero if FONT1 and FONT2 have the same width.
751 We do not check the height, because we can now deal with
753 We assume that they're both character-cell fonts. */
756 same_size_fonts (font1
, font2
)
757 XFontStruct
*font1
, *font2
;
759 XCharStruct
*bounds1
= &font1
->min_bounds
;
760 XCharStruct
*bounds2
= &font2
->min_bounds
;
762 return (bounds1
->width
== bounds2
->width
);
765 /* Update the line_height of frame F according to the biggest font in
766 any face. Return nonzero if if line_height changes. */
769 frame_update_line_height (f
)
773 int fontset
= f
->output_data
.x
->fontset
;
774 int biggest
= (fontset
> 0
775 ? FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
]->height
776 : FONT_HEIGHT (f
->output_data
.x
->font
));
778 for (i
= 0; i
< f
->output_data
.x
->n_param_faces
; i
++)
779 if (f
->output_data
.x
->param_faces
[i
] != 0
780 && f
->output_data
.x
->param_faces
[i
]->font
!= (XFontStruct
*) FACE_DEFAULT
)
782 int height
= ((fontset
= f
->output_data
.x
->param_faces
[i
]->fontset
) > 0
783 ? FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
]->height
784 : FONT_HEIGHT (f
->output_data
.x
->param_faces
[i
]->font
));
786 if (height
> biggest
)
790 if (biggest
== f
->output_data
.x
->line_height
)
793 f
->output_data
.x
->line_height
= biggest
;
796 #endif /* not HAVE_X_WINDOWS */
798 /* Modify face TO by copying from FROM all properties which have
799 nondefault settings. */
802 merge_faces (from
, to
)
803 struct face
*from
, *to
;
805 /* Only merge the font if it's the same width as the base font.
806 Otherwise ignore it, since we can't handle it properly. */
807 if (from
->font
!= (XFontStruct
*) FACE_DEFAULT
808 && same_size_fonts (from
->font
, to
->font
))
809 to
->font
= from
->font
;
810 if (from
->fontset
!= -1)
811 to
->fontset
= from
->fontset
;
812 if (from
->foreground
!= FACE_DEFAULT
)
813 to
->foreground
= from
->foreground
;
814 if (from
->background
!= FACE_DEFAULT
)
815 to
->background
= from
->background
;
816 if (from
->stipple
!= FACE_DEFAULT
)
818 to
->stipple
= from
->stipple
;
819 to
->pixmap_h
= from
->pixmap_h
;
820 to
->pixmap_w
= from
->pixmap_w
;
823 to
->underline
= from
->underline
;
826 /* Set up the basic set of facial parameters, based on the frame's
827 data; all faces are deltas applied to this. */
830 compute_base_face (f
, face
)
835 face
->foreground
= FRAME_FOREGROUND_PIXEL (f
);
836 face
->background
= FRAME_BACKGROUND_PIXEL (f
);
837 face
->font
= FRAME_FONT (f
);
843 /* Return the face ID to use to display a special glyph which selects
844 FACE_CODE as the face ID, assuming that ordinarily the face would
845 be CURRENT_FACE. F is the frame. */
848 compute_glyph_face (f
, face_code
, current_face
)
850 int face_code
, current_face
;
854 face
= *FRAME_COMPUTED_FACES (f
)[current_face
];
856 if (face_code
>= 0 && face_code
< FRAME_N_PARAM_FACES (f
)
857 && FRAME_PARAM_FACES (f
) [face_code
] != 0)
858 merge_faces (FRAME_PARAM_FACES (f
) [face_code
], &face
);
860 return intern_computed_face (f
, &face
);
863 /* Return the face ID to use to display a special glyph which selects
864 FACE_CODE as the face ID, assuming that ordinarily the face would
865 be CURRENT_FACE. F is the frame. */
868 compute_glyph_face_1 (f
, face_name
, current_face
)
870 Lisp_Object face_name
;
875 face
= *FRAME_COMPUTED_FACES (f
)[current_face
];
877 if (!NILP (face_name
))
879 int facecode
= face_name_id_number (f
, face_name
);
880 if (facecode
>= 0 && facecode
< FRAME_N_PARAM_FACES (f
)
881 && FRAME_PARAM_FACES (f
) [facecode
] != 0)
882 merge_faces (FRAME_PARAM_FACES (f
) [facecode
], &face
);
885 return intern_computed_face (f
, &face
);
888 /* Return the face ID associated with a buffer position POS.
889 Store into *ENDPTR the position at which a different face is needed.
890 This does not take account of glyphs that specify their own face codes.
891 F is the frame in use for display, and W is a window displaying
894 REGION_BEG, REGION_END delimit the region, so it can be highlighted.
896 LIMIT is a position not to scan beyond. That is to limit
897 the time this function can take.
899 If MOUSE is nonzero, use the character's mouse-face, not its face. */
902 compute_char_face (f
, w
, pos
, region_beg
, region_end
, endptr
, limit
, mouse
)
906 int region_beg
, region_end
;
912 Lisp_Object prop
, position
;
915 Lisp_Object
*overlay_vec
;
918 Lisp_Object propname
;
920 /* W must display the current buffer. We could write this function
921 to use the frame and buffer of W, but right now it doesn't. */
922 if (XBUFFER (w
->buffer
) != current_buffer
)
925 XSETFRAME (frame
, f
);
928 if (pos
< region_beg
&& region_beg
< endpos
)
931 XSETFASTINT (position
, pos
);
934 propname
= Qmouse_face
;
938 prop
= Fget_text_property (position
, propname
, w
->buffer
);
941 Lisp_Object limit1
, end
;
943 XSETFASTINT (limit1
, (limit
< endpos
? limit
: endpos
));
944 end
= Fnext_single_property_change (position
, propname
, w
->buffer
, limit1
);
953 /* First try with room for 40 overlays. */
955 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
957 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
,
958 &next_overlay
, (int *) 0);
960 /* If there are more than 40,
961 make enough space for all, and try again. */
965 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
966 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
,
967 &next_overlay
, (int *) 0);
970 if (next_overlay
< endpos
)
971 endpos
= next_overlay
;
976 /* Optimize the default case. */
977 if (noverlays
== 0 && NILP (prop
)
978 && !(pos
>= region_beg
&& pos
< region_end
))
981 compute_base_face (f
, &face
);
985 /* We have a list of faces, merge them in reverse order */
990 length
= Fsafe_length (prop
);
991 len
= XFASTINT (length
);
993 /* Put them into an array */
994 faces
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
995 for (j
= 0; j
< len
; j
++)
997 faces
[j
] = Fcar (prop
);
1000 /* So that we can merge them in the reverse order */
1001 for (j
= len
- 1; j
>= 0; j
--)
1003 facecode
= face_name_id_number (f
, faces
[j
]);
1004 if (facecode
>= 0 && facecode
< FRAME_N_PARAM_FACES (f
)
1005 && FRAME_PARAM_FACES (f
) [facecode
] != 0)
1006 merge_faces (FRAME_PARAM_FACES (f
) [facecode
], &face
);
1009 else if (!NILP (prop
))
1011 facecode
= face_name_id_number (f
, prop
);
1012 if (facecode
>= 0 && facecode
< FRAME_N_PARAM_FACES (f
)
1013 && FRAME_PARAM_FACES (f
) [facecode
] != 0)
1014 merge_faces (FRAME_PARAM_FACES (f
) [facecode
], &face
);
1017 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1019 /* Now merge the overlay data in that order. */
1020 for (i
= 0; i
< noverlays
; i
++)
1022 prop
= Foverlay_get (overlay_vec
[i
], propname
);
1025 /* We have a list of faces, merge them in reverse order */
1030 length
= Fsafe_length (prop
);
1031 len
= XFASTINT (length
);
1033 /* Put them into an array */
1034 faces
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
1035 for (j
= 0; j
< len
; j
++)
1037 faces
[j
] = Fcar (prop
);
1040 /* So that we can merge them in the reverse order */
1041 for (j
= len
- 1; j
>= 0; j
--)
1043 facecode
= face_name_id_number (f
, faces
[j
]);
1044 if (facecode
>= 0 && facecode
< FRAME_N_PARAM_FACES (f
)
1045 && FRAME_PARAM_FACES (f
) [facecode
] != 0)
1046 merge_faces (FRAME_PARAM_FACES (f
) [facecode
], &face
);
1049 else if (!NILP (prop
))
1054 facecode
= face_name_id_number (f
, prop
);
1055 if (facecode
>= 0 && facecode
< FRAME_N_PARAM_FACES (f
)
1056 && FRAME_PARAM_FACES (f
) [facecode
] != 0)
1057 merge_faces (FRAME_PARAM_FACES (f
)[facecode
], &face
);
1059 oend
= OVERLAY_END (overlay_vec
[i
]);
1060 oendpos
= OVERLAY_POSITION (oend
);
1061 if (oendpos
< endpos
)
1066 if (pos
>= region_beg
&& pos
< region_end
)
1068 if (region_end
< endpos
)
1069 endpos
= region_end
;
1070 if (region_face
>= 0 && region_face
< next_face_id
)
1071 merge_faces (FRAME_PARAM_FACES (f
)[region_face
], &face
);
1076 return intern_computed_face (f
, &face
);
1079 /* Recompute the GC's for the default and modeline faces.
1080 We call this after changing frame parameters on which those GC's
1084 recompute_basic_faces (f
)
1087 /* If the frame's faces haven't been initialized yet, don't worry about
1089 if (FRAME_N_PARAM_FACES (f
) < 2)
1094 if (FRAME_DEFAULT_FACE (f
)->gc
)
1096 XFreeGC (FRAME_X_DISPLAY (f
), FRAME_DEFAULT_FACE (f
)->gc
);
1097 XFreeGC (FRAME_X_DISPLAY (f
), FRAME_DEFAULT_FACE (f
)->non_ascii_gc
);
1099 if (FRAME_MODE_LINE_FACE (f
)->gc
)
1101 XFreeGC (FRAME_X_DISPLAY (f
), FRAME_MODE_LINE_FACE (f
)->gc
);
1102 XFreeGC (FRAME_X_DISPLAY (f
), FRAME_MODE_LINE_FACE (f
)->non_ascii_gc
);
1104 compute_base_face (f
, FRAME_DEFAULT_FACE (f
));
1105 compute_base_face (f
, FRAME_MODE_LINE_FACE (f
));
1107 merge_faces (FRAME_DEFAULT_PARAM_FACE (f
), FRAME_DEFAULT_FACE (f
));
1108 merge_faces (FRAME_MODE_LINE_PARAM_FACE (f
), FRAME_MODE_LINE_FACE (f
));
1110 intern_face (f
, FRAME_DEFAULT_FACE (f
));
1111 intern_face (f
, FRAME_MODE_LINE_FACE (f
));
1118 /* Lisp interface. */
1120 DEFUN ("make-face-internal", Fmake_face_internal
, Smake_face_internal
, 1, 1, 0,
1121 "Create face number FACE-ID on all frames.")
1123 Lisp_Object face_id
;
1125 Lisp_Object rest
, frame
;
1126 int id
= XINT (face_id
);
1128 CHECK_NUMBER (face_id
, 0);
1129 if (id
< 0 || id
>= next_face_id
)
1130 error ("Face id out of range");
1132 FOR_EACH_FRAME (rest
, frame
)
1134 if (FRAME_MSDOS_P (XFRAME (frame
)) || FRAME_X_P (XFRAME (frame
)))
1135 ensure_face_ready (XFRAME (frame
), id
);
1141 DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal
,
1142 Sset_face_attribute_internal
, 4, 4, 0, "")
1143 (face_id
, attr_name
, attr_value
, frame
)
1144 Lisp_Object face_id
, attr_name
, attr_value
, frame
;
1152 CHECK_FRAME (frame
, 0);
1153 CHECK_NUMBER (face_id
, 0);
1154 CHECK_SYMBOL (attr_name
, 0);
1157 id
= XINT (face_id
);
1158 if (id
< 0 || id
>= next_face_id
)
1159 error ("Face id out of range");
1161 if (! FRAME_X_P (f
) && ! FRAME_MSDOS_P (f
))
1164 ensure_face_ready (f
, id
);
1165 face
= FRAME_PARAM_FACES (f
) [XFASTINT (face_id
)];
1167 if (EQ (attr_name
, intern ("font")))
1169 #if defined (MSDOS) && !defined (HAVE_X_WINDOWS)
1170 /* The one and only font. Must *not* be zero (which
1171 is taken to mean an unused face nowadays). */
1172 face
->font
= (XFontStruct
*)1 ;
1177 if (NILP (attr_value
))
1179 font
= (XFontStruct
*) FACE_DEFAULT
;
1184 CHECK_STRING (attr_value
, 0);
1185 fontset
= fs_query_fontset (f
, XSTRING (attr_value
)->data
);
1188 struct font_info
*fontp
;
1190 if (!(fontp
= FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
1191 CHARSET_ASCII
, NULL
, fontset
)))
1193 Fcons (build_string ("ASCII font can't be loaded"),
1194 Fcons (attr_value
, Qnil
)));
1195 font
= (XFontStruct
*) (fontp
->font
);
1198 font
= load_font (f
, attr_value
);
1201 if (face
->fontset
== -1 && face
->font
!= f
->output_data
.x
->font
)
1202 unload_font (f
, face
->font
);
1205 face
->fontset
= fontset
;
1206 if (frame_update_line_height (f
))
1207 x_set_window_size (f
, 0, f
->width
, f
->height
);
1208 /* Must clear cache, since it might contain the font
1209 we just got rid of. */
1213 else if (EQ (attr_name
, intern ("foreground")))
1215 unsigned long new_color
= load_color (f
, attr_value
);
1216 unload_color (f
, face
->foreground
);
1217 face
->foreground
= new_color
;
1220 else if (EQ (attr_name
, intern ("background")))
1222 unsigned long new_color
= load_color (f
, attr_value
);
1223 unload_color (f
, face
->background
);
1224 face
->background
= new_color
;
1227 else if (EQ (attr_name
, intern ("background-pixmap")))
1230 unsigned long new_pixmap
= load_pixmap (f
, attr_value
, &w
, &h
);
1231 x_destroy_bitmap (f
, face
->stipple
);
1232 face
->stipple
= new_pixmap
;
1237 else if (EQ (attr_name
, intern ("underline")))
1239 int new = !NILP (attr_value
);
1240 face
->underline
= new;
1243 error ("unknown face attribute");
1245 if (id
== 0 || id
== 1)
1246 recompute_basic_faces (f
);
1248 /* We must redraw the frame whenever any face font or color changes,
1249 because it's possible that a merged (display) face
1250 contains the font or color we just replaced.
1251 And we must inhibit any Expose events until the redraw is done,
1252 since they would try to use the invalid display faces. */
1255 SET_FRAME_GARBAGED (f
);
1256 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
1261 /* Return the face id for name NAME on frame FRAME.
1262 (It should be the same for all frames,
1263 but it's as easy to use the "right" frame to look it up
1264 as to use any other one.) */
1267 face_name_id_number (f
, name
)
1273 tem
= Fcdr (assq_no_quit (name
, f
->face_alist
));
1276 CHECK_VECTOR (tem
, 0);
1277 tem
= XVECTOR (tem
)->contents
[2];
1278 CHECK_NUMBER (tem
, 0);
1282 #endif /* HAVE_FACES */
1285 DEFUN ("frame-face-alist", Fframe_face_alist
, Sframe_face_alist
, 1, 1, 0,
1290 CHECK_FRAME (frame
, 0);
1291 return XFRAME (frame
)->face_alist
;
1294 DEFUN ("set-frame-face-alist", Fset_frame_face_alist
, Sset_frame_face_alist
,
1297 Lisp_Object frame
, value
;
1299 CHECK_FRAME (frame
, 0);
1300 XFRAME (frame
)->face_alist
= value
;
1304 DEFUN ("internal-next-face-id", Finternal_next_face_id
, Sinternal_next_face_id
,
1308 return make_number (next_face_id
++);
1311 /* Emacs initialization. */
1317 Qface
= intern ("face");
1319 Qmouse_face
= intern ("mouse-face");
1320 staticpro (&Qmouse_face
);
1321 Qpixmap_spec_p
= intern ("pixmap-spec-p");
1322 staticpro (&Qpixmap_spec_p
);
1324 DEFVAR_INT ("region-face", ®ion_face
,
1325 "Face number to use to highlight the region\n\
1326 The region is highlighted with this face\n\
1327 when Transient Mark mode is enabled and the mark is active.");
1329 defsubr (&Smake_face_internal
);
1330 defsubr (&Sset_face_attribute_internal
);
1331 #endif /* HAVE_FACES */
1333 #ifdef HAVE_X_WINDOWS
1334 defsubr (&Spixmap_spec_p
);
1337 defsubr (&Sframe_face_alist
);
1338 defsubr (&Sset_frame_face_alist
);
1339 defsubr (&Sinternal_next_face_id
);