1 /*
2 * This file is part of libdom.
3 * Licensed under the MIT License,
4 * http://www.opensource.org/licenses/mit-license.php
5 * Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org>
6 */
7
8 #ifndef dom_internal_core_node_h_
9 #define dom_internal_core_node_h_
10
11 #include <stdbool.h>
12
13 #include <libwapcaplet/libwapcaplet.h>
14
15 #include <dom/core/node.h>
16 #include <dom/functypes.h>
17
18 #include "events/event_target.h"
19 #include "events/mutation_event.h"
20
21 #include "utils/list.h"
22
23 /**
24 * User data context attached to a DOM node
25 */
26 struct dom_user_data {
27 dom_string *key; /**< Key for data */
28 void *data; /**< Client-specific data */
29 dom_user_data_handler handler; /**< Callback function */
30
31 struct dom_user_data *next; /**< Next in list */
32 struct dom_user_data *prev; /**< Previous in list */
33 };
34 typedef struct dom_user_data dom_user_data;
35
36 /**
37 * The internally used virtual function table.
38 */
39 typedef struct dom_node_protect_vtable {
40
41 void (*destroy)(dom_node_internal *n);
42 /**< The destroy virtual function, it
43 * should be private to client */
44 dom_exception (*copy)(dom_node_internal *old, dom_node_internal **copy);
45 /**< Copy the old to new as well as
46 * all its attributes, but not its children */
47 } dom_node_protect_vtable;
48
49 /**
50 * The real DOM node object
51 *
52 * DOM nodes are reference counted
53 */
54 struct dom_node_internal {
55 struct dom_node base; /**< The vtable base */
56 void *vtable; /**< The protected vtable */
57
58 dom_string *name; /**< Node name (this is the local part
59 * of a QName in the cases where a
60 * namespace exists) */
61 dom_string *value; /**< Node value */
62 dom_node_type type; /**< Node type */
63 dom_node_internal *parent; /**< Parent node */
64 dom_node_internal *first_child; /**< First child node */
65 dom_node_internal *last_child; /**< Last child node */
66 dom_node_internal *previous; /**< Previous sibling */
67 dom_node_internal *next; /**< Next sibling */
68
69 struct dom_document *owner; /**< Owning document */
70
71 dom_string *namespace; /**< Namespace URI */
72 dom_string *prefix; /**< Namespace prefix */
73
74 struct dom_user_data *user_data; /**< User data list */
75
76 struct list_entry pending_list; /**< The document delete pending list */
77
78 dom_event_target_internal eti; /**< The EventTarget interface */
79 };
80
81 dom_node_internal * _dom_node_create(void);
82
83 dom_exception _dom_node_initialise(struct dom_node_internal *node,
84 struct dom_document *doc, dom_node_type type,
85 dom_string *name, dom_string *value,
86 dom_string *namespace, dom_string *prefix);
87
88 void _dom_node_finalise(dom_node_internal *node);
89
90 bool _dom_node_readonly(const dom_node_internal *node);
91
92 /* Event Target implementation */
93 dom_exception _dom_node_add_event_listener(dom_event_target *et,
94 dom_string *type, struct dom_event_listener *listener,
95 bool capture);
96 dom_exception _dom_node_remove_event_listener(dom_event_target *et,
97 dom_string *type, struct dom_event_listener *listener,
98 bool capture);
99 dom_exception _dom_node_add_event_listener_ns(dom_event_target *et,
100 dom_string *namespace, dom_string *type,
101 struct dom_event_listener *listener, bool capture);
102 dom_exception _dom_node_remove_event_listener_ns(dom_event_target *et,
103 dom_string *namespace, dom_string *type,
104 struct dom_event_listener *listener, bool capture);
105 dom_exception _dom_node_dispatch_event(dom_event_target *et,
106 struct dom_event *evt, bool *success);
107
108 /* The DOM Node's vtable methods */
109 dom_exception _dom_node_get_node_name(dom_node_internal *node,
110 dom_string **result);
111 dom_exception _dom_node_get_node_value(dom_node_internal *node,
112 dom_string **result);
113 dom_exception _dom_node_set_node_value(dom_node_internal *node,
114 dom_string *value);
115 dom_exception _dom_node_get_node_type(dom_node_internal *node,
116 dom_node_type *result);
117 dom_exception _dom_node_get_parent_node(dom_node_internal *node,
118 dom_node_internal **result);
119 dom_exception _dom_node_get_child_nodes(dom_node_internal *node,
120 struct dom_nodelist **result);
121 dom_exception _dom_node_get_first_child(dom_node_internal *node,
122 dom_node_internal **result);
123 dom_exception _dom_node_get_last_child(dom_node_internal *node,
124 dom_node_internal **result);
125 dom_exception _dom_node_get_previous_sibling(dom_node_internal *node,
126 dom_node_internal **result);
127 dom_exception _dom_node_get_next_sibling(dom_node_internal *node,
128 dom_node_internal **result);
129 dom_exception _dom_node_get_attributes(dom_node_internal *node,
130 struct dom_namednodemap **result);
131 dom_exception _dom_node_get_owner_document(dom_node_internal *node,
132 struct dom_document **result);
133 dom_exception _dom_node_insert_before(dom_node_internal *node,
134 dom_node_internal *new_child, dom_node_internal *ref_child,
135 dom_node_internal **result);
136 dom_exception _dom_node_replace_child(dom_node_internal *node,
137 dom_node_internal *new_child, dom_node_internal *old_child,
138 dom_node_internal **result);
139 dom_exception _dom_node_remove_child(dom_node_internal *node,
140 dom_node_internal *old_child,
141 dom_node_internal **result);
142 dom_exception _dom_node_append_child(dom_node_internal *node,
143 dom_node_internal *new_child,
144 dom_node_internal **result);
145 dom_exception _dom_node_has_child_nodes(dom_node_internal *node, bool *result);
146 dom_exception _dom_node_clone_node(dom_node_internal *node, bool deep,
147 dom_node_internal **result);
148 dom_exception _dom_node_normalize(dom_node_internal *node);
149 dom_exception _dom_node_is_supported(dom_node_internal *node,
150 dom_string *feature, dom_string *version,
151 bool *result);
152 dom_exception _dom_node_get_namespace(dom_node_internal *node,
153 dom_string **result);
154 dom_exception _dom_node_get_prefix(dom_node_internal *node,
155 dom_string **result);
156 dom_exception _dom_node_set_prefix(dom_node_internal *node,
157 dom_string *prefix);
158 dom_exception _dom_node_get_local_name(dom_node_internal *node,
159 dom_string **result);
160 dom_exception _dom_node_has_attributes(dom_node_internal *node, bool *result);
161 dom_exception _dom_node_get_base(dom_node_internal *node,
162 dom_string **result);
163 dom_exception _dom_node_compare_document_position(dom_node_internal *node,
164 dom_node_internal *other, uint16_t *result);
165 dom_exception _dom_node_get_text_content(dom_node_internal *node,
166 dom_string **result);
167 dom_exception _dom_node_set_text_content(dom_node_internal *node,
168 dom_string *content);
169 dom_exception _dom_node_is_same(dom_node_internal *node,
170 dom_node_internal *other, bool *result);
171 dom_exception _dom_node_lookup_prefix(dom_node_internal *node,
172 dom_string *namespace, dom_string **result);
173 dom_exception _dom_node_is_default_namespace(dom_node_internal *node,
174 dom_string *namespace, bool *result);
175 dom_exception _dom_node_lookup_namespace(dom_node_internal *node,
176 dom_string *prefix, dom_string **result);
177 dom_exception _dom_node_is_equal(dom_node_internal *node,
178 dom_node_internal *other, bool *result);
179 dom_exception _dom_node_get_feature(dom_node_internal *node,
180 dom_string *feature, dom_string *version,
181 void **result);
182 dom_exception _dom_node_set_user_data(dom_node_internal *node,
183 dom_string *key, void *data,
184 dom_user_data_handler handler, void **result);
185 dom_exception _dom_node_get_user_data(dom_node_internal *node,
186 dom_string *key, void **result);
187
188 #define DOM_NODE_EVENT_TARGET_VTABLE \
189 _dom_node_add_event_listener, \
190 _dom_node_remove_event_listener, \
191 _dom_node_dispatch_event, \
192 _dom_node_add_event_listener_ns, \
193 _dom_node_remove_event_listener_ns
194
195 #define DOM_NODE_VTABLE \
196 _dom_node_try_destroy, \
197 _dom_node_get_node_name, \
198 _dom_node_get_node_value, \
199 _dom_node_set_node_value, \
200 _dom_node_get_node_type, \
201 _dom_node_get_parent_node, \
202 _dom_node_get_child_nodes, \
203 _dom_node_get_first_child, \
204 _dom_node_get_last_child, \
205 _dom_node_get_previous_sibling, \
206 _dom_node_get_next_sibling, \
207 _dom_node_get_attributes, \
208 _dom_node_get_owner_document, \
209 _dom_node_insert_before, \
210 _dom_node_replace_child, \
211 _dom_node_remove_child, \
212 _dom_node_append_child, \
213 _dom_node_has_child_nodes, \
214 _dom_node_clone_node, \
215 _dom_node_normalize, \
216 _dom_node_is_supported, \
217 _dom_node_get_namespace, \
218 _dom_node_get_prefix, \
219 _dom_node_set_prefix, \
220 _dom_node_get_local_name, \
221 _dom_node_has_attributes, \
222 _dom_node_get_base, \
223 _dom_node_compare_document_position, \
224 _dom_node_get_text_content, \
225 _dom_node_set_text_content, \
226 _dom_node_is_same, \
227 _dom_node_lookup_prefix, \
228 _dom_node_is_default_namespace, \
229 _dom_node_lookup_namespace, \
230 _dom_node_is_equal, \
231 _dom_node_get_feature, \
232 _dom_node_set_user_data, \
233 _dom_node_get_user_data
234
235
236 /* Following comes the protected vtable */
237 void _dom_node_destroy(struct dom_node_internal *node);
238 dom_exception _dom_node_copy(struct dom_node_internal *old,
239 struct dom_node_internal **copy);
240
241 #define DOM_NODE_PROTECT_VTABLE \
242 _dom_node_destroy, \
243 _dom_node_copy
244
245
246 /* The destroy API should be used inside DOM module */
dom_node_destroy(struct dom_node_internal * node)247 static inline void dom_node_destroy(struct dom_node_internal *node)
248 {
249 ((dom_node_protect_vtable *) node->vtable)->destroy(node);
250 }
251 #define dom_node_destroy(n) dom_node_destroy((dom_node_internal *) (n))
252
253 /* Copy the Node old to new */
dom_node_copy(struct dom_node_internal * old,struct dom_node_internal ** copy)254 static inline dom_exception dom_node_copy(struct dom_node_internal *old,
255 struct dom_node_internal **copy)
256 {
257 return ((dom_node_protect_vtable *) old->vtable)->copy(old, copy);
258 }
259 #define dom_node_copy(o,c) dom_node_copy((dom_node_internal *) (o), \
260 (dom_node_internal **) (c))
261
262 /* Following are some helper functions */
263 dom_exception _dom_node_copy_internal(dom_node_internal *old,
264 dom_node_internal *new);
265 #define dom_node_copy_internal(o, n) _dom_node_copy_internal( \
266 (dom_node_internal *) (o), (dom_node_internal *) (n))
267
268 #define dom_node_get_owner(n) ((dom_node_internal *) (n))->owner
269
270 #define dom_node_set_owner(n, d) ((dom_node_internal *) (n))->owner = \
271 (struct dom_document *) (d)
272
273 #define dom_node_get_parent(n) ((dom_node_internal *) (n))->parent
274
275 #define dom_node_set_parent(n, p) ((dom_node_internal *) (n))->parent = \
276 (dom_node_internal *) (p)
277
278 #define dom_node_get_refcount(n) ((dom_node_internal *) (n))->refcnt
279
280 dom_exception _dom_merge_adjacent_text(dom_node_internal *p,
281 dom_node_internal *n);
282
283 /* Try to destroy the node, if its refcnt is not zero, then append it to the
284 * owner document's pending list */
285 dom_exception _dom_node_try_destroy(dom_node_internal *node);
286
287 /* To add some node to the pending list */
288 void _dom_node_mark_pending(dom_node_internal *node);
289 #define dom_node_mark_pending(n) _dom_node_mark_pending(\
290 (dom_node_internal *) (n))
291 /* To remove the node from the pending list, this may happen when
292 * a node is removed and then appended to another parent */
293 void _dom_node_remove_pending(dom_node_internal *node);
294 #define dom_node_remove_pending(n) _dom_node_remove_pending(\
295 (dom_node_internal *) (n))
296
297 dom_exception _dom_node_dispatch_node_change_event(dom_document *doc,
298 dom_node_internal *node, dom_node_internal *related,
299 dom_mutation_type change, bool *success);
300 #define dom_node_dispatch_node_change_event( \
301 doc, node, related, change, success) \
302 _dom_node_dispatch_node_change_event((dom_document *) (doc), \
303 (dom_node_internal *) (node), \
304 (dom_node_internal *) (related), \
305 (dom_mutation_type) (change), \
306 (bool *) (success))
307
308 #endif
309