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