428
|
1 /* Face data structures.
|
|
2 Copyright (C) 1995 Board of Trustees, University of Illinois.
|
771
|
3 Copyright (C) 1995, 2002 Ben Wing
|
428
|
4
|
|
5 This file is part of XEmacs.
|
|
6
|
|
7 XEmacs is free software; you can redistribute it and/or modify it
|
|
8 under the terms of the GNU General Public License as published by the
|
|
9 Free Software Foundation; either version 2, or (at your option) any
|
|
10 later version.
|
|
11
|
|
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
|
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
15 for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with XEmacs; see the file COPYING. If not, write to
|
|
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
20 Boston, MA 02111-1307, USA. */
|
|
21
|
|
22 /* Synched up with: Not in FSF. */
|
|
23
|
440
|
24 #ifndef INCLUDED_faces_h_
|
|
25 #define INCLUDED_faces_h_
|
428
|
26
|
771
|
27 #include "charset.h" /* for NUM_LEADING_BYTES */
|
3659
|
28 #include "specifier.h"
|
428
|
29
|
440
|
30 /* a Lisp_Face is the C object corresponding to a face. There is one
|
|
31 of these per face. It basically contains all of the specifiers for
|
|
32 the built-in face properties, plus the plist of user-specified
|
428
|
33 properties. */
|
|
34
|
|
35 struct Lisp_Face
|
|
36 {
|
3017
|
37 struct LCRECORD_HEADER header;
|
428
|
38
|
|
39 Lisp_Object name;
|
|
40 Lisp_Object doc_string;
|
|
41 unsigned int dirty :1; /* Set whenever a face property is changed on
|
|
42 a face. */
|
|
43
|
|
44 Lisp_Object foreground;
|
|
45 Lisp_Object background;
|
|
46 Lisp_Object font;
|
|
47
|
|
48 Lisp_Object display_table;
|
|
49 Lisp_Object background_pixmap;
|
|
50
|
|
51 Lisp_Object underline;
|
|
52 Lisp_Object strikethru;
|
|
53 Lisp_Object highlight;
|
|
54 Lisp_Object dim;
|
|
55 Lisp_Object blinking;
|
|
56 Lisp_Object reverse;
|
|
57
|
|
58 Lisp_Object plist;
|
|
59
|
|
60 Lisp_Object charsets_warned_about;
|
|
61 };
|
|
62
|
|
63 /*
|
|
64
|
|
65 A face cache element caches the results of instantiating the
|
|
66 properties of a face in a particular window. (Instantiation can
|
|
67 take a long time so this is very important.) Each window contains
|
|
68 an array of face cache elements (called the "face cache"), one for
|
|
69 each face that has been seen in the window so far.
|
|
70
|
|
71 Some tricky stuff is done to make sure the face cache does not
|
|
72 become inconsistent:
|
|
73
|
|
74 1) Switching buffers in a window clears the face cache for that
|
|
75 window, because this can change the way any property is
|
|
76 instantiated in the window.
|
|
77 2) Setting a face property causes that face to be marked as
|
|
78 dirty. This causes various stuff to happen to make sure
|
|
79 the appropriate face cache elements are invalidated.
|
|
80 (#### Actually this doesn't work quite right, and errs
|
|
81 too much on the side of invalidating unnecessary stuff.)
|
|
82
|
|
83 There are also face cache elements for "merged faces", which are the
|
|
84 result of merging all the faces that overlap a particular buffer
|
|
85 position. The merging is always done in the context of a particular
|
|
86 domain (specifically, a window), and the face cache element is
|
|
87 specific to a particular window. (Face cache elements are contained
|
|
88 in an array that is attached to each struct_window.) The reason that
|
|
89 the merging takes place in the context of a particular window has
|
|
90 to do with the way the merging works:
|
|
91
|
|
92 1) All extents overlying the buffer position are sorted by descending
|
|
93 priority.
|
|
94 2) The property of a particular merged face comes from the highest-
|
|
95 priority face that specifies a value for that particular property.
|
|
96 3) The way to determine whether a face specifies a value for a
|
|
97 particular property is to instantiate that face's property in
|
|
98 the window in question with the no-fallback option set, to
|
|
99 see if we got anything.
|
|
100
|
|
101 For Mule, things get a bit trickier because there can be multiple
|
|
102 fonts per face/window combination -- the charset is an argument
|
|
103 to specifier-instance.
|
|
104
|
|
105 We have two possible data structure representations:
|
|
106
|
|
107 1) Keep the original "one font per face cache element" representation
|
|
108 and use a different face cache element for each charset.
|
|
109 2) Allow multiple fonts to be in a single face cache element.
|
|
110
|
|
111 I've chosen to use (2) -- the data structure gets more complicated
|
|
112 but the algorithms for maintaining face cache elements end up
|
|
113 simpler.
|
|
114 */
|
|
115
|
|
116 #define NUM_STATIC_CACHEL_FACES 4
|
|
117
|
|
118 typedef struct face_cachel face_cachel;
|
|
119 struct face_cachel
|
|
120 {
|
3092
|
121 #ifdef NEW_GC
|
|
122 struct lrecord_header header;
|
3263
|
123 #endif /* NEW_GC */
|
428
|
124 /* There are two kinds of cachels; those created from a single face
|
|
125 and those created by merging more than one face. In the former
|
|
126 case, the FACE element specifies the face used. In the latter
|
|
127 case, the MERGED_FACES_STATIC and MERGED_FACES elements specify
|
|
128 the faces used for merging by giving the indices of the
|
|
129 corresponding single-face cachels.
|
|
130
|
|
131 Formerly we didn't bother to keep track of the faces used for
|
442
|
132 merging. We do now because we need to do so because there is no
|
428
|
133 other way to properly handle multiple charsets for Mule in the
|
|
134 presence of display tables short of always computing the values
|
|
135 for all charsets, which is very expensive. Instead, we use a
|
|
136 lazy scheme where we only compute the font for a particular charset
|
|
137 when it is needed. (The exception is the font for the ASCII charset.
|
|
138 We always compute it, just like the other attributes, because
|
|
139 many places in the C code refer to the font of the ASCII charset
|
|
140 and expect it to always be there.)
|
|
141
|
|
142 We store the first four faces in a static array, and use a
|
|
143 Dynarr for the rest. This has the advantage that the space used
|
|
144 is small but the Dynarr will almost never be created, so we
|
|
145 won't spend much time in malloc()/free().
|
|
146
|
|
147 The order of the faces here is decreasing extent priority. */
|
|
148 Lisp_Object face;
|
|
149 int merged_faces_static[NUM_STATIC_CACHEL_FACES];
|
|
150 int_dynarr *merged_faces;
|
|
151 int nfaces;
|
|
152
|
|
153 /* The values stored here are computed by calling specifier_instance()
|
|
154 on the appropriate specifiers. This means that we will have either
|
|
155 a value computed from the face itself or a value computed from the
|
|
156 default face. We need to distinguish the two so that merging works
|
|
157 properly -- a value that comes from the default face is treated
|
|
158 as "unspecified" during merging and is overridden by lower-priority
|
|
159 faces. This is what the _specified flags below are for. */
|
|
160
|
|
161 Lisp_Object foreground;
|
|
162 Lisp_Object background;
|
771
|
163 /* There are currently 128 or 129 possible charsets under Mule. For the
|
428
|
164 moment we just take the easy way out and allocate space for each
|
|
165 of them. This avoids messing with Dynarrs.
|
|
166
|
|
167 #### We should look into this and probably clean it up
|
3094
|
168 to use Dynarrs. This may be a big space hog as is.
|
|
169 sjt sez: doesn't look like it, my total face cache is 170KB.
|
|
170 Could be reduced to maybe 50KB. */
|
428
|
171 Lisp_Object font[NUM_LEADING_BYTES];
|
|
172
|
|
173 Lisp_Object display_table;
|
|
174 Lisp_Object background_pixmap;
|
|
175
|
|
176 unsigned int underline :1;
|
|
177 unsigned int strikethru :1;
|
|
178 unsigned int highlight :1;
|
|
179 unsigned int dim :1;
|
|
180 unsigned int blinking :1;
|
|
181 unsigned int reverse :1;
|
|
182
|
|
183 /* Used when merging to tell if the above field represents an actual
|
|
184 value of this face or a fallback value. */
|
3659
|
185 DECLARE_INLINE_LISP_BIT_VECTOR(NUM_LEADING_BYTES) font_specified;
|
|
186
|
428
|
187 unsigned int foreground_specified :1;
|
|
188 unsigned int background_specified :1;
|
|
189 unsigned int display_table_specified :1;
|
|
190 unsigned int background_pixmap_specified :1;
|
|
191
|
|
192 unsigned int strikethru_specified :1;
|
|
193 unsigned int underline_specified :1;
|
|
194 unsigned int highlight_specified :1;
|
|
195 unsigned int dim_specified :1;
|
|
196 unsigned int blinking_specified :1;
|
|
197 unsigned int reverse_specified :1;
|
|
198
|
|
199 /* The updated flag is set after we calculate the values for the
|
|
200 face cachel and cleared whenever a face changes, to indicate
|
|
201 that the values stored here might be wrong. The next time
|
|
202 we go to access the values, we recompute them; if any values
|
|
203 change, we set the DIRTY flag, which tells the output routines
|
|
204 that a face value has in fact changed and the sections of text
|
|
205 using this face need to be redrawn.
|
|
206
|
|
207 It is trickier with fonts because we don't automatically
|
|
208 recompute the fonts but do it only when it is necessary.
|
|
209 (The ASCII font is an exception, of course; see above).
|
|
210
|
|
211 In the case of fonts, we maintain a separate updated flag
|
|
212 for each font. Whenever we need to access the font for
|
|
213 a particular charset, we recalculate it if either its
|
|
214 value is Qunbound (meaning it's never been computed at all)
|
|
215 or the updated flag is not set. We set the dirty flag if
|
|
216 the value is not the same as before and the previous value
|
|
217 was not Qunbound.
|
|
218
|
|
219 #### Note that we don't yet deal with the case of the new
|
|
220 value being Qunbound, as could happen if no fonts of the
|
|
221 right sort are available on the system. In this case, the
|
|
222 whole program will just crash. For the moment, this is
|
|
223 OK (for debugging purposes) but we should fix this by
|
|
224 storing a "blank font" if the instantiation fails. */
|
|
225 unsigned int dirty :1;
|
|
226 unsigned int updated :1;
|
3659
|
227
|
|
228 DECLARE_INLINE_LISP_BIT_VECTOR(NUM_LEADING_BYTES) font_updated;
|
|
229
|
|
230 /* Whether the font for the charset in question was determined in the
|
|
231 "final stage"; that is, the last stage Lisp code could specify it,
|
|
232 after the initial stage and before the fallback. */
|
|
233 DECLARE_INLINE_LISP_BIT_VECTOR(NUM_LEADING_BYTES) font_final_stage;
|
428
|
234 };
|
|
235
|
3092
|
236 #ifdef NEW_GC
|
|
237 typedef struct face_cachel Lisp_Face_Cachel;
|
|
238
|
|
239 DECLARE_LRECORD (face_cachel, Lisp_Face_Cachel);
|
|
240
|
|
241 #define XFACE_CACHEL(x) \
|
|
242 XRECORD (x, face_cachel, Lisp_Face_Cachel)
|
|
243 #define wrap_face_cachel(p) wrap_record (p, face_cachel)
|
|
244 #define FACE_CACHEL_P(x) RECORDP (x, face_cachel)
|
|
245 #define CHECK_FACE_CACHEL(x) CHECK_RECORD (x, face_cachel)
|
|
246 #define CONCHECK_FACE_CACHEL(x) CONCHECK_RECORD (x, face_cachel)
|
|
247 #endif /* NEW_GC */
|
|
248
|
440
|
249 DECLARE_LRECORD (face, Lisp_Face);
|
|
250 #define XFACE(x) XRECORD (x, face, Lisp_Face)
|
617
|
251 #define wrap_face(p) wrap_record (p, face)
|
428
|
252 #define FACEP(x) RECORDP (x, face)
|
|
253 #define CHECK_FACE(x) CHECK_RECORD (x, face)
|
|
254
|
|
255 Lisp_Object ensure_face_cachel_contains_charset (struct face_cachel *cachel,
|
|
256 Lisp_Object domain,
|
|
257 Lisp_Object charset);
|
|
258 void ensure_face_cachel_complete (struct face_cachel *cachel,
|
|
259 Lisp_Object domain,
|
|
260 unsigned char *charsets);
|
|
261 void update_face_cachel_data (struct face_cachel *cachel,
|
|
262 Lisp_Object domain,
|
|
263 Lisp_Object face);
|
|
264 void face_cachel_charset_font_metric_info (struct face_cachel *cachel,
|
|
265 unsigned char *charsets,
|
|
266 struct font_metric_info *fm);
|
|
267 void mark_face_cachels (face_cachel_dynarr *elements);
|
|
268 void mark_face_cachels_as_clean (struct window *w);
|
|
269 void mark_face_cachels_as_not_updated (struct window *w);
|
|
270 void reset_face_cachel (struct face_cachel *inst);
|
|
271 void reset_face_cachels (struct window *w);
|
|
272 face_index get_builtin_face_cache_index (struct window *w,
|
|
273 Lisp_Object face);
|
3094
|
274 /* WARNING: this interface may change. */
|
|
275 face_index merge_face_list_to_cache_index (struct window *w,
|
|
276 Lisp_Object *face_list, int count);
|
|
277
|
428
|
278 #ifdef MEMORY_USAGE_STATS
|
|
279 int compute_face_cachel_usage (face_cachel_dynarr *face_cachels,
|
|
280 struct overhead_stats *ovstats);
|
|
281 #endif /* MEMORY_USAGE_STATS */
|
|
282
|
|
283 EXFUN (Fface_name, 1);
|
|
284 EXFUN (Ffind_face, 1);
|
|
285 EXFUN (Fget_face, 1);
|
|
286
|
|
287 extern Lisp_Object Qstrikethru, Vbuilt_in_face_specifiers, Vdefault_face;
|
|
288 extern Lisp_Object Vleft_margin_face, Vpointer_face, Vright_margin_face;
|
432
|
289 extern Lisp_Object Vtext_cursor_face, Vvertical_divider_face;
|
428
|
290 extern Lisp_Object Vtoolbar_face, Vgui_element_face, Vwidget_face;
|
|
291
|
|
292 void mark_all_faces_as_clean (void);
|
|
293 void init_frame_faces (struct frame *f);
|
|
294 void init_device_faces (struct device *d);
|
|
295 void init_global_faces (struct device *d);
|
|
296 face_index get_extent_fragment_face_cache_index (struct window *w,
|
|
297 struct extent_fragment *ef);
|
|
298 void update_frame_face_values (struct frame *f);
|
|
299 void face_property_was_changed (Lisp_Object face, Lisp_Object property,
|
|
300 Lisp_Object locale);
|
|
301 void default_face_font_info (Lisp_Object domain, int *ascent,
|
|
302 int *descent, int *height, int *width,
|
|
303 int *proportional_p);
|
|
304 void default_face_height_and_width (Lisp_Object domain,
|
|
305 int *height, int *width);
|
|
306 void default_face_height_and_width_1 (Lisp_Object domain,
|
|
307 int *height, int *width);
|
|
308
|
|
309 #define FACE_CACHEL_FONT(cachel, charset) \
|
771
|
310 (cachel->font[XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE])
|
428
|
311
|
3659
|
312 #define FACE_CACHEL_FONT_UPDATED(x) \
|
|
313 ((struct Lisp_Bit_Vector *)(&((x)->font_updated)))
|
|
314 #define FACE_CACHEL_FONT_SPECIFIED(x) \
|
|
315 ((struct Lisp_Bit_Vector *)(&((x)->font_specified)))
|
|
316 #define FACE_CACHEL_FONT_FINAL_STAGE(x) \
|
|
317 ((struct Lisp_Bit_Vector *)(&((x)->font_final_stage)))
|
|
318
|
428
|
319 #define WINDOW_FACE_CACHEL(window, index) \
|
|
320 Dynarr_atp ((window)->face_cachels, index)
|
|
321
|
|
322 #define FACE_CACHEL_FINDEX_UNSAFE(cachel, offset) \
|
|
323 ((offset) < NUM_STATIC_CACHEL_FACES \
|
|
324 ? (cachel)->merged_faces_static[offset] \
|
|
325 : Dynarr_at ((cachel)->merged_faces, (offset) - NUM_STATIC_CACHEL_FACES))
|
|
326
|
|
327 #define WINDOW_FACE_CACHEL_FACE(window, index) \
|
|
328 (WINDOW_FACE_CACHEL (window, index)->face)
|
|
329 #define WINDOW_FACE_CACHEL_FOREGROUND(window, index) \
|
|
330 (WINDOW_FACE_CACHEL (window, index)->foreground)
|
|
331 #define WINDOW_FACE_CACHEL_BACKGROUND(window, index) \
|
|
332 (WINDOW_FACE_CACHEL (window, index)->background)
|
|
333 /* #### This can be referenced by various functions,
|
|
334 but face_cachels isn't initialized for the stream device.
|
|
335 Since it doesn't need the value we just return nil here to avoid
|
|
336 blowing up in multiple places. */
|
|
337 #define WINDOW_FACE_CACHEL_FONT(window, index, charset) \
|
|
338 ((window)->face_cachels \
|
|
339 ? FACE_CACHEL_FONT (WINDOW_FACE_CACHEL (window, index), charset) \
|
|
340 : Qnil)
|
|
341 #define WINDOW_FACE_CACHEL_DISPLAY_TABLE(window, index) \
|
|
342 (WINDOW_FACE_CACHEL (window, index)->display_table)
|
|
343 #define WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP(window, index) \
|
|
344 (WINDOW_FACE_CACHEL (window, index)->background_pixmap)
|
|
345 #define WINDOW_FACE_CACHEL_DIRTY(window, index) \
|
|
346 (WINDOW_FACE_CACHEL (window, index)->dirty)
|
|
347 #define WINDOW_FACE_CACHEL_UNDERLINE_P(window, index) \
|
|
348 (WINDOW_FACE_CACHEL (window, index)->underline)
|
|
349 #define WINDOW_FACE_CACHEL_HIGHLIGHT_P(window, index) \
|
|
350 (WINDOW_FACE_CACHEL (window, index)->highlight)
|
|
351 #define WINDOW_FACE_CACHEL_DIM_P(window, index) \
|
|
352 (WINDOW_FACE_CACHEL (window, index)->dim)
|
|
353 #define WINDOW_FACE_CACHEL_BLINKING_P(window, index) \
|
|
354 (WINDOW_FACE_CACHEL (window, index)->blinking)
|
|
355 #define WINDOW_FACE_CACHEL_REVERSE_P(window, index) \
|
|
356 (WINDOW_FACE_CACHEL (window, index)->reverse)
|
|
357
|
|
358 #define FACE_PROPERTY_SPECIFIER(face, property) Fget (face, property, Qnil)
|
|
359
|
|
360 #define FACE_PROPERTY_INSTANCE_1(face, property, domain, errb, no_fallback, depth) \
|
|
361 specifier_instance (FACE_PROPERTY_SPECIFIER (face, property), Qunbound, \
|
|
362 domain, errb, 1, no_fallback, depth)
|
|
363
|
|
364 #define FACE_PROPERTY_INSTANCE(face, property, domain, no_fallback, depth) \
|
793
|
365 FACE_PROPERTY_INSTANCE_1 (face, property, domain, ERROR_ME_DEBUG_WARN, \
|
428
|
366 no_fallback, depth)
|
|
367
|
3659
|
368 Lisp_Object face_property_matching_instance
|
|
369 (Lisp_Object face,
|
|
370 Lisp_Object property,
|
|
371 Lisp_Object charset,
|
|
372 Lisp_Object domain,
|
|
373 Error_Behavior errb,
|
|
374 int no_fallback,
|
|
375 Lisp_Object depth,
|
|
376 enum font_specifier_matchspec_stages stages);
|
428
|
377
|
|
378 #define FACE_PROPERTY_SPEC_LIST(face, property, locale) \
|
|
379 Fspecifier_spec_list (FACE_PROPERTY_SPECIFIER (face, property), \
|
|
380 locale, Qnil, Qnil)
|
498
|
381 #define SET_FACE_PROPERTY(face, property, value, locale, tag, how_to_add) \
|
428
|
382 Fadd_spec_to_specifier (FACE_PROPERTY_SPECIFIER (face, property), \
|
498
|
383 value, locale, tag, how_to_add)
|
428
|
384
|
|
385 #define FACE_FOREGROUND(face, domain) \
|
|
386 FACE_PROPERTY_INSTANCE (face, Qforeground, domain, 0, Qzero)
|
|
387 #define FACE_BACKGROUND(face, domain) \
|
|
388 FACE_PROPERTY_INSTANCE (face, Qbackground, domain, 0, Qzero)
|
3676
|
389
|
|
390 /* Calling this function on the default face with the ASCII character set
|
|
391 may delete any X11 frames; see the code at the end of
|
|
392 x_find_charset_font. */
|
428
|
393 #define FACE_FONT(face, domain, charset) \
|
|
394 face_property_matching_instance (face, Qfont, charset, domain, \
|
3659
|
395 ERROR_ME_DEBUG_WARN, 0, Qzero, \
|
|
396 initial)
|
428
|
397 #define FACE_DISPLAY_TABLE(face, domain) \
|
|
398 FACE_PROPERTY_INSTANCE (face, Qdisplay_table, domain, 0, Qzero)
|
|
399 #define FACE_BACKGROUND_PIXMAP(face, domain) \
|
|
400 FACE_PROPERTY_INSTANCE (face, Qbackground_pixmap, domain, 0, Qzero)
|
|
401 #define FACE_UNDERLINE_P(face, domain) \
|
|
402 (!NILP (FACE_PROPERTY_INSTANCE (face, Qunderline, domain, 0, Qzero)))
|
440
|
403 #define FACE_STRIKETHRU_P(face, domain) \
|
|
404 (!NILP (FACE_PROPERTY_INSTANCE (face, Qstrikethru, domain, 0, Qzero)))
|
428
|
405 #define FACE_HIGHLIGHT_P(face, domain) \
|
|
406 (!NILP (FACE_PROPERTY_INSTANCE (face, Qhighlight, domain, 0, Qzero)))
|
|
407 #define FACE_DIM_P(face, domain) \
|
|
408 (!NILP (FACE_PROPERTY_INSTANCE (face, Qdim, domain, 0, Qzero)))
|
|
409 #define FACE_BLINKING_P(face, domain) \
|
|
410 (!NILP (FACE_PROPERTY_INSTANCE (face, Qblinking, domain, 0, Qzero)))
|
|
411 #define FACE_REVERSE_P(face, domain) \
|
|
412 (!NILP (FACE_PROPERTY_INSTANCE (face, Qreverse, domain, 0, Qzero)))
|
|
413
|
440
|
414 #endif /* INCLUDED_faces_h_ */
|