1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
2 /* gdome-xml-node.c
3  *
4  * Copyright (C) 1999 Raph Levien <raph@acm.org>
5  * Copyright (C) 2000 Mathieu Lacage <mathieu@gnu.org>
6  * Copyright (C) 2000 Anders Carlsson <andersca@gnu.org>
7  * Copyright (C) 2001 Paolo Casarini <paolo@casarini.org>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27 #include <sys/time.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include "gdome.h"
32 #include "gdome-events.h"
33 #include "gdome-refdebug.h"
34 #include "gdome-treegc.h"
35 #include <libxml/tree.h>
36 #include <libxml/parser.h>
37 #include <libxml/xmlmemory.h>
38 #include <libxml/hash.h>
39 #include "gdome-xml-util.h"
40 #include "gdome-xml-xmlmemory.h"
41 #include "gdome-xml-xmlutil.h"
42 #include "gdome-xml-xmldtdutil.h"
43 #include "gdome-xml-str.h"
44 #include "gdome-evt-event.h"
45 #include "gdome-evt-eventl.h"
46 #include "gdome-evt-mevent.h"
47 #include "gdome-evt-propagation.h"
48 #include "gdome-xml-nodel.h"
49 #include "gdome-xml-node.h"
50 #include "gdome-xml-document.h"
51 #include "gdome-xml-element.h"
52 #include "gdome-xml-attribute.h"
53 #include "gdome-xml-cdata.h"
54 #include "gdome-xml-entityref.h"
55 #include "gdome-xml-text.h"
56 #include "gdome-xml-cdatas.h"
57 #include "gdome-xml-comment.h"
58 #include "gdome-xml-entity.h"
59 #include "gdome-xml-pi.h"
60 #include "gdome-xml-notation.h"
61 #include "gdome-xml-documentt.h"
62 #include "gdome-xml-documentf.h"
63 #include "gdome-xml-domimpl.h"
64 #include "gdome-xpath.h"
65 #include "gdome-xml-xpns.h"
66 
67 /* indexed by node type
68 	 first one is NULL because there
69    is no node type number 0
70    cf: spec p25 (DOM 1). interface Node.
71 */
72 const void * gdome_xml_vtabs[] = {
73 	NULL,
74 	&gdome_xml_el_vtab,
75 	&gdome_xml_a_vtab,
76 	&gdome_xml_t_vtab,
77 	&gdome_xml_cds_vtab,
78 	&gdome_xml_er_vtab,
79 	&gdome_xml_ent_vtab,
80 	&gdome_xml_pi_vtab,
81 	&gdome_xml_c_vtab,
82 	&gdome_xml_doc_vtab,
83 	&gdome_xml_dt_vtab,
84 	&gdome_xml_df_vtab,
85 	&gdome_xml_not_vtab,
86 	&gdome_xml_doc_vtab,
87   &gdome_xml_dt_vtab,
88   NULL,
89   NULL,
90   &gdome_xml_ent_vtab
91 };
92 
93 /***************
94  * Virtual Table
95  **************/
96 const GdomeNodeVtab gdome_xml_n_vtab =
97 {
98 	gdome_xml_n_ref,
99 	gdome_xml_n_unref,
100 	gdome_xml_n_query_interface,
101 	gdome_xml_n_nodeName,
102 	gdome_xml_n_nodeValue,
103 	gdome_xml_n_set_nodeValue,
104 	gdome_xml_n_nodeType,
105 	gdome_xml_n_parentNode,
106 	gdome_xml_n_childNodes,
107 	gdome_xml_n_firstChild,
108 	gdome_xml_n_lastChild,
109 	gdome_xml_n_previousSibling,
110 	gdome_xml_n_nextSibling,
111 	gdome_xml_n_attributes,
112 	gdome_xml_n_ownerDocument,
113 	gdome_xml_n_insertBefore,
114 	gdome_xml_n_replaceChild,
115 	gdome_xml_n_removeChild,
116 	gdome_xml_n_appendChild,
117 	gdome_xml_n_hasChildNodes,
118 	gdome_xml_n_cloneNode,
119 	gdome_xml_n_normalize,
120 	gdome_xml_n_isSupported,
121 	gdome_xml_n_namespaceURI,
122 	gdome_xml_n_prefix,
123 	gdome_xml_n_set_prefix,
124   gdome_xml_n_localName,
125   gdome_xml_n_hasAttributes,
126 	gdome_xml_n_addEventListener,
127 	gdome_xml_n_removeEventListener,
128   gdome_xml_n_dispatchEvent,
129 	gdome_xml_n_subTreeDispatchEvent,
130   gdome_xml_n_canAppend
131 };
132 
133 
134 /* function to get the xmlNode from a GdomeNode */
135 xmlNode *
gdome_xml_n_get_xmlNode(GdomeNode * node)136 gdome_xml_n_get_xmlNode (GdomeNode *node)
137 {
138 	Gdome_xml_Node *xmlnode;
139 
140 	xmlnode = (Gdome_xml_Node *)node;
141 
142 	return xmlnode->n;
143 }
144 
145 /***********************************************************
146  ***** Constructor and Reference Count Implementation ******
147  ***********************************************************/
148 
149 /**
150  * gdome_xml_n_mkref:
151  * @n:  The libxml node of which a Gdome reference is wanted
152  *
153  * Constructor of the Node structure.
154  * Returns: the reference to the Gdome node wanted.
155  */
156 GdomeNode *
gdome_xml_n_mkref(xmlNode * n)157 gdome_xml_n_mkref (xmlNode *n) {
158 	Gdome_xml_Node *result = NULL;
159 	xmlElementType type;
160 
161 	if (n == NULL)
162 		return NULL;
163 
164 	type = n->type;
165 	if (n->_private && type != XML_NAMESPACE_DECL) {
166 		result = (Gdome_xml_Node *)n->_private;
167 		result->refcnt++;
168 	} else {
169 		switch (type) {
170 		case XML_ELEMENT_NODE:
171 		case XML_TEXT_NODE:
172 		case XML_CDATA_SECTION_NODE:
173 		case XML_ENTITY_REF_NODE:
174 		case XML_PI_NODE:
175 		case XML_COMMENT_NODE:
176 		case XML_NOTATION_NODE:
177 		case XML_DOCUMENT_FRAG_NODE:
178 		case XML_ATTRIBUTE_NODE:
179 		case XML_ENTITY_DECL: /*libxml use this instead of XML_ENTITY_NODE*/
180 			result = g_new (Gdome_xml_Node, 1);
181 
182 			result->refcnt = 1;
183       result->vtab = (GdomeNodeVtab *)gdome_xml_vtabs[n->type];
184       result->super.user_data = NULL;
185       result->n = n;
186       if (type == XML_NOTATION_NODE || type == XML_ENTITY_NODE || type == XML_ENTITY_DECL)
187         result->accessType = GDOME_READONLY_NODE;
188       else
189         result->accessType = GDOME_READWRITE_NODE;
190       result->ll = NULL;
191 
192 			n->_private = result;
193 
194 #ifdef DEBUG_REFCNT
195       gdome_refdbg_addRef ((void *)result, GDOME_REFDBG_NODE);
196 #endif
197       gdome_treegc_addNode ((GdomeNode *)result);
198 
199       break;
200     case XML_DOCUMENT_TYPE_NODE:
201     case XML_DTD_NODE:
202       return (GdomeNode *)gdome_xml_dt_mkref ((xmlDtd *)n);
203 		case XML_HTML_DOCUMENT_NODE:
204 		case XML_DOCUMENT_NODE:
205       return (GdomeNode *)gdome_xml_doc_mkref ((xmlDoc *)n);
206 		case XML_NAMESPACE_DECL:
207 			return (GdomeNode *)gdome_xml_xpns_mkref ((xmlNs *)n);
208 		default:
209 			g_warning ("gdome_xml_n_mkref: invalid node type");
210 			break;
211 		}
212 	}
213 	return (GdomeNode *)result;
214 }
215 
216 /**
217  * gdome_xml_n_ref:
218  * @self:  Node Object ref
219  * @exc:  Exception Object ref
220  *
221  * Increase the reference count of the specified Node.
222  */
223 void
gdome_xml_n_ref(GdomeNode * self,GdomeException * exc)224 gdome_xml_n_ref (GdomeNode *self, GdomeException *exc) {
225 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
226 
227   g_return_if_fail (priv != NULL);
228   g_return_if_fail (GDOME_XML_IS_N (priv));
229   g_return_if_fail (exc != NULL);
230 
231 	priv->refcnt++;
232 }
233 
234 /**
235  * gdome_xml_n_unref:
236  * @self:  Node Object ref
237  * @exc:  Exception Object ref
238  *
239  * Decrease the reference count of the specified Node. Free the Node structure
240  * if the Node will have zero reference.
241  */
242 void
gdome_xml_n_unref(GdomeNode * self,GdomeException * exc)243 gdome_xml_n_unref (GdomeNode *self, GdomeException *exc) {
244 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
245   xmlElementType type;
246 
247   g_return_if_fail (priv != NULL);
248 	g_return_if_fail (GDOME_XML_IS_N (priv));
249   g_return_if_fail (exc != NULL);
250 
251   type = gdome_xmlGetType (priv->n);
252   switch (type) {
253   case XML_DOCUMENT_TYPE_NODE:
254   case XML_DTD_NODE:
255     return gdome_xml_dt_unref (self, exc);
256   case XML_DOCUMENT_NODE:
257     return gdome_xml_doc_unref (self, exc);
258   default:
259     if (priv->refcnt > 0)
260       priv->refcnt--;
261 
262     if (priv->refcnt == 0 && priv->ll == NULL) {
263       xmlNode *n = (xmlNode *)priv->n;
264 
265 			gdome_treegc_delNode (self);
266 
267       n->_private = NULL;
268 			if (type != XML_NOTATION_NODE &&
269 					type != XML_ENTITY_DECL &&
270 					n->parent == NULL)
271 				gdome_xmlFreeSubtree (n);
272 			else {
273 				if (type == XML_ATTRIBUTE_NODE)
274 					if (gdome_xmlIsNsDecl ((xmlAttr *)n))
275 						gdome_xmlFreeSubtree (n);
276 			}
277 
278 #ifdef DEBUG_REFCNT
279       gdome_refdbg_delRef ((void *)self, GDOME_REFDBG_NODE);
280 #endif
281       g_free (self);
282     }
283   }
284 }
285 
286 /**
287  * gdome_xml_n_query_interface:
288  * @self:  Node Object ref
289  * @interface:  interface needed
290  * @exc:  Exception Object ref
291  *
292  * Returns: a reference to this object that implements the @interface needed,
293  *          or %NULL if the @interface is not supported by this Object.
294  */
295 gpointer
gdome_xml_n_query_interface(GdomeNode * self,const char * interface,GdomeException * exc)296 gdome_xml_n_query_interface (GdomeNode *self, const char *interface, GdomeException *exc)
297 {
298 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
299 
300   g_return_val_if_fail (priv != NULL, NULL);
301   g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
302   g_return_val_if_fail (interface != NULL, NULL);
303   g_return_val_if_fail (exc != NULL, NULL);
304 
305   if (!strcmp (interface, "Node") ||
306       !strcmp (interface, "EventTarget")) {
307     priv->refcnt++;
308     return self;
309   }
310   else
311     return NULL;
312 }
313 
314 /**************************************
315  ***** Attributes implementation ******
316  **************************************/
317 
318 /**
319  * gdome_xml_n_attributes:
320  * @self:  Node Object ref
321  * @exc:  Exception Object ref
322  *
323  * Returns: a NamedNodeMap containing the attributes of this node (if it is an
324  * Element) or %NULL otherwise.
325  */
326 GdomeNamedNodeMap *
gdome_xml_n_attributes(GdomeNode * self,GdomeException * exc)327 gdome_xml_n_attributes (GdomeNode *self, GdomeException *exc)
328 {
329 	g_return_val_if_fail (self != NULL, NULL);
330 	g_return_val_if_fail (GDOME_XML_IS_N (self), NULL);
331 	g_return_val_if_fail (exc != NULL, NULL);
332 
333 	if (GDOME_XML_IS_EL (self))
334 		return gdome_el_attributes((GdomeElement *)self, exc);
335 
336 	return NULL;
337 }
338 
339 /**
340  * gdome_xml_n_childNodes:
341  * @self:  Node Object ref
342  * @exc:  Exception Object ref
343  *
344  * Returns: a NodeList that contains all children of this node. If there are no
345  * children, this is a NodeList containing no nodes.  Note that attributes are
346  * not considered to be children of element nodes - use gdome_n_attributes to
347  * obtain the attributes.
348  */
349 GdomeNodeList *
gdome_xml_n_childNodes(GdomeNode * self,GdomeException * exc)350 gdome_xml_n_childNodes (GdomeNode *self, GdomeException *exc)
351 {
352 	g_return_val_if_fail (self != NULL, NULL);
353 	g_return_val_if_fail (GDOME_XML_IS_N (self), NULL);
354 	g_return_val_if_fail (exc != NULL, NULL);
355 
356   if (GDOME_XML_IS_NS(self))
357 		return NULL;
358 
359   return gdome_xml_nl_mkref ((GdomeNode*)self, NULL, NULL, GDOME_READONLY_NODE);
360 }
361 
362 /**
363  * gdome_xml_n_firstChild:
364  * @self:  Node Object ref
365  * @exc:  Exception Object ref
366  *
367  * Returns: the first child of this node. If there is no such node,
368  * this returns %NULL.
369  */
370 GdomeNode *
gdome_xml_n_firstChild(GdomeNode * self,GdomeException * exc)371 gdome_xml_n_firstChild (GdomeNode *self, GdomeException *exc)
372 {
373 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
374 
375 	g_return_val_if_fail (priv != NULL, NULL);
376 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
377 	g_return_val_if_fail (exc != NULL, NULL);
378 
379   switch (gdome_xmlGetType (priv->n)) {
380   case XML_DOCUMENT_TYPE_NODE:
381   case XML_DTD_NODE:
382   case XML_PI_NODE:
383   case XML_COMMENT_NODE:
384   case XML_TEXT_NODE:
385   case XML_CDATA_SECTION_NODE:
386   case XML_NOTATION_NODE:
387   case XML_NAMESPACE_DECL:
388     return NULL;
389   case XML_DOCUMENT_NODE:
390   case XML_DOCUMENT_FRAG_NODE:
391   case XML_ENTITY_REF_NODE:
392   case XML_ELEMENT_NODE:
393   case XML_ATTRIBUTE_NODE:
394   case XML_ENTITY_NODE:
395   case XML_ENTITY_DECL:
396     return gdome_xml_n_mkref (gdome_xmlGetFirstChild (priv->n));
397   default:
398     g_warning ("gdome_xml_n_firstChild: invalid node type");
399     return NULL;
400   }
401 }
402 
403 /**
404  * gdome_xml_n_lastChild:
405  * @self:  Node Object ref
406  * @exc:  Exception Object ref
407  *
408  * Returns: the last child of this node. If there is no such node,
409  * this returns %NULL.
410  */
411 GdomeNode *
gdome_xml_n_lastChild(GdomeNode * self,GdomeException * exc)412 gdome_xml_n_lastChild (GdomeNode *self, GdomeException *exc)
413 {
414 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
415 
416 	g_return_val_if_fail (priv != NULL, NULL);
417 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
418 	g_return_val_if_fail (exc != NULL, NULL);
419 
420   switch (gdome_xmlGetType (priv->n)) {
421   case XML_DOCUMENT_TYPE_NODE:
422   case XML_DTD_NODE:
423   case XML_PI_NODE:
424   case XML_COMMENT_NODE:
425   case XML_TEXT_NODE:
426   case XML_CDATA_SECTION_NODE:
427   case XML_NOTATION_NODE:
428   case XML_NAMESPACE_DECL:
429     return NULL;
430   case XML_DOCUMENT_NODE:
431   case XML_DOCUMENT_FRAG_NODE:
432   case XML_ENTITY_REF_NODE:
433   case XML_ELEMENT_NODE:
434   case XML_ATTRIBUTE_NODE:
435   case XML_ENTITY_NODE:
436   case XML_ENTITY_DECL:
437     return gdome_xml_n_mkref (gdome_xmlGetLastChild (priv->n));
438   default:
439     g_warning ("gdome_xml_n_lastChild: invalid node type");
440     return NULL;
441   }
442 }
443 
444 /**
445  * gdome_xml_n_localName:
446  * @self:  Node Objects ref
447  * @exc:  Exception Object ref
448  *
449  * Returns: the local part of the qualified name of this node.
450  * For nodes of any type other than %GDOME_ELEMENT_NODE and
451  * %GDOME_ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, this is
452  * always %NULL.
453  */
454 GdomeDOMString *
gdome_xml_n_localName(GdomeNode * self,GdomeException * exc)455 gdome_xml_n_localName (GdomeNode *self, GdomeException *exc)
456 {
457 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
458 
459 	g_return_val_if_fail (priv != NULL, NULL);
460 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
461 	g_return_val_if_fail (exc != NULL, NULL);
462 
463 	if((gdome_xmlGetType(priv->n) == XML_ELEMENT_NODE ||
464 			gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE) &&
465 		 gdome_xmlGetNs(priv->n) != NULL)
466 		return gdome_xml_str_mkref_dup ((gchar *)gdome_xmlGetName (priv->n));
467 	else
468 		return NULL;
469 }
470 
471 /**
472  * gdome_xml_n_namespaceURI:
473  * @self:  Node Objects ref
474  * @exc:  Exception Object ref
475  *
476  * Returns: the namespace URI of this node, or %NULL if it is unspecified.
477  * For nodes of any type other than %GDOME_ELEMENT_NODE and
478  * %GDOME_ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, this is
479  * always %NULL.
480  */
481 GdomeDOMString *
gdome_xml_n_namespaceURI(GdomeNode * self,GdomeException * exc)482 gdome_xml_n_namespaceURI (GdomeNode *self, GdomeException *exc)
483 {
484 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
485 
486 	g_return_val_if_fail (priv != NULL, NULL);
487 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
488 	g_return_val_if_fail (exc != NULL, NULL);
489 
490 	if((gdome_xmlGetType(priv->n) == XML_ELEMENT_NODE ||
491 			gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE ||
492 			gdome_xmlGetType(priv->n) == XML_NAMESPACE_DECL) &&
493 		 gdome_xmlGetNs(priv->n) != NULL)
494 		return gdome_xml_str_mkref_dup ((gchar *)gdome_xmlGetNsURI (priv->n));
495 	else
496 		return NULL;
497 }
498 
499 /**
500  * gdome_xml_n_nextSibling:
501  * @self:  Node Object ref
502  * @exc:  Exception Object ref
503  *
504  * Returns: the node immediately following this node. If there is no such
505  * node, this returns %NULL.
506  */
507 GdomeNode *
gdome_xml_n_nextSibling(GdomeNode * self,GdomeException * exc)508 gdome_xml_n_nextSibling (GdomeNode *self, GdomeException *exc)
509 {
510 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
511 
512 	g_return_val_if_fail (priv != NULL, NULL);
513 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
514 	g_return_val_if_fail (exc != NULL, NULL);
515 
516 	if(GDOME_XML_IS_A (priv) || GDOME_XML_IS_NS (priv))
517 		return NULL;
518 	else
519 		return gdome_xml_n_mkref (gdome_xmlGetNext (priv->n));
520 }
521 
522 /**
523  * gdome_xml_n_nodeName:
524  * @self:  Node Object ref
525  * @exc:  Exception Object ref
526  *
527  * Returns: the name of this node, depending on its type.
528  */
529 GdomeDOMString *
gdome_xml_n_nodeName(GdomeNode * self,GdomeException * exc)530 gdome_xml_n_nodeName (GdomeNode *self, GdomeException *exc)
531 {
532 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
533 	GdomeDOMString *ret = NULL;
534 
535 	g_return_val_if_fail (priv != NULL, NULL);
536 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
537 	g_return_val_if_fail (exc != NULL, NULL);
538 
539 	switch (gdome_xmlGetType (priv->n)) {
540 	case XML_ATTRIBUTE_NODE:
541 		ret = gdome_a_name((GdomeAttr *)self, exc);
542 		break;
543 	case XML_ELEMENT_NODE:
544 		ret = gdome_el_tagName((GdomeElement *)self, exc);
545 		break;
546   case XML_DOCUMENT_TYPE_NODE:
547   case XML_DTD_NODE:
548     ret = gdome_dt_name((GdomeDocumentType *)self, exc);
549     break;
550   case XML_PI_NODE:
551     ret = gdome_pi_target((GdomeProcessingInstruction *)self, exc);
552 		break;
553   case XML_ENTITY_NODE:
554   case XML_ENTITY_DECL: /*libxml use this instead of XML_ENTITY_NODE*/
555 	case XML_ENTITY_REF_NODE:
556 	case XML_NOTATION_NODE:
557 		ret = gdome_xml_str_mkref_dup((gchar *)gdome_xmlGetName (priv->n));
558 		break;
559 	case XML_CDATA_SECTION_NODE:
560 		ret = gdome_xml_str_mkref_dup("#cdata-section");
561 		break;
562 	case XML_COMMENT_NODE:
563 		ret = gdome_xml_str_mkref_dup("#comment");
564 		break;
565 	case XML_DOCUMENT_NODE:
566 		ret = gdome_xml_str_mkref_dup("#document");
567 		break;
568 	case XML_DOCUMENT_FRAG_NODE:
569 		ret = gdome_xml_str_mkref_dup("#document-fragment");
570 		break;
571 	case XML_TEXT_NODE:
572 		ret = gdome_xml_str_mkref_dup("#text");
573 		break;
574   case XML_NAMESPACE_DECL:
575     ret = gdome_xml_str_mkref_dup(gdome_xmlGetNsPrefix(priv->n));
576 		break;
577 	default:
578 		g_warning ("gdome_n_name: wrong Node Type.");
579 	}
580 
581 	return ret;
582 }
583 
584 /**
585  * gdome_xml_n_nodeType:
586  * @self:  Node Object ref
587  * @exc:  Exception Object ref
588  *
589  * Returns: an integer bigger than %0 representing the type of the underlying
590  * object or %0 on error.
591  */
592 unsigned short
gdome_xml_n_nodeType(GdomeNode * self,GdomeException * exc)593 gdome_xml_n_nodeType (GdomeNode *self, GdomeException *exc)
594 {
595   Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
596   xmlElementType type;
597 
598 	g_return_val_if_fail (priv != NULL, 0);
599 	g_return_val_if_fail (GDOME_XML_IS_N (priv), 0);
600 	g_return_val_if_fail (exc != NULL, 0);
601 
602   type = gdome_xmlGetType(priv->n);
603   if (type == XML_DTD_NODE)
604     return XML_DOCUMENT_TYPE_NODE;
605   else if (type == XML_ENTITY_DECL)
606     return XML_ENTITY_NODE;
607 	else if (type == XML_NAMESPACE_DECL)
608 		return GDOME_XPATH_NAMESPACE_NODE;
609   else
610     return type;
611 }
612 
613 /**
614  * gdome_xml_n_nodeValue:
615  * @self:  Node Object ref
616  * @exc:  Exception Object ref
617  *
618  * Returns: the value of this node, depending on its type.
619  */
620 GdomeDOMString *
gdome_xml_n_nodeValue(GdomeNode * self,GdomeException * exc)621 gdome_xml_n_nodeValue (GdomeNode *self, GdomeException *exc)
622 {
623 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
624 	GdomeDOMString *ret = NULL;
625 
626 	g_return_val_if_fail (priv != NULL, 0);
627 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
628 	g_return_val_if_fail (exc != NULL, 0);
629 
630 	switch (gdome_xmlGetType (priv->n)) {
631 	case XML_ATTRIBUTE_NODE:
632 		ret = gdome_a_value ((GdomeAttr *)self, exc);
633 		break;
634   case XML_PI_NODE:
635     ret = gdome_pi_data ((GdomeProcessingInstruction *)self, exc);
636     break;
637 	case XML_CDATA_SECTION_NODE:
638 	case XML_COMMENT_NODE:
639 	case XML_TEXT_NODE:
640 		ret = gdome_xml_str_mkref_own (xmlNodeGetContent (priv->n));
641 		break;
642 	case XML_ELEMENT_NODE:
643 	case XML_ENTITY_NODE:
644 	case XML_ENTITY_REF_NODE:
645 	case XML_DOCUMENT_NODE:
646 	case XML_DOCUMENT_TYPE_NODE:
647 	case XML_DOCUMENT_FRAG_NODE:
648   case XML_NOTATION_NODE:
649   case XML_DTD_NODE:
650   case XML_ENTITY_DECL:
651 	case XML_NAMESPACE_DECL:
652 		break;
653 	default:
654 		g_warning ("could not recognize the Node Type.");
655 	}
656 
657 	return ret;
658 }
659 
660 /**
661  * gdome_xml_n_ownerDocument:
662  * @self:  Node Objects ref
663  * @exc:  Exception Object ref
664  *
665  * Returns: the documment object associated with this node. This is also the
666  * Document object used to create new nodes. When this node is a Document or a
667  * DocumentType which is not used with any Document yet, this is %NULL.
668  */
669 GdomeDocument *
gdome_xml_n_ownerDocument(GdomeNode * self,GdomeException * exc)670 gdome_xml_n_ownerDocument (GdomeNode *self, GdomeException *exc)
671 {
672 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
673 
674 	g_return_val_if_fail (priv != NULL, NULL);
675 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
676 	g_return_val_if_fail (exc != NULL, NULL);
677 
678   if (gdome_xmlGetType (priv->n) == XML_DOCUMENT_NODE)
679     return NULL;
680   else
681     return (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)gdome_xmlGetOwner (priv->n));
682 }
683 
684 /**
685  * gdome_xml_n_parentNode:
686  * @self: Node Object ref
687  * @exc: Exception Object ref
688  *
689  * Returns: the parent of this node. All nodes, except Attr,
690  * Document, DocumentFragment, Entity, and Notation may have a parent. However,
691  * if a node has just been created and not yet added to the tree, or if it has
692  * been removed from the tree, this is %NULL.
693  */
694 GdomeNode *
gdome_xml_n_parentNode(GdomeNode * self,GdomeException * exc)695 gdome_xml_n_parentNode (GdomeNode *self, GdomeException *exc)
696 {
697 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
698 
699 	g_return_val_if_fail (priv != NULL, NULL);
700 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
701 	g_return_val_if_fail (exc != NULL, NULL);
702 
703 	if(GDOME_XML_IS_TREE_N (priv))
704 		return gdome_xml_n_mkref (gdome_xmlGetParent (priv->n));
705 	else
706 		return NULL;
707 }
708 
709 /**
710  * gdome_xml_n_prefix:
711  * @self:  Node Objects ref
712  * @exc:  Exception Object ref
713  *
714  * Returns: the namespace prefix of this node, or %NULL if it is unspecified.
715  * For nodes of any type other than %GDOME_ELEMENT_NODE and
716  * %GDOME_ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, this is
717  * always %NULL.
718  */
719 GdomeDOMString *
gdome_xml_n_prefix(GdomeNode * self,GdomeException * exc)720 gdome_xml_n_prefix (GdomeNode *self, GdomeException *exc)
721 {
722 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
723 
724 	g_return_val_if_fail (priv != NULL, 0);
725 	g_return_val_if_fail (GDOME_XML_IS_N (priv), 0);
726 	g_return_val_if_fail (exc != NULL, 0);
727 
728 	if((gdome_xmlGetType(priv->n) == XML_ELEMENT_NODE ||
729 			gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE ||
730 			gdome_xmlGetType(priv->n) == XML_NAMESPACE_DECL) &&
731 		 gdome_xmlGetNs(priv->n) != NULL)
732 		return gdome_xml_str_mkref_dup ((gchar *)gdome_xmlGetNsPrefix (priv->n));
733 	else
734 		return NULL;
735 }
736 
737 /**
738  * gdome_xml_n_previousSibling:
739  * @self:  Node Object ref
740  * @exc:  Exception Object ref
741  *
742  * Returns: the node immediately preceding this node. If there is no such
743  * node, this returns %NULL.
744  */
745 GdomeNode *
gdome_xml_n_previousSibling(GdomeNode * self,GdomeException * exc)746 gdome_xml_n_previousSibling (GdomeNode *self, GdomeException *exc)
747 {
748 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
749 
750 	g_return_val_if_fail (priv != NULL, NULL);
751 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
752 	g_return_val_if_fail (exc != NULL, NULL);
753 
754 	if(GDOME_XML_IS_A (priv) || GDOME_XML_IS_NS (priv))
755 		return NULL;
756 	else
757 		return gdome_xml_n_mkref (gdome_xmlGetPrev (priv->n));
758 }
759 
760 /**
761  * gdome_xml_n_set_nodeValue:
762  * @self:  Node Object ref
763  * @nodeValue:  The new value for this node.
764  * @exc:  Exception Object ref
765  *
766  * Sets The value of this node, depending on its type.
767  *
768  * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
769  */
770 void
gdome_xml_n_set_nodeValue(GdomeNode * self,GdomeDOMString * nodeValue,GdomeException * exc)771 gdome_xml_n_set_nodeValue (GdomeNode *self, GdomeDOMString *nodeValue, GdomeException *exc)
772 {
773 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
774 
775 	g_return_if_fail (priv != NULL);
776 	g_return_if_fail (GDOME_XML_IS_N (priv));
777 	g_return_if_fail (nodeValue != NULL);
778   g_return_if_fail (exc != NULL);
779 
780   if (GDOME_ISREADONLY (priv)) {
781     *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
782     return;
783   }
784 
785 	switch (gdome_xmlGetType(priv->n)) {
786 	case XML_ATTRIBUTE_NODE:
787 		gdome_xml_a_set_value ((GdomeAttr *)self, nodeValue, exc);
788 		break;
789   case XML_PI_NODE:
790     gdome_xml_pi_set_data ((GdomeProcessingInstruction *)self, nodeValue, exc);
791     break;
792 	case XML_CDATA_SECTION_NODE:
793 	case XML_COMMENT_NODE:
794   case XML_TEXT_NODE:
795     gdome_xml_cd_set_data ((GdomeCharacterData *)self, nodeValue, exc);
796 		break;
797 	case XML_ELEMENT_NODE:
798 	case XML_ENTITY_NODE:
799 	case XML_ENTITY_REF_NODE:
800 	case XML_DOCUMENT_NODE:
801 	case XML_DOCUMENT_TYPE_NODE:
802 	case XML_DOCUMENT_FRAG_NODE:
803   case XML_NOTATION_NODE:
804   case XML_DTD_NODE:
805   case XML_NAMESPACE_DECL:
806 		break;
807 	default:
808 		g_warning ("could not recognize the Node Type.");
809   }
810 }
811 
812 /**
813  * gdome_xml_n_set_prefix:
814  * @self:  Node Object ref
815  * @prefix:  The new prefix for this node.
816  * @exc:  Exception Object ref
817  *
818  * Sets a new nemaspace prefix for this node.
819  *
820  * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
821  * %GDOME_NAMESPACE_ERR: Raised if the specified @prefix is malformed per the
822  * Namespaces in XML specification, if the namespaceURI of this node is %NULL,
823  * if the specified prefix is "xml" and the namespaceURI of this node is
824  * different from "http://www.w3.org/XML/1998/namespace", if this node is an
825  * attribute and the specified prefix is "xmlns" and the namespaceURI of this
826  * node is different from "http://www.w3.org/2000/xmlns/", or if this node is
827  * an attribute and the qualifiedName of this node is "xmlns".
828  */
829 void
gdome_xml_n_set_prefix(GdomeNode * self,GdomeDOMString * prefix,GdomeException * exc)830 gdome_xml_n_set_prefix (GdomeNode *self, GdomeDOMString *prefix, GdomeException *exc)
831 {
832 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
833 	xmlNs *ns;
834 
835 	g_return_if_fail (priv != NULL);
836 	g_return_if_fail (GDOME_XML_IS_N (priv));
837 	g_return_if_fail (prefix != NULL);
838 	g_return_if_fail (exc != NULL);
839 
840   if (GDOME_ISREADONLY (priv)) {
841     *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
842     return;
843   }
844 
845   if((gdome_xmlGetType(priv->n) == XML_ELEMENT_NODE ||
846 			gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE) &&
847 		 gdome_xmlGetNs(priv->n) != NULL &&
848      !xmlStrEqual(gdome_xmlGetNsPrefix (priv->n), (xmlChar *)prefix->str)) {
849 
850 		/* tests for NAMESPACE_ERR */
851     gchar *nsURI = (gchar *)gdome_xmlGetNsURI (priv->n);
852 		if (nsURI == NULL ||
853 				(!strcmp (prefix->str, "xml") &&
854 				 strcmp (nsURI, "http://www.w3.org/XML/1998/namespace")) ||
855 				(gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE &&
856 				 !strcmp (prefix->str, "xmlns") &&
857 				 strcmp (nsURI, GDOME_XMLNS_NAMESPACE)) ||
858 				(gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE &&
859 				 !strcmp (gdome_xmlGetName(priv->n), "xmlns"))) {
860 			*exc = GDOME_NAMESPACE_ERR;
861 			return;
862 		}
863 		ns = gdome_xmlNewNs (priv->n->doc, gdome_xmlGetNsURI (priv->n), (xmlChar *)prefix->str);
864 		gdome_xmlSetNs(priv->n, ns);
865 	}
866 }
867 
868 /**************************************
869  ******* Methods implementation *******
870  **************************************/
871 
872 /**
873  * gdome_xml_n_appendChild:
874  * @self:  Node Object ref
875  * @newChild:  The node to add
876  * @exc:  Exception Object ref
877  *
878  * Adds the node @newChild to the end of the list of children of this node.
879  * If the @newChild is already in the tree, it is first removed. If it is a
880  * DocumentFragment node, the entire contents of the document fragment are
881  * moved into the child list of this node
882  *
883  * %GDOME_HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
884  * allow children of the type of the @newChild node, or if the node to append is
885  * one of this node's ancestors or this node itself.
886  * %GDOME_WRONG_DOCUMENT_ERR: Raised if @newChild was created from a different
887  * document than the one that created this node.
888  * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
889  * Returns: the node added.
890  */
891 GdomeNode *
gdome_xml_n_appendChild(GdomeNode * self,GdomeNode * newChild,GdomeException * exc)892 gdome_xml_n_appendChild (GdomeNode *self, GdomeNode *newChild, GdomeException *exc)
893 {
894 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
895 	Gdome_xml_Node *new_priv = (Gdome_xml_Node *)newChild;
896 	GdomeMutationEvent *mev;
897 	xmlNode *ret;
898 
899 	g_return_val_if_fail (priv != NULL, NULL);
900 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
901 	g_return_val_if_fail (new_priv != NULL, NULL);
902 	g_return_val_if_fail (GDOME_XML_IS_N (new_priv), NULL);
903 	g_return_val_if_fail (exc != NULL, NULL);
904 
905 	if (!gdome_xml_n_canAppend (self, newChild, exc)) {
906 		*exc = GDOME_HIERARCHY_REQUEST_ERR;
907 		return NULL;
908 	}
909 
910 	if (gdome_xmlGetOwner(new_priv->n) != gdome_xmlGetOwner(priv->n)) {
911 		*exc = GDOME_WRONG_DOCUMENT_ERR;
912 		return NULL;
913 	}
914 
915 	if (GDOME_ISREADONLY (priv)) {
916 		*exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
917 		return NULL;
918 	}
919 
920 	/* If the newChild is already in the tree, it is first removed. */
921 	if (gdome_xmlGetParent(new_priv->n) != NULL)
922 		gdome_xmlUnlinkChild(gdome_xmlGetParent(new_priv->n), new_priv->n);
923 
924 	ret = gdome_xmlAppendChild(priv->n, new_priv->n);
925 
926 	/* Delete children list for DocumentFragment Node */
927 	if (gdome_xmlGetType (new_priv->n) == XML_DOCUMENT_FRAG_NODE) {
928 		gdome_xmlSetFirstChild(new_priv->n, NULL);
929 		gdome_xmlSetLastChild(new_priv->n, NULL);
930 	}
931 
932 	if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_INSERTED_EVENT_TYPE)) {
933 		/* Fire DOMNodeInserted */
934 		mev = gdome_evt_mevnt_mkref ();
935 		gdome_xml_n_ref (self, exc);
936 		gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_INSERTED_EVENT_TYPE,
937 																						 TRUE, FALSE, self,
938 																						 NULL, NULL, NULL, 0, exc);
939 		gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
940 		gdome_xml_n_unref (self, exc);
941 		gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
942 	}
943 
944 	if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_INSERTED_INTO_DOCUMENT_EVENT_TYPE)) {
945 		/* Fire DOMNodeInsertedIntoDocument */
946 		mev = gdome_evt_mevnt_mkref ();
947 		gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_INSERTED_INTO_DOCUMENT_EVENT_TYPE,
948 																						 FALSE, FALSE, NULL,
949 																						 NULL, NULL, NULL, 0, exc);
950 		gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
951 		gdome_xml_n_subTreeDispatchEvent (newChild, (GdomeEvent *)mev, exc);
952 		gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
953 	}
954 
955 	if (gdome_xml_n_eventEnabledByCode (self, DOM_SUBTREE_MODIFIED_EVENT_TYPE)) {
956 		/* Fire DOMSubtreeModified */
957 		mev = gdome_evt_mevnt_mkref ();
958 		gdome_evt_mevnt_initMutationEventByCode (mev, DOM_SUBTREE_MODIFIED_EVENT_TYPE,
959 																						 TRUE, FALSE, NULL,
960 																						 NULL, NULL, NULL, 0, exc);
961 		gdome_xml_n_dispatchEvent (self, (GdomeEvent *)mev, exc);
962 		gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
963 	}
964 
965 	return gdome_xml_n_mkref (ret);
966 }
967 
968 /**
969  * gdome_xml_n_cloneNode:
970  * @self:  Node Object ref
971  * @deep:  If true, recursively clone the subtree under the specified node;
972  *         if false, clone only the node itself (and its attributes, if it is
973  *         an Element).
974  * @exc:  Exception Object ref
975  *
976  * Makes a duplicate of this node, i.e., serves as a generic copy
977  * constructor for nodes. The duplicate node has no parent; (parentNode is
978  * %NULL).
979  * %GDOME_DOCUMENT_TYPE_NODE, %GDOME_NOTATION_NODE and %GDOME_ENTITY_NODE
980  * nodes are not supported.
981  *
982  * %GDOME_NOT_SUPPORTED_ERR: Raised if the type of node being cloned is not
983  * supported.
984  * Returns: the duplicate node.
985  */
986 GdomeNode *
gdome_xml_n_cloneNode(GdomeNode * self,GdomeBoolean deep,GdomeException * exc)987 gdome_xml_n_cloneNode (GdomeNode *self, GdomeBoolean deep, GdomeException *exc)
988 {
989 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
990   xmlNode *n = NULL;
991   xmlElementType type;
992 
993 	g_return_val_if_fail (priv != NULL, NULL);
994 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
995 	g_return_val_if_fail (exc != NULL, NULL);
996 
997   type = gdome_xmlGetType (priv->n);
998   if (type == XML_ENTITY_NODE ||
999       type == XML_ENTITY_DECL ||
1000 			type == XML_NOTATION_NODE ||
1001 			type == XML_DOCUMENT_TYPE_NODE ||
1002 			type == XML_DTD_NODE ||
1003 			type == XML_NAMESPACE_DECL )
1004 		*exc = GDOME_NOT_SUPPORTED_ERR;
1005 	else if (type == XML_DOCUMENT_NODE)
1006 		n = (xmlNode *)xmlCopyDoc ((xmlDoc *)priv->n, deep);
1007 	else if (type == XML_ATTRIBUTE_NODE) {
1008 		n = (xmlNode *)xmlCopyProp (NULL, (xmlAttr *)priv->n);
1009 		if (gdome_xmlGetOwner (n) == NULL)
1010 			gdome_xmlSetOwner (n , gdome_xmlGetOwner (priv->n));
1011 	}
1012 	else
1013 		n = xmlDocCopyNode (priv->n, gdome_xmlGetOwner(priv->n), deep);
1014 
1015 	if (*exc)
1016 		return NULL;
1017   else
1018 		return gdome_xml_n_mkref (n);
1019 }
1020 
1021 /**
1022  * gdome_xml_n_hasAttributes:
1023  * @self:  Node Object ref
1024  * @exc:  Exception Object ref
1025  *
1026  * Returns: %TRUE if this node has any attributes, %FALSE otherwise.
1027  */
1028 GdomeBoolean
gdome_xml_n_hasAttributes(GdomeNode * self,GdomeException * exc)1029 gdome_xml_n_hasAttributes (GdomeNode *self, GdomeException *exc) {
1030 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1031 
1032 	g_return_val_if_fail (priv != NULL, 0);
1033 	g_return_val_if_fail (GDOME_XML_IS_N (priv), 0);
1034 	g_return_val_if_fail (exc != NULL, 0);
1035 
1036 	if (GDOME_XML_IS_EL (priv))
1037 		return (gdome_xmlGetAttrList (priv->n) != NULL);
1038 	else
1039     return FALSE;
1040 }
1041 
1042 /**
1043  * gdome_xml_n_hasChildNodes:
1044  * @self:  Node Object ref
1045  * @exc:  Exception Object ref
1046  *
1047  * Returns: %TRUE if this node has any children, %FALSE otherwise.
1048  */
1049 GdomeBoolean
gdome_xml_n_hasChildNodes(GdomeNode * self,GdomeException * exc)1050 gdome_xml_n_hasChildNodes (GdomeNode *self, GdomeException *exc) {
1051 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1052 
1053 	g_return_val_if_fail (priv != NULL, 0);
1054 	g_return_val_if_fail (GDOME_XML_IS_N (priv), 0);
1055   g_return_val_if_fail (exc != NULL, 0);
1056 
1057   switch (gdome_xmlGetType (priv->n)) {
1058   case XML_DOCUMENT_TYPE_NODE:
1059   case XML_DTD_NODE:
1060   case XML_PI_NODE:
1061   case XML_COMMENT_NODE:
1062   case XML_TEXT_NODE:
1063   case XML_CDATA_SECTION_NODE:
1064   case XML_NOTATION_NODE:
1065 	case XML_NAMESPACE_DECL:
1066     return FALSE;
1067   case XML_DOCUMENT_NODE:
1068   case XML_DOCUMENT_FRAG_NODE:
1069   case XML_ENTITY_REF_NODE:
1070   case XML_ELEMENT_NODE:
1071   case XML_ATTRIBUTE_NODE:
1072   case XML_ENTITY_NODE:
1073   case XML_ENTITY_DECL:
1074 		return (gdome_xmlGetFirstChild (priv->n) != NULL);
1075   default:
1076     g_warning ("gdome_xml_n_hasChildNodes: invalid node type");
1077     return FALSE;
1078   }
1079 }
1080 
1081 /**
1082  * gdome_xml_n_insertBefore:
1083  * @self:  Node Object ref
1084  * @newChild:  The new node to put in the child list
1085  * @refChild:  the reference node, i.e., the node before which the new node
1086  *             must be inserted.
1087  * @exc:  Exception Object ref
1088  *
1089  * Inserts the node @newChild before the existing child node @refChild. If
1090  * @refChild is %NULL, insert @newChild at the end of the list of children.
1091  * If @newChild is a DocumentFragment node, all of its children are inserted,
1092  * in the same order, before @refChild. If the @newChild is already in the
1093  * tree, it is first removed.
1094  *
1095  * %GDOME_HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
1096  * allow children of the type of the @newChild node, or if the node to insert is
1097  * one of this node's ancestors or this node itself.
1098  * %GDOME_WRONG_DOCUMENT_ERR: Raised if @newChild was created from a different
1099  * document than the one that created this node.
1100  * %GDOME_NOT_FOUND_ERR: Raised if @refChild is not a child of this node.
1101  * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1102  * Returns: the node being inserted.
1103  */
1104 GdomeNode *
gdome_xml_n_insertBefore(GdomeNode * self,GdomeNode * newChild,GdomeNode * refChild,GdomeException * exc)1105 gdome_xml_n_insertBefore (GdomeNode *self, GdomeNode *newChild, GdomeNode *refChild, GdomeException *exc)
1106 {
1107 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1108 	Gdome_xml_Node *new_priv = (Gdome_xml_Node *)newChild;
1109 	Gdome_xml_Node *ref_priv = (Gdome_xml_Node *)refChild;
1110 	GdomeMutationEvent *mev;
1111 	xmlNode *ret = NULL;
1112 
1113 	g_return_val_if_fail (priv != NULL, NULL);
1114 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
1115 	g_return_val_if_fail (new_priv != NULL, NULL);
1116 	g_return_val_if_fail (GDOME_XML_IS_N (new_priv), NULL);
1117 	g_return_val_if_fail (exc != NULL, NULL);
1118 
1119 	if (!gdome_xml_n_canAppend (self, newChild, exc)) {
1120 		*exc = GDOME_HIERARCHY_REQUEST_ERR;
1121 		return NULL;
1122 	}
1123 
1124 	if (gdome_xmlGetOwner(new_priv->n) != gdome_xmlGetOwner(priv->n)) {
1125 		*exc = GDOME_WRONG_DOCUMENT_ERR;
1126 		return NULL;
1127 	}
1128 
1129   if (GDOME_ISREADONLY (priv)) {
1130     *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
1131     return NULL;
1132   }
1133 
1134   /* If refChild is null, insert newChild at the end of the list of children.*/
1135 	if(ref_priv == NULL)
1136 		return gdome_xml_n_appendChild (self, newChild, exc);
1137 	else
1138 		g_return_val_if_fail (GDOME_XML_IS_N (ref_priv), NULL);
1139 
1140 	/* If the newChild is already in the tree, it is first removed. */
1141   if (gdome_xmlGetParent(new_priv->n) != NULL) {
1142 		if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_REMOVED_EVENT_TYPE)) {
1143 			/* Fire DOMNodeRemoved */
1144 			mev = gdome_evt_mevnt_mkref ();
1145 			gdome_xml_n_ref (self, exc);
1146 			gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_REMOVED_EVENT_TYPE,
1147 																							 TRUE, FALSE, self,
1148 																							 NULL, NULL, NULL, 0, exc);
1149 			gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
1150 			gdome_xml_n_unref (self, exc);
1151 			gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1152 		}
1153 
1154 		if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_REMOVED_FROM_DOCUMENT_EVENT_TYPE)) {
1155 			/* Fire DOMNodeRemovedFromDocument */
1156 			mev = gdome_evt_mevnt_mkref ();
1157 			gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_REMOVED_FROM_DOCUMENT_EVENT_TYPE,
1158 																							 FALSE, FALSE, NULL,
1159 																							 NULL, NULL, NULL, 0, exc);
1160 			gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
1161 			gdome_xml_n_subTreeDispatchEvent (newChild, (GdomeEvent *)mev, exc);
1162 			gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1163 		}
1164 
1165     gdome_xmlUnlinkChild(gdome_xmlGetParent(new_priv->n), new_priv->n);
1166   }
1167 
1168 	if ((ret = gdome_xmlInsertBeforeChild(priv->n, new_priv->n, ref_priv->n)) == NULL) {
1169 		*exc = GDOME_NOT_FOUND_ERR;
1170 		return NULL;
1171   }
1172 
1173   /* Unlink children list for DocumentFragment Node */
1174   if (gdome_xmlGetType (new_priv->n) == XML_DOCUMENT_FRAG_NODE) {
1175     gdome_xmlSetFirstChild(new_priv->n, NULL);
1176     gdome_xmlSetLastChild(new_priv->n, NULL);
1177   }
1178 
1179 	if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_INSERTED_EVENT_TYPE)) {
1180 		/* Fire DOMNodeInserted */
1181 		mev = gdome_evt_mevnt_mkref ();
1182 		gdome_xml_n_ref (self, exc);
1183 		gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_INSERTED_EVENT_TYPE,
1184 																						 TRUE, FALSE, self,
1185 																						 NULL, NULL, NULL, 0, exc);
1186 		gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
1187 		gdome_xml_n_unref (self, exc);
1188 		gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1189 	}
1190 
1191 	if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_INSERTED_INTO_DOCUMENT_EVENT_TYPE)) {
1192 		/* Fire DOMNodeInsertedIntoDocument */
1193 		mev = gdome_evt_mevnt_mkref ();
1194 		gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_INSERTED_INTO_DOCUMENT_EVENT_TYPE,
1195 																						 FALSE, FALSE, NULL,
1196 																						 NULL, NULL, NULL, 0, exc);
1197 		gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
1198 		gdome_xml_n_subTreeDispatchEvent (newChild, (GdomeEvent *)mev, exc);
1199 		gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1200 	}
1201 
1202 	if (gdome_xml_n_eventEnabledByCode (self, DOM_SUBTREE_MODIFIED_EVENT_TYPE)) {
1203 		/* Fire DOMSubtreeModified */
1204 		mev = gdome_evt_mevnt_mkref ();
1205 		gdome_evt_mevnt_initMutationEventByCode (mev, DOM_SUBTREE_MODIFIED_EVENT_TYPE,
1206 																						 TRUE, FALSE, NULL,
1207 																						 NULL, NULL, NULL, 0, exc);
1208 		gdome_xml_n_dispatchEvent (self, (GdomeEvent *)mev, exc);
1209 		gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1210 	}
1211 
1212 	return gdome_xml_n_mkref (ret);
1213 }
1214 
1215 /**
1216  * gdome_xml_n_isSupported:
1217  * @self:  Node Object ref
1218  * @feature:  The name of the feature to test.
1219  * @version:  This is the version number of the feature to test. In Level 2,
1220  *            version 1, this is the string "2.0". If the version is not
1221  *            specified, supporting any version of the feature will cause the
1222  *            method to return %TRUE.
1223  * @exc:  Exception Object ref
1224  *
1225  * Tests whether the DOM implementation implements a specific feature and that
1226  * feature is supported by this node.
1227  * Returns: %TRUE if the specified feature is supported on this node, %FALSE
1228  * otherwise.
1229  */
1230 GdomeBoolean
gdome_xml_n_isSupported(GdomeNode * self,GdomeDOMString * feature,GdomeDOMString * version,GdomeException * exc)1231 gdome_xml_n_isSupported (GdomeNode *self, GdomeDOMString *feature, GdomeDOMString *version, GdomeException *exc)
1232 {
1233 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1234 	GdomeBoolean ret;
1235   GdomeDOMImplementation *domimpl;
1236 
1237 	g_return_val_if_fail (priv != NULL, FALSE);
1238 	g_return_val_if_fail (GDOME_XML_IS_N (priv), FALSE);
1239 	g_return_val_if_fail (feature != NULL, FALSE);
1240 	g_return_val_if_fail (exc != NULL, FALSE);
1241 
1242 	if (version == NULL)
1243 		return TRUE;
1244 
1245 	domimpl = gdome_xml_di_mkref();
1246 	ret = gdome_xml_di_hasFeature (domimpl, feature, version, exc);
1247 	gdome_xml_di_unref (domimpl, exc);
1248 
1249   return ret;
1250 }
1251 
1252 /**
1253  * gdome_xml_n_normalize:
1254  * @self:  Node Object ref
1255  * @exc:  Exception Object ref
1256  *
1257  * Puts all Text nodes in the full depth of the sub-tree underneath this Node,
1258  * including attribute nodes, into a "normal" form where only structure (e.g.,
1259  * elements, comments, processing instructions, CDATA sections, and entity
1260  * references) separates Text nodes, i.e., there are neither adjacent Text
1261  * nodes nor empty Text nodes.
1262  */
1263 void
gdome_xml_n_normalize(GdomeNode * self,GdomeException * exc)1264 gdome_xml_n_normalize (GdomeNode *self, GdomeException *exc)
1265 {
1266 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1267 	GdomeNode *child = NULL, *new_child = NULL;
1268 	GdomeNode *next = NULL, *new_next = NULL;
1269 	GdomeDOMString *str = NULL;
1270 	GdomeNode *result = NULL;
1271 
1272 	g_return_if_fail (priv != NULL);
1273 	g_return_if_fail (GDOME_XML_IS_N (priv));
1274 	g_return_if_fail (exc != NULL);
1275 
1276 	/* this is a generic implementation, not optimized for speed */
1277 	child = gdome_n_firstChild (self, exc);
1278 	while (child != NULL) {
1279 		unsigned short type;
1280 
1281 		type = gdome_n_nodeType (child, exc);
1282 		if (type == GDOME_TEXT_NODE) {
1283 			next = gdome_n_nextSibling (child, exc);
1284 			while (next != NULL) {
1285 				if (gdome_n_nodeType (next, exc) != GDOME_TEXT_NODE) {
1286 					gdome_n_unref (next, exc);
1287 					break;
1288 				}
1289 				str = gdome_cd_data ((GdomeCharacterData *)next, exc);
1290 				gdome_cd_appendData ((GdomeCharacterData *)child, str, exc);
1291 				gdome_str_unref (str);
1292 				new_next = gdome_n_nextSibling (next, exc);
1293 				result = gdome_n_removeChild (self, next, exc);
1294 				gdome_n_unref (result, exc);
1295 				gdome_n_unref (next, exc);
1296 				next = new_next;
1297 			}
1298 		} else if (type == GDOME_ELEMENT_NODE) {
1299 			GdomeNamedNodeMap *nnm;
1300 			gulong i, n;
1301 
1302 			gdome_n_normalize (child, exc);
1303 			nnm = gdome_n_attributes (child, exc);
1304 			n = gdome_nnm_length (nnm, exc);
1305 			for (i = 0; i < n; i++) {
1306 				GdomeNode *attr;
1307 
1308 				attr = gdome_nnm_item (nnm, i, exc);
1309 				gdome_n_normalize (attr, exc);
1310 				gdome_n_unref (attr, exc);
1311 			}
1312 			gdome_nnm_unref (nnm, exc);
1313 		}
1314 		new_child = gdome_n_nextSibling (child, exc);
1315 		gdome_n_unref (child, exc);
1316 		child = new_child;
1317 	}
1318 }
1319 
1320 /**
1321  * gdome_xml_n_removeChild:
1322  * @self:  Node Object ref
1323  * @oldChild:  The node being removed
1324  * @exc:  Exception Object ref
1325  *
1326  * Removes the child node indicated by @oldChild from the list of children, and
1327  * returns it.
1328  *
1329  * %GDOME_NOT_FOUND_ERR: Raised if @oldChild is not a child of this node.
1330  * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1331  * Returns: the node removed.
1332  */
1333 GdomeNode *
gdome_xml_n_removeChild(GdomeNode * self,GdomeNode * oldChild,GdomeException * exc)1334 gdome_xml_n_removeChild (GdomeNode *self, GdomeNode *oldChild, GdomeException *exc)
1335 {
1336 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1337 	Gdome_xml_Node *old_priv = (Gdome_xml_Node *)oldChild;
1338 	GdomeMutationEvent *mev;
1339 	xmlNode *ret;
1340 
1341 	g_return_val_if_fail (priv != NULL, NULL);
1342 	g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
1343 	g_return_val_if_fail (old_priv != NULL, NULL);
1344 	g_return_val_if_fail (GDOME_XML_IS_TREE_N (old_priv), NULL);
1345 	g_return_val_if_fail (exc != NULL, NULL);
1346 
1347   if (GDOME_ISREADONLY (priv)) {
1348     *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
1349     return NULL;
1350   }
1351 
1352 	if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_REMOVED_EVENT_TYPE)) {
1353 		/* Fire DOMNodeRemoved */
1354 		mev = gdome_evt_mevnt_mkref ();
1355 		gdome_xml_n_ref (self, exc);
1356 		gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_REMOVED_EVENT_TYPE,
1357 																						 TRUE, FALSE, self,
1358 																						 NULL, NULL, NULL, 0, exc);
1359 		gdome_xml_n_dispatchEvent (oldChild, (GdomeEvent *)mev, exc);
1360 		gdome_xml_n_unref (self, exc);
1361 		gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1362 	}
1363 
1364 	if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_REMOVED_FROM_DOCUMENT_EVENT_TYPE)) {
1365 		/* Fire DOMNodeRemovedFromDocument */
1366 		mev = gdome_evt_mevnt_mkref ();
1367 		gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_REMOVED_FROM_DOCUMENT_EVENT_TYPE,
1368 																						 FALSE, FALSE, NULL,
1369 																						 NULL, NULL, NULL, 0, exc);
1370 		gdome_xml_n_dispatchEvent (oldChild, (GdomeEvent *)mev, exc);
1371 		gdome_xml_n_subTreeDispatchEvent (oldChild, (GdomeEvent *)mev, exc);
1372 		gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1373 	}
1374 
1375 	if (gdome_xml_n_eventEnabledByCode (self, DOM_SUBTREE_MODIFIED_EVENT_TYPE)) {
1376 		/* Fire DOMSubtreeModified */
1377 		mev = gdome_evt_mevnt_mkref ();
1378 		gdome_evt_mevnt_initMutationEventByCode (mev, DOM_SUBTREE_MODIFIED_EVENT_TYPE,
1379 																						 TRUE, FALSE, NULL,
1380 																						 NULL, NULL, NULL, 0, exc);
1381 		gdome_xml_n_dispatchEvent (self, (GdomeEvent *)mev, exc);
1382 		gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1383 	}
1384 
1385   if ((ret = gdome_xmlUnlinkChild(priv->n, old_priv->n)) == NULL) {
1386 		*exc = GDOME_NOT_FOUND_ERR;
1387 		return NULL;
1388   }
1389 
1390   return gdome_xml_n_mkref (ret);
1391 }
1392 
1393 /**
1394  * gdome_xml_n_replaceChild:
1395  * @self:  Node Object ref
1396  * @newChild:  The new node to put in the child list
1397  * @oldChild:  The node being replaced in the list
1398  * @exc:  Exception Object ref
1399  *
1400  * Replaces the child node @oldChild with @newChild in the list of children,
1401  * and returns the @oldChild node. If @newChild is a DocumentFragment object,
1402  * @oldChild is replaced by all of the DocumentFragment children, which are
1403  * inserted in the same order. If the @newChild is already in the tree, it is
1404  * first removed.
1405  *
1406  * %GDOME_HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does
1407  * not allow children of the type of the @newChild node, or if the node to put
1408  * in is one of this node's ancestors or this node itself.
1409  * %GDOME_WRONG_DOCUMENT_ERR: Raised if @newChild was created from a different
1410  * document than the one that created this node.
1411  * %GDOME_NOT_FOUND_ERR: Raised if @oldChild is not a child of this node.
1412  * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1413  * Returns: the node replaced.
1414  */
1415 GdomeNode *
gdome_xml_n_replaceChild(GdomeNode * self,GdomeNode * newChild,GdomeNode * oldChild,GdomeException * exc)1416 gdome_xml_n_replaceChild (GdomeNode *self, GdomeNode *newChild, GdomeNode *oldChild, GdomeException *exc)
1417 {
1418 	GdomeNode *ret = NULL;
1419 	GdomeNode *refChild = NULL;
1420 
1421 	g_return_val_if_fail (self != NULL, NULL);
1422 	g_return_val_if_fail (GDOME_XML_IS_N (self), NULL);
1423 	g_return_val_if_fail (newChild != NULL, NULL);
1424 	g_return_val_if_fail (GDOME_XML_IS_N (newChild), NULL);
1425 	g_return_val_if_fail (oldChild != NULL, NULL);
1426 	g_return_val_if_fail (GDOME_XML_IS_N (oldChild), NULL);
1427 	g_return_val_if_fail (exc != NULL, NULL);
1428 
1429   if (GDOME_ISREADONLY (self)) {
1430     *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
1431     return NULL;
1432   }
1433 
1434   refChild = gdome_n_nextSibling (oldChild, exc);
1435 	if (gdome_n_removeChild (self, oldChild, exc)) {
1436 		if (gdome_n_insertBefore (self, newChild, refChild, exc)) {
1437 			gdome_n_unref (newChild, exc);
1438       ret = oldChild;
1439 		} else {
1440 			gdome_n_unref (oldChild, exc);
1441 			ret = NULL;
1442 		}
1443 	}
1444 
1445 	if (refChild)
1446 		gdome_n_unref (refChild, exc);
1447 
1448   return ret;
1449 }
1450 
1451 /**
1452  * gdome_xml_n_addEventListener:
1453  * @self:  Node Object ref
1454  * @type:  the event type for which the user is registering
1455  * @listener:  the listener parameter takes an interface implemented by the
1456  *             user which contains the methods to be called when the event occurs.
1457  * @useCapture:  if %TRUE, useCapture indicates that the user wishes to initiate
1458  *               capture. After initiating capture, all events of the specified
1459  *               type will be dispatched to the registered EventListener before
1460  *               being dispatched to any EventTargets beneath them in the tree.
1461  *               Events which are bubbling upward through the tree will not
1462  *               trigger an EventListener designated to use capture.
1463  * @exc:  Exception Object ref
1464  *
1465  * This method allows the registration of event listeners on the event target.
1466  * If an EventListener is added to an EventTarget while it is processing an
1467  * event, it will not be triggered by the current actions but may be triggered
1468  * during a later stage of event flow, such as the bubbling phase.
1469  * If multiple identical EventListeners are registered on the same EventTarget
1470  * with the same parameters the duplicate instances are discarded. They do not
1471  * cause the EventListener to be called twice and since they are discarded
1472  * they do not need to be removed with the removeEventListener method.
1473  */
1474 void
gdome_xml_n_addEventListener(GdomeNode * self,GdomeDOMString * type,GdomeEventListener * listener,GdomeBoolean useCapture,GdomeException * exc)1475 gdome_xml_n_addEventListener (GdomeNode *self, GdomeDOMString *type,
1476                               GdomeEventListener *listener, GdomeBoolean useCapture,
1477                               GdomeException *exc)
1478 {
1479 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1480 	Gdome_xml_ListenerList *ll = NULL;
1481 	Gdome_xml_ListenerList *temp;
1482   guint32 codeType;
1483 
1484 	g_return_if_fail (priv != NULL);
1485 	g_return_if_fail (GDOME_XML_IS_N (priv));
1486 	g_return_if_fail (listener != NULL);
1487 	g_return_if_fail (type != NULL);
1488 	g_return_if_fail (exc != NULL);
1489 
1490 	/* duplicate instances are discarted */
1491   codeType = gdome_evt_evnt_codeOfName (type->str);
1492 	temp = priv->ll;
1493 	while (temp) {
1494 		if (temp->listener == listener &&
1495 				temp->type == codeType &&
1496 				temp->useCapture == useCapture) {
1497 			return;
1498 		}
1499 		temp = temp->next;
1500 	}
1501 
1502 	/* create a new ListenerList entry*/
1503 	ll = g_new (Gdome_xml_ListenerList, 1);
1504 	ll->type = codeType;
1505 	gdome_evt_evntl_ref (listener, exc);
1506 	ll->listener = listener;
1507 	ll->useCapture = useCapture;
1508 
1509 	/* add it at begin of the ListenerList of the target */
1510 	ll->next = priv->ll;
1511 	priv->ll = ll;
1512 }
1513 
1514 /**
1515  * gdome_xml_n_removeEventListener:
1516  * @self:  Node Object ref
1517  * @type:  Specifies the event type of the EventListener being removed.
1518  * @listener:  The EventListener parameter indicates the EventListener to be
1519  *             removed.
1520  * @useCapture:  Specifies whether the EventListener being removed was
1521  *               registered as a capturing listener or not. If a listener was
1522  *               registered twice, one with capture and one without, each must
1523  *               be removed separately. Removal of a capturing listener does
1524  *               not affect a non-capturing version of the same listener, and
1525  *               vice versa.
1526  * @exc:  Exception Object ref
1527  *
1528  * This method allows the removal of event listeners from the event target. If
1529  * an EventListener is removed from an EventTarget while it is processing an
1530  * event, it will not be triggered by the current actions. EventListeners can
1531  * never be invoked after being removed. Calling removeEventListener with
1532  * arguments which do not identify any currently registered EventListener on
1533  * the EventTarget has no effect.
1534  */
1535 void
gdome_xml_n_removeEventListener(GdomeNode * self,GdomeDOMString * type,GdomeEventListener * listener,GdomeBoolean useCapture,GdomeException * exc)1536 gdome_xml_n_removeEventListener (GdomeNode *self, GdomeDOMString *type,
1537 																 GdomeEventListener *listener, GdomeBoolean useCapture,
1538 																 GdomeException *exc)
1539 {
1540 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1541   Gdome_xml_ListenerList *temp, *prev = NULL;
1542   guint32 codeType;
1543 
1544 	g_return_if_fail (priv != NULL);
1545 	g_return_if_fail (GDOME_XML_IS_N (priv));
1546 	g_return_if_fail (listener != NULL);
1547 	g_return_if_fail (type != NULL);
1548 	g_return_if_fail (exc != NULL);
1549 
1550   codeType = gdome_evt_evnt_codeOfName (type->str);
1551   temp = priv->ll;
1552 	while (temp) {
1553     if (useCapture == temp->useCapture &&
1554         temp->listener == listener &&
1555         temp->type == codeType) {
1556         if (prev)
1557           prev->next = temp->next;
1558         else {
1559           g_assert (priv->ll == temp);
1560           priv->ll = priv->ll->next;
1561         }
1562         temp->next = NULL;
1563         gdome_evt_evntl_unref (listener, exc);
1564         g_free (temp);
1565         break;
1566     }
1567     prev = temp;
1568 		temp = temp->next;
1569 	}
1570 }
1571 
1572 
1573 /**
1574  * gdome_xml_n_dispatchEvent:
1575  * @self:  Node Object ref
1576  * @evt:  Specifies the event type, behavior, and contextual information to be
1577  *        used in processing the event.
1578  * @exc:  Exception Object ref
1579  *
1580  * This method allows the dispatch of events into the implementations event
1581  * model. Events dispatched in this manner will have the same capturing and
1582  * bubbling behavior as events dispatched directly by the implementation. The
1583  * target of the event is the EventTarget on which dispatchEvent is called.
1584  *
1585  * GDOME_UNSPECIFIED_EVENT_TYPE_ERR: Raised if the Event's type was not
1586  * specified by initializing the event before dispatchEvent was called.
1587  * Specification of the Event's type as %NULL or an empty string will also
1588  * trigger this exception.
1589  * Returns: if preventDefault was called the value is %FALSE, else the value
1590  *          is %TRUE.
1591  */
1592 GdomeBoolean
gdome_xml_n_dispatchEvent(GdomeNode * self,GdomeEvent * evt,GdomeException * exc)1593 gdome_xml_n_dispatchEvent (GdomeNode *self, GdomeEvent *evt, GdomeException *exc)
1594 {
1595   Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1596   Gdome_evt_Event *ev_priv = (Gdome_evt_Event *)evt;
1597 
1598 	g_return_val_if_fail (priv != NULL, FALSE);
1599 	g_return_val_if_fail (GDOME_XML_IS_N (priv), FALSE);
1600 	g_return_val_if_fail (evt != NULL, FALSE);
1601   g_return_val_if_fail (exc != NULL, FALSE);
1602 
1603   if (ev_priv->type == 0) {
1604     *exc = GDOME_EVENT_EXCEPTION + GDOME_UNSPECIFIED_EVENT_TYPE_ERR;
1605     return FALSE;
1606   }
1607 
1608   gdome_xml_n_ref (self, exc);
1609 	ev_priv->target = self;
1610   gdome_evt_fireEvent (evt);
1611   gdome_xml_n_unref (self, exc);
1612 
1613 	return !ev_priv->default_prevented;
1614 }
1615 
1616 /**
1617  * gdome_xml_n_subTreeDispatchEvent:
1618  * @self:  Node Object ref
1619  * @evt:  Specifies the event type, behavior, and contextual information to be
1620  *        used in processing the event.
1621  * @exc:  Exception Object ref
1622  *
1623  * This method allows the dispatch of events into the implementations event
1624  * model. Events dispatched in this manner will have the same capturing and
1625  * bubbling behavior as events dispatched directly by the implementation. The
1626  * target of the event is any nodes in the subtree of the EventTarget on which
1627  * dispatchEvent is called.
1628  *
1629  * GDOME_UNSPECIFIED_EVENT_TYPE_ERR: Raised if the Event's type was not
1630  * specified by initializing the event before dispatchEvent was called.
1631  * Specification of the Event's type as %NULL or an empty string will also
1632  * trigger this exception.
1633  */
1634 void
gdome_xml_n_subTreeDispatchEvent(GdomeNode * self,GdomeEvent * evt,GdomeException * exc)1635 gdome_xml_n_subTreeDispatchEvent (GdomeNode *self, GdomeEvent *evt, GdomeException *exc)
1636 {
1637 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1638   GdomeNode *child, *temp;
1639 
1640 	g_return_if_fail (priv != NULL);
1641 	g_return_if_fail (GDOME_XML_IS_N (priv));
1642   g_return_if_fail (evt != NULL);
1643 	g_return_if_fail (exc != NULL);
1644 
1645 	child = gdome_xml_n_firstChild (self, exc);
1646 
1647 	while (child) {
1648 		gdome_xml_n_dispatchEvent (child, evt, exc);
1649 		gdome_xml_n_subTreeDispatchEvent (child, evt, exc);
1650 		temp = gdome_xml_n_nextSibling (child, exc);
1651 		gdome_xml_n_unref (child, exc);
1652 		child = temp;
1653 	}
1654 }
1655 
1656 /**
1657  * gdome_xml_n_canAppend:
1658  * @self:  Node Object ref
1659  * @newChild:  The Node Object ref of the node to test
1660  * @exc:  Exception Object ref
1661  *
1662  * Tests if a @newChild can be added in the child list of this node.
1663  * Returns: %TRUE if @newChild can be added, %FALSE otherwise.
1664  */
1665 GdomeBoolean
gdome_xml_n_canAppend(GdomeNode * self,GdomeNode * newChild,GdomeException * exc)1666 gdome_xml_n_canAppend (GdomeNode *self, GdomeNode *newChild, GdomeException *exc)
1667 {
1668 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1669 	Gdome_xml_Node *new_priv = (Gdome_xml_Node *)newChild;
1670 	xmlElementType new_type;
1671   GdomeBoolean ret = TRUE;
1672 
1673 	g_return_val_if_fail (priv != NULL, FALSE);
1674 	g_return_val_if_fail (GDOME_XML_IS_N (priv), FALSE);
1675 	g_return_val_if_fail (new_priv != NULL, FALSE);
1676 	g_return_val_if_fail (GDOME_XML_IS_N (new_priv), FALSE);
1677 	g_return_val_if_fail (exc != NULL, FALSE);
1678 
1679   /* Check if self can have a child of newChild type */
1680   new_type = gdome_xmlGetType (new_priv->n);
1681   if (new_type == XML_DOCUMENT_FRAG_NODE)
1682 		return TRUE;
1683 	switch (gdome_xmlGetType (priv->n)) {
1684 	case XML_DOCUMENT_TYPE_NODE:
1685   case XML_DTD_NODE:
1686 	case XML_PI_NODE:
1687 	case XML_COMMENT_NODE:
1688   case XML_TEXT_NODE:
1689   case XML_CDATA_SECTION_NODE:
1690   case XML_NOTATION_NODE:
1691 		ret = FALSE;
1692     break;
1693 	case XML_DOCUMENT_NODE:
1694     /* Element (max of one), ProcessingInstruction, Comment, DocumentType (max of one) */
1695 		if ((new_type != XML_ELEMENT_NODE &&
1696 				 new_type != XML_PI_NODE &&
1697 				 new_type != XML_COMMENT_NODE &&
1698 				 new_type != XML_DTD_NODE &&
1699 				 new_type != XML_DOCUMENT_TYPE_NODE) ||
1700 				(new_type == XML_ELEMENT_NODE &&
1701 				 xmlDocGetRootElement ((xmlDoc *)priv->n) != NULL) ||
1702 				((new_type == XML_DTD_NODE ||
1703 					new_type == XML_DOCUMENT_TYPE_NODE) &&
1704 				 ((xmlDoc *)priv->n)->intSubset != NULL))
1705 			ret = FALSE;
1706     break;
1707   case XML_DOCUMENT_FRAG_NODE:
1708   case XML_ENTITY_REF_NODE:
1709   case XML_ELEMENT_NODE:
1710   case XML_ENTITY_NODE:
1711 	case XML_ENTITY_DECL:
1712 		/* Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference	*/
1713 		if (new_type != XML_ELEMENT_NODE &&
1714 				new_type != XML_PI_NODE &&
1715 				new_type != XML_COMMENT_NODE &&
1716 				new_type != XML_TEXT_NODE &&
1717 				new_type != XML_CDATA_SECTION_NODE &&
1718 				new_type != XML_ENTITY_REF_NODE)
1719 			ret = FALSE;
1720     break;
1721 	case XML_ATTRIBUTE_NODE:
1722     /* Text, EntityReference */
1723 		if (new_type != XML_TEXT_NODE &&
1724 				new_type != XML_ENTITY_REF_NODE)
1725 			ret = FALSE;
1726     break;
1727   default:
1728     g_warning ("gdome_xml_n_canAppend: invalid node type");
1729 		ret = FALSE;
1730     break;
1731 	}
1732 
1733   /* Check if newChild is an ancestor of self */
1734 	if (ret) {
1735 		xmlNode *p = priv->n;
1736 		while (p != NULL) {
1737 			if (p == new_priv->n) {
1738 				ret = FALSE;
1739 				break;
1740 			}
1741 			p = gdome_xmlGetParent (p);
1742 		}
1743 	}
1744 
1745   return ret;
1746 }
1747 
1748 /**
1749  * gdome_xml_n_eventEnabledByCode:
1750  * @self:  Node Objects ref
1751  * @code:  The event type to check
1752  *
1753  * Returns: TRUE if the specified event type is enabled
1754  */
1755 GdomeBoolean
gdome_xml_n_eventEnabledByCode(GdomeNode * self,guint32 code)1756 gdome_xml_n_eventEnabledByCode (GdomeNode *self, guint32 code)
1757 {
1758 	Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1759 	GdomeException exc = 0;
1760 	GdomeDocument *doc;
1761 	GdomeBoolean res;
1762 
1763 	g_return_val_if_fail (priv != NULL, FALSE);
1764 	g_return_val_if_fail (GDOME_XML_IS_N (priv), FALSE);
1765 
1766   doc = gdome_xml_doc_mkref (gdome_xmlGetOwnerOrSelf (priv->n));
1767 	g_assert(doc != NULL);
1768 
1769 	res = gdome_xml_doc_eventEnabledByCode (doc, code);
1770 
1771 	gdome_doc_unref(doc, &exc);
1772 	g_assert(exc == 0);
1773 
1774 	return res;
1775 }
1776