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