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