1 /* CSS stylesheet handling */
2 /* $Id: stylesheet.c,v 1.50 2005/07/09 18:41:52 miciah Exp $ */
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 list_head
*sels
, enum css_selector_type type
,
30 enum css_selector_relation rel
,
31 unsigned char *name
, int namelen
)
33 struct css_selector
*selector
;
37 foreach (selector
, *sels
) {
38 if (type
!= selector
->type
|| rel
!= selector
->relation
)
40 if (strlcasecmp(name
, namelen
, selector
->name
, -1))
49 init_css_selector(struct list_head
*sels
, enum css_selector_type type
,
50 unsigned char *name
, int namelen
)
52 struct css_selector
*selector
;
54 selector
= mem_calloc(1, sizeof(*selector
));
55 if (!selector
) return NULL
;
57 selector
->relation
= CSR_ROOT
; /* Default */
58 init_list(selector
->leaves
);
60 selector
->type
= type
;
61 init_list(selector
->properties
);
65 namelen
= strlen(name
);
66 selector
->name
= memacpy(name
, namelen
);
67 if (!selector
->name
) {
71 set_mem_comment(selector
, name
, namelen
);
75 add_to_list(*sels
, selector
);
82 get_css_selector(struct list_head
*sels
, enum css_selector_type type
,
83 enum css_selector_relation rel
,
84 unsigned char *name
, int namelen
)
86 struct css_selector
*selector
= NULL
;
88 if (sels
&& name
&& namelen
) {
89 selector
= find_css_selector(sels
, type
, rel
, name
, namelen
);
94 selector
= init_css_selector(sels
, type
, name
, namelen
);
96 selector
->relation
= rel
;
103 static struct css_selector
*
104 copy_css_selector(struct css_stylesheet
*css
, struct css_selector
*orig
)
106 struct css_selector
*copy
;
110 copy
= init_css_selector(&css
->selectors
, orig
->type
,
111 orig
->name
, strlen(orig
->name
));
119 add_selector_property(struct css_selector
*selector
, struct css_property
*prop
)
121 struct css_property
*newprop
= mem_alloc(sizeof(*newprop
));
124 copy_struct(newprop
, prop
);
125 add_to_list(selector
->properties
, newprop
);
130 add_selector_properties(struct css_selector
*selector
,
131 struct list_head
*properties
)
133 struct css_property
*prop
;
135 foreach (prop
, *properties
) {
136 add_selector_property(selector
, prop
);
140 static struct css_selector
*
141 clone_css_selector(struct css_stylesheet
*css
, struct css_selector
*orig
)
143 struct css_selector
*copy
;
147 copy
= copy_css_selector(css
, orig
);
150 add_selector_properties(copy
, &orig
->properties
);
155 merge_css_selectors(struct css_selector
*sel1
, struct css_selector
*sel2
)
157 struct css_property
*prop
;
159 foreach (prop
, sel2
->properties
) {
160 struct css_property
*origprop
;
162 foreach (origprop
, sel1
->properties
)
163 if (origprop
->type
== prop
->type
) {
164 del_from_list(origprop
);
169 /* Not there yet, let's add it. */
170 add_selector_property(sel1
, prop
);
175 done_css_selector(struct css_selector
*selector
)
177 while (selector
->leaves
.next
!= &selector
->leaves
) {
178 done_css_selector(selector
->leaves
.next
);
181 if (selector
->next
) del_from_list(selector
);
182 free_list(selector
->properties
);
183 mem_free_if(selector
->name
);
189 dump_css_selector_tree_iter(struct list_head
*sels
, int level
)
191 struct css_selector
*sel
;
193 foreach (sel
, *sels
) {
194 struct css_property
*prop
;
196 fprintf(stderr
, "%*s +- [%s] type %d rel %d props",
198 sel
->name
, sel
->type
, sel
->relation
);
199 foreach (prop
, sel
->properties
) {
200 fprintf(stderr
, " [%d]", prop
->type
);
202 fprintf(stderr
, "\n");
203 dump_css_selector_tree_iter(&sel
->leaves
, level
+ 1);
208 dump_css_selector_tree(struct list_head
*sels
)
210 dump_css_selector_tree_iter(sels
, 0);
215 struct css_stylesheet
*
216 init_css_stylesheet(css_stylesheet_importer_T importer
, void *import_data
)
218 struct css_stylesheet
*css
;
220 css
= mem_calloc(1, sizeof(*css
));
223 css
->import
= importer
;
224 css
->import_data
= import_data
;
225 init_list(css
->selectors
);
230 mirror_css_stylesheet(struct css_stylesheet
*css1
, struct css_stylesheet
*css2
)
232 struct css_selector
*selector
;
234 foreach (selector
, css1
->selectors
) {
235 clone_css_selector(css2
, selector
);
240 struct css_stylesheet
*
241 clone_css_stylesheet(struct css_stylesheet
*orig
)
243 struct css_stylesheet
*copy
;
244 struct css_selector
*selector
;
246 copy
= init_css_stylesheet(orig
->import
, orig
->import_data
);
249 mirror_css_stylesheet(orig
, copy
);
254 merge_css_stylesheets(struct css_stylesheet
*css1
,
255 struct css_stylesheet
*css2
)
257 struct css_selector
*selector
;
259 assert(css1
&& css2
);
261 /* This is 100% evil. And gonna be a huge bottleneck. Essentially
262 * O(N^2) where we could be much smarter (ie. sort it once and then
263 * always be O(N)). */
265 foreach (selector
, css2
->selectors
) {
266 struct css_selector
*origsel
;
268 origsel
= find_css_selector(&css1
->selectors
, selector
->name
,
269 strlen(selector
->name
));
271 clone_css_selector(css1
, selector
);
273 merge_css_selectors(origsel
, selector
);
280 done_css_stylesheet(struct css_stylesheet
*css
)
282 while (!list_empty(css
->selectors
)) {
283 done_css_selector(css
->selectors
.next
);