Merge with git+ssh://pasky.or.cz/srv/git/elinks.git
[elinks.git] / src / dom / select.h
blobe794e1f5d0a5526a4f3d627338d8473f4f5c84da
1 #ifndef EL_DOM_SELECT_H
2 #define EL_DOM_SELECT_H
4 #include "dom/node.h"
7 /* FIXME: Namespaces; *|E */
9 enum dom_select_element_match {
10 /* Gives info about the relation required between two element nodes for
11 * them to match. This is also referred to as combinators. */
12 /* The following are mutually exclusive and at least one must be set.
13 * DOM_SELECT_RELATION_DESCENDANT is the default. */
15 /* Matches any F descendant of E: E F */
16 /* Bogus flag; it is an easy way to have a default. */
17 DOM_SELECT_RELATION_DESCENDANT = 0,
18 /* Matches F being a direct child of E: E > F */
19 DOM_SELECT_RELATION_DIRECT_CHILD = 1,
20 /* Matches F immediate preceded by E: E + F */
21 DOM_SELECT_RELATION_DIRECT_ADJACENT = 2,
22 /* Matches F preceded by E: E ~ F */
23 DOM_SELECT_RELATION_INDIRECT_ADJACENT = 4,
25 DOM_SELECT_RELATION_FLAGS = DOM_SELECT_RELATION_DESCENDANT
26 | DOM_SELECT_RELATION_DIRECT_CHILD
27 | DOM_SELECT_RELATION_DIRECT_ADJACENT
28 | DOM_SELECT_RELATION_INDIRECT_ADJACENT,
30 /* None of the following are mutual exclusive. They can co-exist
31 * although combining them might not make a lot of sense. */
33 /* Matches any element: * */
34 DOM_SELECT_ELEMENT_UNIVERSAL = 8,
35 /* Matches the root node of the document: :root or // */
36 DOM_SELECT_ELEMENT_ROOT = 16,
37 /* Matches the empty element (not even text): :empty */
38 DOM_SELECT_ELEMENT_EMPTY = 32,
40 /* Matches the some n-th child of its parent: :nth-child(n), etc. */
41 DOM_SELECT_ELEMENT_NTH_CHILD = 64,
43 /* Matches the some n-th sibling of its type: :nth-of-type(n), etc. */
44 DOM_SELECT_ELEMENT_NTH_TYPE = 128,
47 /* The special CSS .bar class attribute syntax is represented as
48 * E[class="bar"]. The ID flag will match against any attribute with it's
49 * boolean id member set. XXX: These flags are ATM mutually exclusive. */
50 enum dom_select_attribute_match {
51 /* Matches any set value: E[foo] */
52 DOM_SELECT_ATTRIBUTE_ANY = 1,
53 /* Matches exact value "bar": E[foo="bar"] */
54 DOM_SELECT_ATTRIBUTE_EXACT = 2,
55 /* Matches space seprated list "z bar bee": E[foo~="bar"] */
56 DOM_SELECT_ATTRIBUTE_SPACE_LIST = 4,
57 /* Matches hyphen separated list "z-bar-bee": E[foo|="bar"] */
58 DOM_SELECT_ATTRIBUTE_HYPHEN_LIST = 8,
59 /* Matches value begining; "bar-z-bee": E[foo^="bar"]*/
60 DOM_SELECT_ATTRIBUTE_BEGIN = 16,
61 /* Matches value ending; "z-bee-bar": E[foo$="bar"] */
62 DOM_SELECT_ATTRIBUTE_END = 32,
63 /* Matches value containing; "m33p/bar\++": E[foo*="bar"] */
64 DOM_SELECT_ATTRIBUTE_CONTAINS = 64,
65 /* Matches exact ID attribute value "bar": #bar */
66 DOM_SELECT_ATTRIBUTE_ID = 128,
69 /* Info about text matching is stored in a DOM text node. */
70 enum dom_select_text_match {
71 /* Matches E containing substring "foo": E:contains("foo") */
72 DOM_SELECT_TEXT_CONTAINS = 1,
75 /* Info about what nth child or type to match. The basic syntax is:
77 * <step>n<index>
79 * with a little syntactic sugar.
81 * Examples:
83 * 0n+1 / 1 is first child (same as :first-child)
84 * 2n+0 / 2n / even is all even children
85 * 2n+1 / odd is all odd children
86 * -0n+2 is the last two children
87 * -0n+1 / -1 is last child (same as :last-child)
88 * 1n+0 / n+0 / n is all elements of type
89 * 0n+0 is only element of type (a special internal syntax
90 * used when storing nth-info)
92 * That is, a zero step (0n) means exact indexing, and non-zero step
93 * means stepwise indexing.
95 struct dom_select_nth_match {
96 size_t step;
97 size_t index;
100 #define set_dom_select_nth_match(nth, nthstep, nthindex) \
101 do { (nth)->step = (nthstep); (nth)->index = (nthindex); } while(0)
103 /* This is supposed to be a simple selector. However, this struct is also used
104 * for holding data for attribute matching and element text matching. */
105 struct dom_select_node {
106 /* This holds the DOM node which has data about the node being matched.
107 * It can be either an element, attribute, or a text node. */
108 /* XXX: Keep at the top. This is used for translating dom_node
109 * reference to dom_select_node. */
110 struct dom_node node;
112 /* Only meaningful for element nodes. */
113 /* FIXME: Don't waste memory for non-element nodes. */
114 struct dom_select_nth_match nth_child;
115 struct dom_select_nth_match nth_type;
117 /* Flags, specifying how the matching should be done. */
118 union {
119 enum dom_select_element_match element;
120 enum dom_select_attribute_match attribute;
121 enum dom_select_text_match text;
122 } match;
126 enum dom_select_pseudo {
127 DOM_SELECT_PSEUDO_UNKNOWN = 0,
129 /* Pseudo-elements: */
131 /* Matches first formatted line: ::first-line */
132 DOM_SELECT_PSEUDO_FIRST_LINE = 1,
133 /* Matches first formatted letter: ::first-letter */
134 DOM_SELECT_PSEUDO_FIRST_LETTER = 2,
135 /* Matches text selected by user: ::selection */
136 DOM_SELECT_PSEUDO_SELECTION = 4,
137 /* Matches generated context after an element: ::after */
138 DOM_SELECT_PSEUDO_AFTER = 8,
139 /* Matches generated content before an element: ::before */
140 DOM_SELECT_PSEUDO_BEFORE = 16,
142 /* Pseudo-attributes: */
144 /* Link pseudo-classes: */
145 DOM_SELECT_PSEUDO_LINK = 32, /* :link */
146 DOM_SELECT_PSEUDO_VISITED = 64, /* :visited */
148 /* User action pseudo-classes: */
149 DOM_SELECT_PSEUDO_ACTIVE = 128, /* :active */
150 DOM_SELECT_PSEUDO_HOVER = 256, /* :hover */
151 DOM_SELECT_PSEUDO_FOCUS = 512, /* :focus */
153 /* Target pseudo-class: */
154 DOM_SELECT_PSEUDO_TARGET = 1024, /* :target */
156 /* UI element states pseudo-classes: */
157 DOM_SELECT_PSEUDO_ENABLED = 2048, /* :enabled */
158 DOM_SELECT_PSEUDO_DISABLED = 4096, /* :disabled */
159 DOM_SELECT_PSEUDO_CHECKED = 8192, /* :checked */
160 DOM_SELECT_PSEUDO_INDETERMINATE = 16384, /* :indeterminate */
162 /* XXX: The following pseudo-classes are not kept in the pseudo member
163 * of the dom_select struct so they should not be bitfields. They are
164 * mostly for parsing purposes. */
166 DOM_SELECT_PSEUDO_CONTAINS = 10000,
168 DOM_SELECT_PSEUDO_NTH_CHILD,
169 DOM_SELECT_PSEUDO_NTH_LAST_CHILD,
170 DOM_SELECT_PSEUDO_FIRST_CHILD,
171 DOM_SELECT_PSEUDO_LAST_CHILD,
172 DOM_SELECT_PSEUDO_ONLY_CHILD,
174 DOM_SELECT_PSEUDO_NTH_TYPE,
175 DOM_SELECT_PSEUDO_NTH_LAST_TYPE,
176 DOM_SELECT_PSEUDO_FIRST_TYPE,
177 DOM_SELECT_PSEUDO_LAST_TYPE,
178 DOM_SELECT_PSEUDO_ONLY_TYPE,
180 DOM_SELECT_PSEUDO_ROOT,
181 DOM_SELECT_PSEUDO_EMPTY,
184 struct dom_select {
185 struct dom_select_node *selector;
186 unsigned long specificity;
187 enum dom_select_pseudo pseudo;
190 enum dom_select_syntax {
191 DOM_SELECT_SYNTAX_CSS, /* Example: 'p a[id=node] a:hover */
192 DOM_SELECT_SYNTAX_PATH, /* Example: '//rss/channel/item' */
195 struct dom_select *init_dom_select(enum dom_select_syntax syntax,
196 struct dom_string *string);
198 void done_dom_select(struct dom_select *select);
200 struct dom_node_list *
201 select_dom_nodes(struct dom_select *select, struct dom_node *root);
204 * +------------------------------------------------------------------------------------+
205 * | Pattern | Meaning | Type | Version |
206 * |-----------------------+------------------------------+-------------------+---------|
207 * | * | any element | Universal | 2 |
208 * | | | selector | |
209 * |-----------------------+------------------------------+-------------------+---------|
210 * | E | an element of type E | Type selector | 1 |
211 * |-----------------------+------------------------------+-------------------+---------|
212 * | E F | an F element descendant of | Descendant | 1 |
213 * | | an E element | combinator | |
214 * |-----------------------+------------------------------+-------------------+---------|
215 * | E > F | an F element child of an E | Child combinator | 2 |
216 * | | element | | |
217 * |-----------------------+------------------------------+-------------------+---------|
218 * | E + F | an F element immediately | Direct adjacent | 2 |
219 * | | preceded by an E element | combinator | |
220 * |-----------------------+------------------------------+-------------------+---------|
221 * | E ~ F | an F element preceded by an | Indirect adjacent | 3 |
222 * | | E element | combinator | |
223 * |-----------------------+------------------------------+-------------------+---------|
224 * | E:root | an E element, root of the | Structural | 3 |
225 * | | document | pseudo-classes | |
226 * |-----------------------+------------------------------+-------------------+---------|
227 * | | an E element that has no | Structural | |
228 * | E:empty | children (including text | pseudo-classes | 3 |
229 * | | nodes) | | |
230 * |-----------------------+------------------------------+-------------------+---------|
231 * | E:first-child | an E element, first child of | Structural | 2 |
232 * | | its parent | pseudo-classes | |
233 * |-----------------------+------------------------------+-------------------+---------|
234 * | E:last-child | an E element, last child of | Structural | 3 |
235 * | | its parent | pseudo-classes | |
236 * |-----------------------+------------------------------+-------------------+---------|
237 * | E:nth-child(n) | an E element, the n-th child | Structural | 3 |
238 * | | of its parent | pseudo-classes | |
239 * |-----------------------+------------------------------+-------------------+---------|
240 * | | an E element, the n-th child | Structural | |
241 * | E:nth-last-child(n) | of its parent, counting from | pseudo-classes | 3 |
242 * | | the last one | | |
243 * |-----------------------+------------------------------+-------------------+---------|
244 * | E:first-of-type | an E element, first sibling | Structural | 3 |
245 * | | of its type | pseudo-classes | |
246 * |-----------------------+------------------------------+-------------------+---------|
247 * | E:last-of-type | an E element, last sibling | Structural | 3 |
248 * | | of its type | pseudo-classes | |
249 * |-----------------------+------------------------------+-------------------+---------|
250 * | E:nth-of-type(n) | an E element, the n-th | Structural | 3 |
251 * | | sibling of its type | pseudo-classes | |
252 * |-----------------------+------------------------------+-------------------+---------|
253 * | | an E element, the n-th | Structural | |
254 * | E:nth-last-of-type(n) | sibling of its type, | pseudo-classes | 3 |
255 * | | counting from the last one | | |
256 * |-----------------------+------------------------------+-------------------+---------|
257 * | E:only-child | an E element, only child of | Structural | 3 |
258 * | | its parent | pseudo-classes | |
259 * |-----------------------+------------------------------+-------------------+---------|
260 * | E:only-of-type | an E element, only sibling | Structural | 3 |
261 * | | of its type | pseudo-classes | |
262 * |-----------------------+------------------------------+-------------------+---------|
263 * | | an E element being the | | |
264 * | E:link | source anchor of a hyperlink | The link | |
265 * | E:visited | of which the target is not | pseudo-classes | 1 |
266 * | | yet visited (:link) or | | |
267 * | | already visited (:visited) | | |
268 * |-----------------------+------------------------------+-------------------+---------|
269 * | E:active | an E element during certain | The user action | |
270 * | E:hover | user actions | pseudo-classes | 1 and 2 |
271 * | E:focus | | | |
272 * |-----------------------+------------------------------+-------------------+---------|
273 * | E:target | an E element being the | The target | 3 |
274 * | | target of the referring URI | pseudo-class | |
275 * |-----------------------+------------------------------+-------------------+---------|
276 * | | an element of type E in | | |
277 * | E:lang(fr) | language "fr" (the document | The :lang() | 2 |
278 * | FIXME | language specifies how | pseudo-class | |
279 * | | language is determined) | | |
280 * |-----------------------+------------------------------+-------------------+---------|
281 * | E:enabled | a user interface element E | The UI element | |
282 * | E:disabled | which is enabled or disabled | states | 3 |
283 * | | | pseudo-classes | |
284 * |-----------------------+------------------------------+-------------------+---------|
285 * | | a user interface element E | | |
286 * | E:checked | which is checked or in an | The UI element | |
287 * | E:indeterminate | indeterminate state (for | states | 3 |
288 * | | instance a radio-button or | pseudo-classes | |
289 * | | checkbox) | | |
290 * |-----------------------+------------------------------+-------------------+---------|
291 * | | an E element containing the | Content | |
292 * | E:contains("foo") | substring "foo" in its | pseudo-class | 3 |
293 * | | textual contents | | |
294 * |-----------------------+------------------------------+-------------------+---------|
295 * | E::first-line | the first formatted line of | The :first-line | 1 |
296 * | | an E element | pseudo-element | |
297 * |-----------------------+------------------------------+-------------------+---------|
298 * | E::first-letter | the first formatted letter | The :first-letter | 1 |
299 * | | of an E element | pseudo-element | |
300 * |-----------------------+------------------------------+-------------------+---------|
301 * | | the portion of an E element | The UI element | |
302 * | E::selection | that is currently | fragments | 3 |
303 * | | selected/highlighted by the | pseudo-elements | |
304 * | | user | | |
305 * |-----------------------+------------------------------+-------------------+---------|
306 * | E::before | generated content before an | The :before | 2 |
307 * | | E element | pseudo-element | |
308 * |-----------------------+------------------------------+-------------------+---------|
309 * | E::after | generated content after an E | The :after | 2 |
310 * | | element | pseudo-element | |
311 * |-----------------------+------------------------------+-------------------+---------|
312 * | | an E element whose class is | | |
313 * | E.warning | "warning" (the document | Class selectors | 1 |
314 * | | language specifies how class | | |
315 * | | is determined). | | |
316 * |-----------------------+------------------------------+-------------------+---------|
317 * | E#myid | an E element with ID equal | ID selectors | 1 |
318 * | | to "myid". | | |
319 * |-----------------------+------------------------------+-------------------+---------|
320 * | E[foo] | an E element with a "foo" | Attribute | 2 |
321 * | | attribute | selectors | |
322 * |-----------------------+------------------------------+-------------------+---------|
323 * | | an E element whose "foo" | Attribute | |
324 * | E[foo="bar"] | attribute value is exactly | selectors | 2 |
325 * | | equal to "bar" | | |
326 * |-----------------------+------------------------------+-------------------+---------|
327 * | | an E element whose "foo" | | |
328 * | | attribute value is a list of | Attribute | |
329 * | E[foo~="bar"] | space-separated values, one | selectors | 2 |
330 * | | of which is exactly equal to | | |
331 * | | "bar" | | |
332 * |-----------------------+------------------------------+-------------------+---------|
333 * | | an E element whose "foo" | | |
334 * | E[foo^="bar"] | attribute value begins | Attribute | 3 |
335 * | | exactly with the string | selectors | |
336 * | | "bar" | | |
337 * |-----------------------+------------------------------+-------------------+---------|
338 * | | an E element whose "foo" | Attribute | |
339 * | E[foo$="bar"] | attribute value ends exactly | selectors | 3 |
340 * | | with the string "bar" | | |
341 * |-----------------------+------------------------------+-------------------+---------|
342 * | | an E element whose "foo" | Attribute | |
343 * | E[foo*="bar"] | attribute value contains the | selectors | 3 |
344 * | | substring "bar" | | |
345 * |-----------------------+------------------------------+-------------------+---------|
346 * | | an E element whose | | |
347 * | | "hreflang" attribute has a | Attribute | |
348 * | E[hreflang|="en"] | hyphen-separated list of | selectors | 2 |
349 * | | values beginning (from the | | |
350 * | | left) with "en" | | |
351 * |-----------------------+------------------------------+-------------------+---------|
352 * | E:not(s) | an E element that does not | Negation | 3 |
353 * | FIXME | match simple selector s | pseudo-class | |
354 * +------------------------------------------------------------------------------------+
357 #endif