Mercurial > hg > xemacs-beta
comparison src/specifier.h @ 276:6330739388db r21-0b36
Import from CVS: tag r21-0b36
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:30:37 +0200 |
parents | c5d627a313b1 |
children | 7df0dd720c89 |
comparison
equal
deleted
inserted
replaced
275:a68ae4439f57 | 276:6330739388db |
---|---|
22 /* Synched up with: Not in FSF. */ | 22 /* Synched up with: Not in FSF. */ |
23 | 23 |
24 #ifndef _XEMACS_SPECIFIER_H_ | 24 #ifndef _XEMACS_SPECIFIER_H_ |
25 #define _XEMACS_SPECIFIER_H_ | 25 #define _XEMACS_SPECIFIER_H_ |
26 | 26 |
27 /* | |
28 MAGIC SPECIFIERS | |
29 ================ | |
30 | |
31 Magic specifiers are used to provide fallback values for window | |
32 system provided specifications, reflecting user preferences on the | |
33 window system, such as default fonts, colors, scrollbar thickness | |
34 etc. | |
35 | |
36 A magic specifier consists of two specifier objects. The first one | |
37 behaves like a normal specifier in all sences. The second one, a | |
38 ghost specifier, is a fallback value for the first one. | |
39 | |
40 Ghost specifiers have the following properties: | |
41 - Have back pointers to their parent specifiers. | |
42 - Do not have instance data. Instead, they share parent's instance | |
43 data. | |
44 - Have the same methods structure pointer. | |
45 - Share parent's caching scheme. | |
46 - Store fallback value instead of their parent. | |
47 | |
48 Ghost specifiers normally are not modifiable at the lisp level, and | |
49 only used to supply fallback instance values. Although, under | |
50 certain rare conditions, all functions that modify specifiers | |
51 operate on ghost objects. This behavior is controlled by the global | |
52 variable Vreveal_ghoste_specifiers. It is not exposed to lisp, and | |
53 is set during calls to lisp functions which initialize global, | |
54 device and frame defaults, such as | |
55 init-{global,frame,device}-{faces,toolbars,etc}. | |
56 | |
57 Thus, values supplied by resources or other means of a window system | |
58 stored in externally unmodifiable ghost objects. Regular lisp code | |
59 may thus freely modify the normal part of a magic specifier, and | |
60 removing a specification for a particular domain causes the | |
61 specification to consider ghost-provided fallback values, or its own | |
62 fallback value. | |
63 | |
64 Rules of conduct for magic specifiers | |
65 ------------------------------------- | |
66 1. All functions exposed to lisp operate on a ghost specifier when | |
67 Vreveal_ghoste_specifiers is non-nil. This includes both | |
68 modifying and non-modifying functions, such as | |
69 Fspecifier_instance, for symmetry and consistency. | |
70 2. These functions deal with the above condition internally, passing | |
71 mangled specifier pointer to internal functions. The internal | |
72 functions always work on a specifier passed, and do not regard | |
73 the value of Vreveal_ghoste_specifiers. | |
74 3. recompute_*() functions always operate on the whole specifier | |
75 when passed only a ghost object, by substituting it with their | |
76 parent bodily object. | |
77 4. All specifier methods, except for instantiate method, are passed | |
78 the bodily object of the magic specifier. Instantiate method is | |
79 passed the specifier being instantiated. | |
80 5. Only bodily objects are passed to set_specifier_caching function, | |
81 and only these may be cached. | |
82 6. All specifiers are added to Vall_specifiers list, both bodily and | |
83 ghost. The pair of objects is always removed from the list at the | |
84 same time. | |
85 */ | |
86 | |
27 struct specifier_methods | 87 struct specifier_methods |
28 { | 88 { |
29 CONST char *name; | 89 CONST char *name; |
30 Lisp_Object predicate_symbol; | 90 Lisp_Object predicate_symbol; |
31 | 91 |
32 /* Implementation specific methods: */ | 92 /* Implementation specific methods: */ |
33 | 93 |
34 /* #### Document me */ | 94 /* Create method: Initialize specifier data. Optional. */ |
35 /* Create method */ | |
36 void (*create_method) (Lisp_Object specifier); | 95 void (*create_method) (Lisp_Object specifier); |
37 /* Mark method */ | 96 |
97 /* Mark method: Mark any lisp object within specifier data | |
98 structure. Not required if no specifier data are Lisp_Objects. */ | |
38 void (*mark_method) (Lisp_Object specifier, void (*markobj) (Lisp_Object)); | 99 void (*mark_method) (Lisp_Object specifier, void (*markobj) (Lisp_Object)); |
39 /* Equal method */ | 100 |
101 /* Equal method: Compare two specifiers. This is called after | |
102 ensuring that the two specifiers are of the same type, and habe | |
103 the same specs. Quit is inhibited during the call so it is safe | |
104 to call internal_equal(). | |
105 | |
106 If this function is not present, specifiers considered equal when | |
107 the above conditions are met, i.e. as if the method returned | |
108 non-zero. */ | |
40 int (*equal_method) (Lisp_Object sp1, Lisp_Object sp2, int depth); | 109 int (*equal_method) (Lisp_Object sp1, Lisp_Object sp2, int depth); |
41 /* Hash method */ | 110 |
111 /* Hash method: Hash specifier instance data. This has to hash only | |
112 data structure of the specifier, as specs are hashed by the core | |
113 code. | |
114 | |
115 If this function is not present, hashing behaves as if it | |
116 returned zero. */ | |
42 unsigned long (*hash_method) (Lisp_Object specifier, int depth); | 117 unsigned long (*hash_method) (Lisp_Object specifier, int depth); |
43 | 118 |
44 /* Validate method: Given an instantiator, verify that it's | 119 /* Validate method: Given an instantiator, verify that it's |
45 valid for this specifier type. If not, signal an error. | 120 valid for this specifier type. If not, signal an error. |
46 | 121 |
47 If this function is not present, all instantiators are | 122 If this function is not present, all instantiators are considered |
48 considered valid. */ | 123 valid. */ |
49 void (*validate_method) (Lisp_Object instantiator); | 124 void (*validate_method) (Lisp_Object instantiator); |
50 | 125 |
51 /* Validate-matchspec method: Given a matchspec, verify that it's | 126 /* Validate-matchspec method: Given a matchspec, verify that it's |
52 valid for this specifier type. If not, signal an error. | 127 valid for this specifier type. If not, signal an error. |
53 | 128 |
54 If this function is not present, *no* matchspecs are considered | 129 If this function is not present, *no* matchspecs are considered |
55 valid. Note that this differs from validate_method(). */ | 130 valid. Note that this differs from validate_method(). */ |
56 void (*validate_matchspec_method) (Lisp_Object matchspec); | 131 void (*validate_matchspec_method) (Lisp_Object matchspec); |
57 | 132 |
58 /* Instantiate method */ | 133 /* Instantiate method: Return SPECIFIER instance in DOMAIN, |
134 specified by INSTANTIATOR. MATCHSPEC specifies an additional | |
135 constraints on the instance value (see the docstring for | |
136 Fspecifier_matching_instance function). MATCHSPEC is passed | |
137 Qunbound when no matching constraints are imposed. The method is | |
138 called via call_with_suspended_errors(), so allowed to eval | |
139 safely. | |
140 | |
141 DEPTH is a lisp integer denoting current depth of instantiation | |
142 calls. #### WTF a method can do with this? | |
143 | |
144 This method must presume that both INSTANTIATOR and MATCSPEC are | |
145 already validated by the corresponding validate_* methods, and | |
146 may abort if they are invalid. | |
147 | |
148 Return value is an instance, which is returned immediately to the | |
149 caller, or Qunbound to continue instantiation lookup chain. | |
150 | |
151 If this function is not present, INSTANTIATOR is used as the | |
152 specifier instance. This is the usual case for "simple" | |
153 specifiers, like integer and boolean. */ | |
59 Lisp_Object (*instantiate_method) (Lisp_Object specifier, | 154 Lisp_Object (*instantiate_method) (Lisp_Object specifier, |
60 Lisp_Object matchspec, | 155 Lisp_Object matchspec, |
61 Lisp_Object domain, | 156 Lisp_Object domain, |
62 Lisp_Object instantiator, | 157 Lisp_Object instantiator, |
63 /* always an integer, but encapsulated | |
64 as a Lisp_Object so it can be called | |
65 from call_with_suspended_errors() */ | |
66 Lisp_Object depth); | 158 Lisp_Object depth); |
159 | |
67 /* Going-to-add method: Called when an instantiator is about | 160 /* Going-to-add method: Called when an instantiator is about |
68 to be added to a specifier. This function can specify | 161 to be added to a specifier. This function can specify |
69 that different instantiators should be used instead by | 162 that different instantiators should be used instead by |
70 returning an inst-list (possibly containing zero elements). | 163 returning an inst-list (possibly containing zero elements). |
71 If the instantiator is fine as-is, return Qt. The | 164 If the instantiator is fine as-is, return Qt. The |
72 instantiator has been copied with copy-tree, so feel | 165 instantiator has been copied with copy-tree, so feel |
73 free to reuse parts of it to create a new instantiator. | 166 free to reuse parts of it to create a new instantiator. |
74 The tag-set, however, is not copied and is not canonicalized | 167 The tag-set, however, is not copied and is not canonicalized |
75 (that will be done on the result of this function). | 168 (that will be done on the result of this function). */ |
76 */ | |
77 Lisp_Object (*going_to_add_method) (Lisp_Object specifier, | 169 Lisp_Object (*going_to_add_method) (Lisp_Object specifier, |
78 Lisp_Object locale, | 170 Lisp_Object locale, |
79 Lisp_Object tag_set, | 171 Lisp_Object tag_set, |
80 Lisp_Object instantiator); | 172 Lisp_Object instantiator); |
81 /* After-change method */ | 173 |
174 /* After-change method: Called when the SPECIFIER has just been | |
175 changed in LOCALE. The method is called upon: | |
176 * Removing and adding specs to/from the specifier; | |
177 * Changing the specifier fallback. | |
178 | |
179 #### The method may have called more than once per each specifier | |
180 change. | |
181 | |
182 #### Do not still know if this can safely eval. */ | |
82 void (*after_change_method) (Lisp_Object specifier, | 183 void (*after_change_method) (Lisp_Object specifier, |
83 Lisp_Object locale); | 184 Lisp_Object locale); |
84 | 185 |
85 int extra_data_size; | 186 int extra_data_size; |
86 }; | 187 }; |
109 */ | 210 */ |
110 Lisp_Object window_specs; | 211 Lisp_Object window_specs; |
111 Lisp_Object buffer_specs; | 212 Lisp_Object buffer_specs; |
112 | 213 |
113 struct specifier_caching *caching; | 214 struct specifier_caching *caching; |
215 | |
216 /* This can be either nil, for a plain, non-magic specifier object, | |
217 t for the normal part of the magic specifier, or #<specifier> for | |
218 the ghost part of the magic specifier, a pointer to its parent | |
219 object */ | |
220 Lisp_Object magic_parent; | |
221 | |
222 /* Fallback value. For magic specifiers, it is a pointer to the ghost. */ | |
114 Lisp_Object fallback; | 223 Lisp_Object fallback; |
224 | |
115 /* type-specific extra data attached to a specifier */ | 225 /* type-specific extra data attached to a specifier */ |
116 char data[1]; | 226 char data[1]; |
117 }; | 227 }; |
118 | 228 |
119 DECLARE_LRECORD (specifier, struct Lisp_Specifier); | 229 DECLARE_LRECORD (specifier, struct Lisp_Specifier); |
145 INLINE struct type##_specifier * \ | 255 INLINE struct type##_specifier * \ |
146 error_check_##type##_specifier_data (struct Lisp_Specifier *sp); \ | 256 error_check_##type##_specifier_data (struct Lisp_Specifier *sp); \ |
147 INLINE struct type##_specifier * \ | 257 INLINE struct type##_specifier * \ |
148 error_check_##type##_specifier_data (struct Lisp_Specifier *sp) \ | 258 error_check_##type##_specifier_data (struct Lisp_Specifier *sp) \ |
149 { \ | 259 { \ |
260 if (SPECIFIERP (sp->magic_parent)) \ | |
261 { \ | |
262 assert (SPECIFIER_TYPE_P (sp, type)); \ | |
263 sp = XSPECIFIER (sp->magic_parent); \ | |
264 } \ | |
265 else \ | |
266 assert (NILP (sp->magic_parent) || EQ (sp->magic_parent, Qt)); \ | |
150 assert (SPECIFIER_TYPE_P (sp, type)); \ | 267 assert (SPECIFIER_TYPE_P (sp, type)); \ |
151 return (struct type##_specifier *) sp->data; \ | 268 return (struct type##_specifier *) sp->data; \ |
152 } \ | 269 } \ |
153 DECLARE_NOTHING | 270 DECLARE_NOTHING |
154 #else | 271 #else |
181 /***** Macros for accessing specifier types *****/ | 298 /***** Macros for accessing specifier types *****/ |
182 | 299 |
183 #define SPECIFIER_TYPE_P(sp, type) \ | 300 #define SPECIFIER_TYPE_P(sp, type) \ |
184 ((sp)->methods == type##_specifier_methods) | 301 ((sp)->methods == type##_specifier_methods) |
185 | 302 |
303 /* Any of the two of the magic spec */ | |
304 #define MAGIC_SPECIFIER_P(sp) \ | |
305 (!NILP((sp)->magic_parent)) | |
306 /* Normal part of the magic specifier */ | |
307 #define BODILY_SPECIFIER_P(sp) \ | |
308 (EQ ((sp)->magic_parent, Qt)) | |
309 /* Ghost part of the magic specifier */ | |
310 #define GHOST_SPECIFIER_P(sp) \ | |
311 (SPECIFIERP((sp)->magic_parent)) | |
312 /* The same three, when used in GC */ | |
313 #define GC_MAGIC_SPECIFIER_P(sp) \ | |
314 (!GC_NILP((sp)->magic_parent)) | |
315 #define GC_BODILY_SPECIFIER_P(sp) \ | |
316 (GC_EQ ((sp)->magic_parent, Qt)) | |
317 #define GC_GHOST_SPECIFIER_P(sp) \ | |
318 (GC_SPECIFIERP((sp)->magic_parent)) | |
319 | |
320 #define GHOST_SPECIFIER(sp) \ | |
321 (XSPECIFIER ((sp)->fallback)) | |
322 | |
186 #ifdef ERROR_CHECK_TYPECHECK | 323 #ifdef ERROR_CHECK_TYPECHECK |
187 # define SPECIFIER_TYPE_DATA(sp, type) \ | 324 # define SPECIFIER_TYPE_DATA(sp, type) \ |
188 error_check_##type##_specifier_data (sp) | 325 error_check_##type##_specifier_data (sp) |
189 #else | 326 #else |
190 # define SPECIFIER_TYPE_DATA(sp, type) \ | 327 # define SPECIFIER_TYPE_DATA(sp, type) \ |
191 ((struct type##_specifier *) (sp)->data) | 328 ((struct type##_specifier *) \ |
329 (GHOST_SPECIFIER_P(sp) \ | |
330 ? XSPECIFIER((sp)->magic_parent)->data \ | |
331 : (sp)->data)) | |
192 #endif | 332 #endif |
193 | 333 |
194 /* #### Need to create ERROR_CHECKING versions of these. */ | 334 /* #### Need to create ERROR_CHECKING versions of these. */ |
195 | 335 |
196 #define XSPECIFIER_TYPE(x, type) XSPECIFIER (x) | 336 #define XSPECIFIER_TYPE(x, type) XSPECIFIER (x) |
248 EXFUN (Fspecifier_instance, 4); | 388 EXFUN (Fspecifier_instance, 4); |
249 EXFUN (Fvalid_specifier_locale_p, 1); | 389 EXFUN (Fvalid_specifier_locale_p, 1); |
250 | 390 |
251 extern Lisp_Object Qfallback, Qnatnum; | 391 extern Lisp_Object Qfallback, Qnatnum; |
252 | 392 |
393 Lisp_Object make_magic_specifier (Lisp_Object type); | |
253 Lisp_Object decode_locale_list (Lisp_Object locale); | 394 Lisp_Object decode_locale_list (Lisp_Object locale); |
254 extern enum spec_add_meth | 395 extern enum spec_add_meth |
255 decode_how_to_add_specification (Lisp_Object how_to_add); | 396 decode_how_to_add_specification (Lisp_Object how_to_add); |
256 Lisp_Object decode_specifier_tag_set (Lisp_Object tag_set); | 397 Lisp_Object decode_specifier_tag_set (Lisp_Object tag_set); |
257 | 398 |
269 void set_specifier_fallback (Lisp_Object specifier, | 410 void set_specifier_fallback (Lisp_Object specifier, |
270 Lisp_Object fallback); | 411 Lisp_Object fallback); |
271 void recompute_all_cached_specifiers_in_window (struct window *w); | 412 void recompute_all_cached_specifiers_in_window (struct window *w); |
272 void recompute_all_cached_specifiers_in_frame (struct frame *f); | 413 void recompute_all_cached_specifiers_in_frame (struct frame *f); |
273 | 414 |
415 /* Counterparts of Fadd_spec_to_specifier and Fremove_specifier, | |
416 which operate directly on ghost objects */ | |
417 void add_spec_to_ghost_specifier (Lisp_Object specifier, Lisp_Object instantiator, | |
418 Lisp_Object locale, Lisp_Object tag_set, | |
419 Lisp_Object how_to_add); | |
420 void remove_ghost_specifier (Lisp_Object specifier, Lisp_Object locale, | |
421 Lisp_Object tag_set, Lisp_Object exact_p); | |
422 | |
423 int reveal_ghost_specifiers_protected (void); | |
424 | |
274 void cleanup_specifiers (void); | 425 void cleanup_specifiers (void); |
275 void prune_specifiers (int (*obj_marked_p) (Lisp_Object)); | 426 void prune_specifiers (int (*obj_marked_p) (Lisp_Object)); |
276 void setup_device_initial_specifier_tags (struct device *d); | 427 void setup_device_initial_specifier_tags (struct device *d); |
277 void kill_specifier_buffer_locals (Lisp_Object buffer); | 428 void kill_specifier_buffer_locals (Lisp_Object buffer); |
278 | 429 |