1 /** CSS stylesheet handling
13 #include "document/css/property.h"
14 #include "document/css/stylesheet.h"
15 #include "util/error.h"
16 #include "util/lists.h"
17 #include "util/memory.h"
18 #include "util/string.h"
21 /* You can find some mysterious functions commented out here. I planned to use
22 * them for various smart things (well they all report to
23 * merge_css_stylesheets()), but it turns out it makes no sense to merge
24 * stylesheets now (and maybe it won't in the future neither...). But maybe you
25 * will find them useful at some time, so... Dunno. --pasky */
29 find_css_selector(struct css_selector_set
*sels
,
30 enum css_selector_type type
,
31 enum css_selector_relation rel
,
32 const unsigned char *name
, int namelen
)
34 struct css_selector
*selector
;
38 foreach_css_selector (selector
, sels
) {
39 if (type
!= selector
->type
|| rel
!= selector
->relation
)
41 if (c_strlcasecmp(name
, namelen
, selector
->name
, -1))
50 init_css_selector(struct css_selector_set
*sels
,
51 enum css_selector_type type
,
52 enum css_selector_relation relation
,
53 const unsigned char *name
, int namelen
)
55 struct css_selector
*selector
;
57 selector
= mem_calloc(1, sizeof(*selector
));
58 if (!selector
) return NULL
;
60 selector
->relation
= relation
;
61 init_css_selector_set(&selector
->leaves
);
63 selector
->type
= type
;
64 init_list(selector
->properties
);
68 namelen
= strlen(name
);
69 selector
->name
= memacpy(name
, namelen
);
70 if (!selector
->name
) {
71 done_css_selector_set(&selector
->leaves
);
75 set_mem_comment(selector
, name
, namelen
);
79 add_css_selector_to_set(selector
, sels
);
86 set_css_selector_relation(struct css_selector
*selector
,
87 enum css_selector_relation relation
)
89 /* Changing the relation after the selector is in a set might require
90 * setting css_relation_set.may_contain_rel_ancestor_or_parent,
91 * but we don't have a pointer to the set here. */
92 assert(!css_selector_is_in_set(selector
));
93 selector
->relation
= relation
;
97 get_css_selector(struct css_selector_set
*sels
,
98 enum css_selector_type type
,
99 enum css_selector_relation rel
,
100 const unsigned char *name
, int namelen
)
102 struct css_selector
*selector
= NULL
;
104 if (sels
&& name
&& namelen
) {
105 selector
= find_css_selector(sels
, type
, rel
, name
, namelen
);
110 return init_css_selector(sels
, type
, rel
, name
, namelen
);
113 static struct css_selector
*
114 copy_css_selector(struct css_stylesheet
*css
, struct css_selector
*orig
)
116 struct css_selector
*copy
;
119 assert(orig
->relation
== CSR_ROOT
);
121 copy
= init_css_selector(&css
->selectors
, orig
->type
, CSR_ROOT
,
122 orig
->name
, strlen(orig
->name
));
130 add_selector_property(struct css_selector
*selector
, struct css_property
*prop
)
132 struct css_property
*newprop
= mem_alloc(sizeof(*newprop
));
135 copy_struct(newprop
, prop
);
136 add_to_list(selector
->properties
, newprop
);
141 add_selector_properties(struct css_selector
*selector
,
142 LIST_OF(struct css_property
) *properties
)
144 struct css_property
*prop
;
146 foreach (prop
, *properties
) {
147 add_selector_property(selector
, prop
);
151 static struct css_selector
*
152 clone_css_selector(struct css_stylesheet
*css
, struct css_selector
*orig
)
154 struct css_selector
*copy
;
158 copy
= copy_css_selector(css
, orig
);
161 add_selector_properties(copy
, &orig
->properties
);
166 merge_css_selectors(struct css_selector
*sel1
, struct css_selector
*sel2
)
168 struct css_property
*prop
;
170 foreach (prop
, sel2
->properties
) {
171 struct css_property
*origprop
;
173 foreach (origprop
, sel1
->properties
)
174 if (origprop
->type
== prop
->type
) {
175 del_from_list(origprop
);
180 /* Not there yet, let's add it. */
181 add_selector_property(sel1
, prop
);
186 done_css_selector(struct css_selector
*selector
)
188 done_css_selector_set(&selector
->leaves
);
190 if (css_selector_is_in_set(selector
))
191 del_css_selector_from_set(selector
);
192 free_list(selector
->properties
);
193 mem_free_if(selector
->name
);
198 init_css_selector_set(struct css_selector_set
*set
)
200 set
->may_contain_rel_ancestor_or_parent
= 0;
201 init_list(set
->list
);
205 done_css_selector_set(struct css_selector_set
*set
)
207 while (!css_selector_set_empty(set
)) {
208 done_css_selector(css_selector_set_front(set
));
213 add_css_selector_to_set(struct css_selector
*selector
,
214 struct css_selector_set
*set
)
216 assert(!css_selector_is_in_set(selector
));
218 add_to_list(set
->list
, selector
);
219 if (selector
->relation
== CSR_ANCESTOR
220 || selector
->relation
== CSR_PARENT
)
221 set
->may_contain_rel_ancestor_or_parent
= 1;
225 del_css_selector_from_set(struct css_selector
*selector
)
227 del_from_list(selector
);
228 selector
->next
= NULL
;
229 selector
->prev
= NULL
;
234 dump_css_selector_tree_iter(struct css_selector_set
*sels
, int level
)
236 struct css_selector
*sel
;
238 foreach_css_selector (sel
, sels
) {
239 struct css_property
*prop
;
241 fprintf(stderr
, "%*s +- [%s] type %d rel %d props",
243 sel
->name
, sel
->type
, sel
->relation
);
244 foreach (prop
, sel
->properties
) {
245 fprintf(stderr
, " [%d]", prop
->type
);
247 fprintf(stderr
, "\n");
248 dump_css_selector_tree_iter(&sel
->leaves
, level
+ 1);
253 dump_css_selector_tree(struct css_selector_set
*sels
)
255 dump_css_selector_tree_iter(sels
, 0);
260 #if 0 /* used only by clone_css_stylesheet */
261 struct css_stylesheet
*
262 init_css_stylesheet(css_stylesheet_importer_T importer
, void *import_data
)
264 struct css_stylesheet
*css
;
266 css
= mem_calloc(1, sizeof(*css
));
269 css
->import
= importer
;
270 css
->import_data
= import_data
;
271 init_css_selector_set(&css
->selectors
);
277 mirror_css_stylesheet(struct css_stylesheet
*css1
, struct css_stylesheet
*css2
)
279 struct css_selector
*selector
;
281 foreach_css_selector (selector
, &css1
->selectors
) {
282 clone_css_selector(css2
, selector
);
287 struct css_stylesheet
*
288 clone_css_stylesheet(struct css_stylesheet
*orig
)
290 struct css_stylesheet
*copy
;
291 struct css_selector
*selector
;
293 copy
= init_css_stylesheet(orig
->import
, orig
->import_data
);
296 mirror_css_stylesheet(orig
, copy
);
301 merge_css_stylesheets(struct css_stylesheet
*css1
,
302 struct css_stylesheet
*css2
)
304 struct css_selector
*selector
;
306 assert(css1
&& css2
);
308 /* This is 100% evil. And gonna be a huge bottleneck. Essentially
309 * O(N^2) where we could be much smarter (ie. sort it once and then
310 * always be O(N)). */
312 foreach_css_selector (selector
, &css2
->selectors
) {
313 struct css_selector
*origsel
;
315 origsel
= find_css_selector(&css1
->selectors
, selector
->name
,
316 strlen(selector
->name
));
318 clone_css_selector(css1
, selector
);
320 merge_css_selectors(origsel
, selector
);
327 done_css_stylesheet(struct css_stylesheet
*css
)
329 done_css_selector_set(&css
->selectors
);