Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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.  * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
  7.  */
  8.  
  9. #include <assert.h>
  10. #include <stdbool.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #include <dom/core/attr.h>
  16. #include <dom/core/text.h>
  17. #include <dom/core/document.h>
  18. #include <dom/core/namednodemap.h>
  19. #include <dom/core/nodelist.h>
  20. #include <dom/core/implementation.h>
  21. #include <dom/core/document_type.h>
  22. #include <dom/events/events.h>
  23.  
  24. #include "core/string.h"
  25. #include "core/namednodemap.h"
  26. #include "core/attr.h"
  27. #include "core/cdatasection.h"
  28. #include "core/comment.h"
  29. #include "core/document.h"
  30. #include "core/document_type.h"
  31. #include "core/doc_fragment.h"
  32. #include "core/element.h"
  33. #include "core/entity_ref.h"
  34. #include "core/node.h"
  35. #include "core/pi.h"
  36. #include "core/text.h"
  37. #include "utils/utils.h"
  38. #include "utils/validate.h"
  39. #include "events/mutation_event.h"
  40.  
  41. static bool _dom_node_permitted_child(const dom_node_internal *parent,
  42.                 const dom_node_internal *child);
  43. static inline dom_exception _dom_node_attach(dom_node_internal *node,
  44.                 dom_node_internal *parent,
  45.                 dom_node_internal *previous,
  46.                 dom_node_internal *next);
  47. static inline void _dom_node_detach(dom_node_internal *node);
  48. static inline dom_exception _dom_node_attach_range(dom_node_internal *first,
  49.                 dom_node_internal *last,
  50.                 dom_node_internal *parent,
  51.                 dom_node_internal *previous,
  52.                 dom_node_internal *next);
  53. static inline void _dom_node_detach_range(dom_node_internal *first,
  54.                 dom_node_internal *last);
  55. static inline void _dom_node_replace(dom_node_internal *old,
  56.                 dom_node_internal *replacement);
  57.  
  58. static struct dom_node_vtable node_vtable = {
  59.         {
  60.                 DOM_NODE_EVENT_TARGET_VTABLE
  61.         },
  62.         DOM_NODE_VTABLE
  63. };
  64.  
  65. static struct dom_node_protect_vtable node_protect_vtable = {
  66.         DOM_NODE_PROTECT_VTABLE
  67. };
  68.  
  69.  
  70.  
  71. /*----------------------------------------------------------------------*/
  72.  
  73. /* The constructor and destructor of this object */
  74.  
  75. /* Create a DOM node and compose the vtable */
  76. dom_node_internal * _dom_node_create(void)
  77. {
  78.         dom_node_internal *node = malloc(sizeof(struct dom_node_internal));
  79.         if (node == NULL)
  80.                 return NULL;
  81.  
  82.         node->base.vtable = &node_vtable;
  83.         node->vtable = &node_protect_vtable;
  84.         return node;
  85. }
  86.  
  87. /**
  88.  * Destroy a DOM node
  89.  *
  90.  * \param node  The node to destroy
  91.  *
  92.  * ::node's parent link must be NULL and its reference count must be 0.
  93.  *
  94.  * ::node will be freed.
  95.  *
  96.  * This function should only be called from dom_node_unref or type-specific
  97.  * destructors (for destroying child nodes). Anything else should not
  98.  * be attempting to destroy nodes -- they should simply be unreferencing
  99.  * them (so destruction will occur at the appropriate time).
  100.  */
  101. void _dom_node_destroy(struct dom_node_internal *node)
  102. {
  103.         struct dom_document *owner = node->owner;
  104.         bool null_owner_permitted = (node->type == DOM_DOCUMENT_NODE ||
  105.                         node->type == DOM_DOCUMENT_TYPE_NODE);
  106.  
  107.         assert(null_owner_permitted || owner != NULL);
  108.  
  109.         if (!null_owner_permitted) {
  110.                 /* Claim a reference upon the owning document during
  111.                  * destruction to ensure that the document doesn't get
  112.                  * destroyed before its contents. */
  113.                 dom_node_ref(owner);
  114.         }
  115.  
  116.         /* Finalise this node, this should also destroy all the child nodes. */
  117.         _dom_node_finalise(node);
  118.  
  119.         if (!null_owner_permitted) {
  120.                 /* Release the reference we claimed on the document. If this
  121.                  * is the last reference held on the document and the list
  122.                  * of nodes pending deletion is empty, then the document will
  123.                  * be destroyed. */
  124.                 dom_node_unref(owner);
  125.         }
  126.  
  127.         /* Release our memory */
  128.         free(node);
  129. }
  130.  
  131. /**
  132.  * Initialise a DOM node
  133.  *
  134.  * \param node       The node to initialise
  135.  * \param doc        The document which owns the node
  136.  * \param type       The node type required
  137.  * \param name       The node (local) name, or NULL
  138.  * \param value      The node value, or NULL
  139.  * \param namespace  Namespace URI to use for node, or NULL
  140.  * \param prefix     Namespace prefix to use for node, or NULL
  141.  * \return DOM_NO_ERR on success.
  142.  *
  143.  * ::name, ::value, ::namespace, and ::prefix  will have their reference
  144.  * counts increased.
  145.  */
  146. dom_exception _dom_node_initialise(dom_node_internal *node,
  147.                 struct dom_document *doc, dom_node_type type,
  148.                 dom_string *name, dom_string *value,
  149.                 dom_string *namespace, dom_string *prefix)
  150. {
  151.         node->owner = doc;
  152.  
  153.         if (name != NULL)
  154.                 node->name = dom_string_ref(name);
  155.         else
  156.                 node->name = NULL;
  157.  
  158.         if (value != NULL)
  159.                 node->value = dom_string_ref(value);
  160.         else
  161.                 node->value = NULL;
  162.  
  163.         node->type = type;
  164.  
  165.         node->parent = NULL;
  166.         node->first_child = NULL;
  167.         node->last_child = NULL;
  168.         node->previous = NULL;
  169.         node->next = NULL;
  170.  
  171.         /* Note: nodes do not reference the document to which they belong,
  172.          * as this would result in the document never being destroyed once
  173.          * the client has finished with it. The document will be aware of
  174.          * any nodes that it owns through 2 mechanisms:
  175.          *
  176.          * either a) Membership of the document tree
  177.          * or     b) Membership of the list of nodes pending deletion
  178.          *
  179.          * It is not possible for any given node to be a member of both
  180.          * data structures at the same time.
  181.          *
  182.          * The document will not be destroyed until both of these
  183.          * structures are empty. It will forcibly attempt to empty
  184.          * the document tree on document destruction. Any still-referenced
  185.          * nodes at that time will be added to the list of nodes pending
  186.          * deletion. This list will not be forcibly emptied, as it contains
  187.          * those nodes (and their sub-trees) in use by client code.
  188.          */
  189.  
  190.         if (namespace != NULL)
  191.                 node->namespace = dom_string_ref(namespace);
  192.         else
  193.                 node->namespace = NULL;
  194.  
  195.         if (prefix != NULL)
  196.                 node->prefix = dom_string_ref(prefix);
  197.         else
  198.                 node->prefix = NULL;
  199.  
  200.         node->user_data = NULL;
  201.  
  202.         node->base.refcnt = 1;
  203.  
  204.         list_init(&node->pending_list);
  205.         if (node->type != DOM_DOCUMENT_NODE) {
  206.                 /* A Node should be in the pending list when it is created */
  207.                 dom_node_mark_pending(node);
  208.         }
  209.  
  210.         return _dom_event_target_internal_initialise(&node->eti);
  211. }
  212.  
  213. /**
  214.  * Finalise a DOM node
  215.  *
  216.  * \param node  The node to finalise
  217.  *
  218.  * The contents of ::node will be cleaned up. ::node will not be freed.
  219.  * All children of ::node should have been removed prior to finalisation.
  220.  */
  221. void _dom_node_finalise(dom_node_internal *node)
  222. {
  223.         struct dom_user_data *u, *v;
  224.         struct dom_node_internal *p;
  225.         struct dom_node_internal *n = NULL;
  226.  
  227.         /* Destroy user data */
  228.         for (u = node->user_data; u != NULL; u = v) {
  229.                 v = u->next;
  230.  
  231.                 if (u->handler != NULL)
  232.                         u->handler(DOM_NODE_DELETED, u->key, u->data,
  233.                                         NULL, NULL);
  234.  
  235.                 dom_string_unref(u->key);
  236.                 free(u);
  237.         }
  238.         node->user_data = NULL;
  239.  
  240.         if (node->prefix != NULL) {
  241.                 dom_string_unref(node->prefix);
  242.                 node->prefix = NULL;
  243.         }
  244.  
  245.         if (node->namespace != NULL) {
  246.                 dom_string_unref(node->namespace);
  247.                 node->namespace = NULL;
  248.         }
  249.  
  250.         /* Destroy all the child nodes of this node */
  251.         p = node->first_child;
  252.         while (p != NULL) {
  253.                 n = p->next;
  254.                 p->parent = NULL;
  255.                 dom_node_try_destroy(p);
  256.                 p = n;
  257.         }
  258.  
  259.         /* Paranoia */
  260.         node->next = NULL;
  261.         node->previous = NULL;
  262.         node->last_child = NULL;
  263.         node->first_child = NULL;
  264.         node->parent = NULL;
  265.  
  266.         if (node->value != NULL) {
  267.                 dom_string_unref(node->value);
  268.                 node->value = NULL;
  269.         }
  270.  
  271.         if (node->name != NULL) {
  272.                 dom_string_unref(node->name);
  273.                 node->name = NULL;
  274.         }
  275.  
  276.         /* If the node has no owner document, we need not to finalise its
  277.          * dom_event_target_internal structure.
  278.          */
  279.         if (node->owner != NULL)
  280.                 _dom_event_target_internal_finalise(&node->eti);
  281.  
  282.         /* Detach from the pending list, if we are in it,
  283.          * this part of code should always be the end of this function. */
  284.         if (node->pending_list.prev != &node->pending_list) {
  285.                 assert (node->pending_list.next != &node->pending_list);
  286.                 list_del(&node->pending_list);
  287.                 if (node->owner != NULL && node->type != DOM_DOCUMENT_NODE) {
  288.                         /* Deleting this node from the pending list may cause
  289.                          * the list to be null and we should try to destroy
  290.                          * the document. */
  291.                         _dom_document_try_destroy(node->owner);
  292.                 }
  293.         }
  294. }
  295.  
  296.  
  297. /* ---------------------------------------------------------------------*/
  298.  
  299. /* The public virtual function of this interface Node */
  300.  
  301. /**
  302.  * Retrieve the name of a DOM node
  303.  *
  304.  * \param node    The node to retrieve the name of
  305.  * \param result  Pointer to location to receive node name
  306.  * \return DOM_NO_ERR.
  307.  *
  308.  * The returned string will have its reference count increased. It is
  309.  * the responsibility of the caller to unref the string once it has
  310.  * finished with it.
  311.  */
  312. dom_exception _dom_node_get_node_name(dom_node_internal *node,
  313.                 dom_string **result)
  314. {
  315.         dom_string *node_name, *temp;
  316.         dom_exception err;
  317.  
  318.         /* Document Node and DocumentType Node can have no owner */
  319.         assert(node->type == DOM_DOCUMENT_TYPE_NODE ||
  320.                         node->type == DOM_DOCUMENT_NODE ||
  321.                         node->owner != NULL);
  322.  
  323.         assert(node->name != NULL);
  324.  
  325.         /* If this node was created using a namespace-aware method and
  326.          * has a defined prefix, then nodeName is a QName comprised
  327.          * of prefix:name. */
  328.         if (node->prefix != NULL) {
  329.                 dom_string *colon;
  330.  
  331.                 err = dom_string_create((const uint8_t *) ":", SLEN(":"),
  332.                                 &colon);
  333.                 if (err != DOM_NO_ERR) {
  334.                         return err;
  335.                 }
  336.  
  337.                 /* Prefix + : */
  338.                 err = dom_string_concat(node->prefix, colon, &temp);
  339.                 if (err != DOM_NO_ERR) {
  340.                         dom_string_unref(colon);
  341.                         return err;
  342.                 }
  343.  
  344.                 /* Finished with colon */
  345.                 dom_string_unref(colon);
  346.  
  347.                 /* Prefix + : + Localname */
  348.                 err = dom_string_concat(temp, node->name, &node_name);
  349.                 if (err != DOM_NO_ERR) {
  350.                         dom_string_unref(temp);
  351.                         return err;
  352.                 }
  353.  
  354.                 /* Finished with temp */
  355.                 dom_string_unref(temp);
  356.         } else {
  357.                 node_name = dom_string_ref(node->name);
  358.         }
  359.  
  360.         *result = node_name;
  361.  
  362.         return DOM_NO_ERR;
  363. }
  364.  
  365. /**
  366.  * Retrieve the value of a DOM node
  367.  *
  368.  * \param node    The node to retrieve the value of
  369.  * \param result  Pointer to location to receive node value
  370.  * \return DOM_NO_ERR.
  371.  *
  372.  * The returned string will have its reference count increased. It is
  373.  * the responsibility of the caller to unref the string once it has
  374.  * finished with it.
  375.  *
  376.  * DOM3Core states that this can raise DOMSTRING_SIZE_ERR. It will not in
  377.  * this implementation; dom_strings are unbounded.
  378.  */
  379. dom_exception _dom_node_get_node_value(dom_node_internal *node,
  380.                 dom_string **result)
  381. {
  382.         if (node->value != NULL)
  383.                 dom_string_ref(node->value);
  384.  
  385.         *result = node->value;
  386.  
  387.         return DOM_NO_ERR;
  388. }
  389.  
  390. /**
  391.  * Set the value of a DOM node
  392.  *
  393.  * \param node   Node to set the value of
  394.  * \param value  New value for node
  395.  * \return DOM_NO_ERR                      on success,
  396.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if the node is readonly and the
  397.  *                                         value is not defined to be null.
  398.  *
  399.  * The new value will have its reference count increased, so the caller
  400.  * should unref it after the call (as the caller should have already claimed
  401.  * a reference on the string). The node's existing value will be unrefed.
  402.  */
  403. dom_exception _dom_node_set_node_value(dom_node_internal *node,
  404.                 dom_string *value)
  405. {
  406.         /* TODO
  407.          * Whether we should change this to a virtual function?
  408.          */
  409.         /* This is a NOP if the value is defined to be null. */
  410.         if (node->type == DOM_DOCUMENT_NODE ||
  411.                         node->type == DOM_DOCUMENT_FRAGMENT_NODE ||
  412.                         node->type == DOM_DOCUMENT_TYPE_NODE ||
  413.                         node->type == DOM_ELEMENT_NODE ||
  414.                         node->type == DOM_ENTITY_NODE ||
  415.                         node->type == DOM_ENTITY_REFERENCE_NODE ||
  416.                         node->type == DOM_NOTATION_NODE) {
  417.                 return DOM_NO_ERR;
  418.         }
  419.  
  420.         /* Ensure node is writable */
  421.         if (_dom_node_readonly(node))
  422.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  423.  
  424.         /* If it's an attribute node, then delegate setting to
  425.          * the type-specific function */
  426.         if (node->type == DOM_ATTRIBUTE_NODE)
  427.                 return dom_attr_set_value((struct dom_attr *) node, value);
  428.  
  429.         if (node->value != NULL)
  430.                 dom_string_unref(node->value);
  431.  
  432.         if (value != NULL)
  433.                 dom_string_ref(value);
  434.  
  435.         node->value = value;
  436.  
  437.         return DOM_NO_ERR;
  438. }
  439.  
  440. /**
  441.  * Retrieve the type of a DOM node
  442.  *
  443.  * \param node    The node to retrieve the type of
  444.  * \param result  Pointer to location to receive node type
  445.  * \return DOM_NO_ERR.
  446.  */
  447. dom_exception _dom_node_get_node_type(dom_node_internal *node,
  448.                 dom_node_type *result)
  449. {
  450.         *result = node->type;
  451.  
  452.         return DOM_NO_ERR;
  453. }
  454.  
  455. /**
  456.  * Retrieve the parent of a DOM node
  457.  *
  458.  * \param node    The node to retrieve the parent of
  459.  * \param result  Pointer to location to receive node parent
  460.  * \return DOM_NO_ERR.
  461.  *
  462.  * The returned node will have its reference count increased. It is
  463.  * the responsibility of the caller to unref the node once it has
  464.  * finished with it.
  465.  */
  466. dom_exception _dom_node_get_parent_node(dom_node_internal *node,
  467.                 dom_node_internal **result)
  468. {
  469.         /* Attr nodes have no parent */
  470.         if (node->type == DOM_ATTRIBUTE_NODE) {
  471.                 *result = NULL;
  472.                 return DOM_NO_ERR;
  473.         }
  474.  
  475.         /* If there is a parent node, then increase its reference count */
  476.         if (node->parent != NULL)
  477.                 dom_node_ref(node->parent);
  478.  
  479.         *result = node->parent;
  480.  
  481.         return DOM_NO_ERR;
  482. }
  483.  
  484. /**
  485.  * Retrieve a list of children of a DOM node
  486.  *
  487.  * \param node    The node to retrieve the children of
  488.  * \param result  Pointer to location to receive child list
  489.  * \return DOM_NO_ERR.
  490.  *
  491.  * The returned NodeList will be referenced. It is the responsibility
  492.  * of the caller to unref the list once it has finished with it.
  493.  */
  494. dom_exception _dom_node_get_child_nodes(dom_node_internal *node,
  495.                 struct dom_nodelist **result)
  496. {
  497.         /* Can't do anything without an owning document.
  498.          * This is only a problem for DocumentType nodes
  499.          * which are not yet attached to a document.
  500.          * DocumentType nodes have no children, anyway. */
  501.         if (node->owner == NULL)
  502.                 return DOM_NOT_SUPPORTED_ERR;
  503.  
  504.         return _dom_document_get_nodelist(node->owner, DOM_NODELIST_CHILDREN,
  505.                         node, NULL, NULL, NULL, result);
  506. }
  507.  
  508. /**
  509.  * Retrieve the first child of a DOM node
  510.  *
  511.  * \param node    The node to retrieve the first child of
  512.  * \param result  Pointer to location to receive node's first child
  513.  * \return DOM_NO_ERR.
  514.  *
  515.  * The returned node will have its reference count increased. It is
  516.  * the responsibility of the caller to unref the node once it has
  517.  * finished with it.
  518.  */
  519. dom_exception _dom_node_get_first_child(dom_node_internal *node,
  520.                 dom_node_internal **result)
  521. {
  522.         /* If there is a first child, increase its reference count */
  523.         if (node->first_child != NULL)
  524.                 dom_node_ref(node->first_child);
  525.  
  526.         *result = node->first_child;
  527.  
  528.         return DOM_NO_ERR;
  529. }
  530.  
  531. /**
  532.  * Retrieve the last child of a DOM node
  533.  *
  534.  * \param node    The node to retrieve the last child of
  535.  * \param result  Pointer to location to receive node's last child
  536.  * \return DOM_NO_ERR.
  537.  *
  538.  * The returned node will have its reference count increased. It is
  539.  * the responsibility of the caller to unref the node once it has
  540.  * finished with it.
  541.  */
  542. dom_exception _dom_node_get_last_child(dom_node_internal *node,
  543.                 dom_node_internal **result)
  544. {
  545.         /* If there is a last child, increase its reference count */
  546.         if (node->last_child != NULL)
  547.                 dom_node_ref(node->last_child);
  548.  
  549.         *result = node->last_child;
  550.  
  551.         return DOM_NO_ERR;
  552. }
  553.  
  554. /**
  555.  * Retrieve the previous sibling of a DOM node
  556.  *
  557.  * \param node    The node to retrieve the previous sibling of
  558.  * \param result  Pointer to location to receive node's previous sibling
  559.  * \return DOM_NO_ERR.
  560.  *
  561.  * The returned node will have its reference count increased. It is
  562.  * the responsibility of the caller to unref the node once it has
  563.  * finished with it.
  564.  */
  565. dom_exception _dom_node_get_previous_sibling(dom_node_internal *node,
  566.                 dom_node_internal **result)
  567. {
  568.         /* Attr nodes have no previous siblings */
  569.         if (node->type == DOM_ATTRIBUTE_NODE) {
  570.                 *result = NULL;
  571.                 return DOM_NO_ERR;
  572.         }
  573.  
  574.         /* If there is a previous sibling, increase its reference count */
  575.         if (node->previous != NULL)
  576.                 dom_node_ref(node->previous);
  577.  
  578.         *result = node->previous;
  579.  
  580.         return DOM_NO_ERR;
  581. }
  582.  
  583. /**
  584.  * Retrieve the subsequent sibling of a DOM node
  585.  *
  586.  * \param node    The node to retrieve the subsequent sibling of
  587.  * \param result  Pointer to location to receive node's subsequent sibling
  588.  * \return DOM_NO_ERR.
  589.  *
  590.  * The returned node will have its reference count increased. It is
  591.  * the responsibility of the caller to unref the node once it has
  592.  * finished with it.
  593.  */
  594. dom_exception _dom_node_get_next_sibling(dom_node_internal *node,
  595.                 dom_node_internal **result)
  596. {
  597.         /* Attr nodes have no next siblings */
  598.         if (node->type == DOM_ATTRIBUTE_NODE) {
  599.                 *result = NULL;
  600.                 return DOM_NO_ERR;
  601.         }
  602.  
  603.         /* If there is a subsequent sibling, increase its reference count */
  604.         if (node->next != NULL)
  605.                 dom_node_ref(node->next);
  606.  
  607.         *result = node->next;
  608.  
  609.         return DOM_NO_ERR;
  610. }
  611.  
  612. /**
  613.  * Retrieve a map of attributes associated with a DOM node
  614.  *
  615.  * \param node    The node to retrieve the attributes of
  616.  * \param result  Pointer to location to receive attribute map
  617.  * \return DOM_NO_ERR.
  618.  *
  619.  * The returned NamedNodeMap will be referenced. It is the responsibility
  620.  * of the caller to unref the map once it has finished with it.
  621.  *
  622.  * If ::node is not an Element, then NULL will be returned.
  623.  */
  624. dom_exception _dom_node_get_attributes(dom_node_internal *node,
  625.                 struct dom_namednodemap **result)
  626. {
  627.         UNUSED(node);
  628.         *result = NULL;
  629.  
  630.         return DOM_NO_ERR;
  631. }
  632.  
  633. /**
  634.  * Retrieve the owning document of a DOM node
  635.  *
  636.  * \param node    The node to retrieve the owner of
  637.  * \param result  Pointer to location to receive node's owner
  638.  * \return DOM_NO_ERR.
  639.  *
  640.  * The returned node will have its reference count increased. It is
  641.  * the responsibility of the caller to unref the node once it has
  642.  * finished with it.
  643.  */
  644. dom_exception _dom_node_get_owner_document(dom_node_internal *node,
  645.                 struct dom_document **result)
  646. {
  647.         /* Document nodes have no owner, as far as clients are concerned
  648.          * In reality, they own themselves as this simplifies code elsewhere */
  649.         if (node->type == DOM_DOCUMENT_NODE) {
  650.                 *result = NULL;
  651.  
  652.                 return DOM_NO_ERR;
  653.         }
  654.  
  655.         /* If there is an owner, increase its reference count */
  656.         if (node->owner != NULL)
  657.                 dom_node_ref(node->owner);
  658.  
  659.         *result = node->owner;
  660.  
  661.         return DOM_NO_ERR;
  662. }
  663.  
  664. /**
  665.  * Insert a child into a node
  666.  *
  667.  * \param node       Node to insert into
  668.  * \param new_child  Node to insert
  669.  * \param ref_child  Node to insert before, or NULL to insert as last child
  670.  * \param result     Pointer to location to receive node being inserted
  671.  * \return DOM_NO_ERR                      on success,
  672.  *         DOM_HIERARCHY_REQUEST_ERR       if ::new_child's type is not
  673.  *                                         permitted as a child of ::node,
  674.  *                                         or ::new_child is an ancestor of
  675.  *                                         ::node (or is ::node itself), or
  676.  *                                         ::node is of type Document and a
  677.  *                                         second DocumentType or Element is
  678.  *                                         being inserted,
  679.  *         DOM_WRONG_DOCUMENT_ERR          if ::new_child was created from a
  680.  *                                         different document than ::node,
  681.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly, or
  682.  *                                         ::new_child's parent is readonly,
  683.  *         DOM_NOT_FOUND_ERR               if ::ref_child is not a child of
  684.  *                                         ::node.
  685.  *
  686.  * If ::new_child is a DocumentFragment, all of its children are inserted.
  687.  * If ::new_child is already in the tree, it is first removed.
  688.  *
  689.  * Attempting to insert a node before itself is a NOP.
  690.  *
  691.  * The returned node will have its reference count increased. It is
  692.  * the responsibility of the caller to unref the node once it has
  693.  * finished with it.
  694.  */
  695. dom_exception _dom_node_insert_before(dom_node_internal *node,
  696.                 dom_node_internal *new_child, dom_node_internal *ref_child,
  697.                 dom_node_internal **result)
  698. {
  699.         dom_exception err;
  700.         dom_node_internal *n;
  701.        
  702.         assert(node != NULL);
  703.        
  704.         /* Ensure that new_child and node are owned by the same document */
  705.         if ((new_child->type == DOM_DOCUMENT_TYPE_NODE &&
  706.                         new_child->owner != NULL &&
  707.                         new_child->owner != node->owner) ||
  708.                         (new_child->type != DOM_DOCUMENT_TYPE_NODE &&
  709.                         new_child->owner != node->owner))
  710.                 return DOM_WRONG_DOCUMENT_ERR;
  711.  
  712.         /* Ensure node isn't read only */
  713.         if (_dom_node_readonly(node))
  714.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  715.  
  716.         /* Ensure that ref_child (if any) is a child of node */
  717.         if (ref_child != NULL && ref_child->parent != node)
  718.                 return DOM_NOT_FOUND_ERR;
  719.        
  720.         /* Ensure that new_child is not an ancestor of node, nor node itself */
  721.         for (n = node; n != NULL; n = n->parent) {
  722.                 if (n == new_child)
  723.                         return DOM_HIERARCHY_REQUEST_ERR;
  724.         }
  725.  
  726.         /* Ensure that new_child is permitted as a child of node */
  727.         if (new_child->type != DOM_DOCUMENT_FRAGMENT_NODE &&
  728.                         !_dom_node_permitted_child(node, new_child))
  729.                 return DOM_HIERARCHY_REQUEST_ERR;
  730.  
  731.         /* Attempting to insert a node before itself is a NOP */
  732.         if (new_child == ref_child) {
  733.                 dom_node_ref(new_child);
  734.                 *result = new_child;
  735.  
  736.                 return DOM_NO_ERR;
  737.         }
  738.  
  739.         /* If new_child is already in the tree and
  740.          * its parent isn't read only, remove it */
  741.         if (new_child->parent != NULL) {
  742.                 if (_dom_node_readonly(new_child->parent))
  743.                         return DOM_NO_MODIFICATION_ALLOWED_ERR;
  744.  
  745.                 _dom_node_detach(new_child);
  746.         }
  747.  
  748.         /* When a Node is attached, it should be removed from the pending
  749.          * list */
  750.         dom_node_remove_pending(new_child);
  751.  
  752.         /* If new_child is a DocumentFragment, insert its children.
  753.          * Otherwise, insert new_child */
  754.         if (new_child->type == DOM_DOCUMENT_FRAGMENT_NODE) {
  755.                 /* Test the children of the docment fragment can be appended */
  756.                 dom_node_internal *c = new_child->first_child;
  757.                 for (; c != NULL; c = c->next)
  758.                         if (!_dom_node_permitted_child(node, c))
  759.                                 return DOM_HIERARCHY_REQUEST_ERR;
  760.  
  761.                 if (new_child->first_child != NULL) {
  762.                         err = _dom_node_attach_range(new_child->first_child,
  763.                                         new_child->last_child,
  764.                                         node,
  765.                                         ref_child == NULL ? node->last_child
  766.                                                           : ref_child->previous,
  767.                                         ref_child == NULL ? NULL
  768.                                                           : ref_child);
  769.                         if (err != DOM_NO_ERR)
  770.                                 return err;
  771.  
  772.                         new_child->first_child = NULL;
  773.                         new_child->last_child = NULL;
  774.                 }
  775.         } else {
  776.                 err = _dom_node_attach(new_child,
  777.                                 node,
  778.                                 ref_child == NULL ? node->last_child
  779.                                                   : ref_child->previous,
  780.                                 ref_child == NULL ? NULL
  781.                                                   : ref_child);
  782.                 if (err != DOM_NO_ERR)
  783.                         return err;
  784.  
  785.         }
  786.  
  787.         /* DocumentType nodes are created outside the Document so,
  788.          * if we're trying to attach a DocumentType node, then we
  789.          * also need to set its owner. */
  790.         if (node->type == DOM_DOCUMENT_NODE &&
  791.                         new_child->type == DOM_DOCUMENT_TYPE_NODE) {
  792.                 /* See long comment in _dom_node_initialise as to why
  793.                  * we don't ref the document here */
  794.                 new_child->owner = (struct dom_document *) node;
  795.         }
  796.  
  797.         /** \todo Is it correct to return DocumentFragments? */
  798.  
  799.         dom_node_ref(new_child);
  800.         *result = new_child;
  801.  
  802.         return DOM_NO_ERR;
  803. }
  804.  
  805. /**
  806.  * Replace a node's child with a new one
  807.  *
  808.  * \param node       Node whose child to replace
  809.  * \param new_child  Replacement node
  810.  * \param old_child  Child to replace
  811.  * \param result     Pointer to location to receive replaced node
  812.  * \return DOM_NO_ERR                      on success,
  813.  *         DOM_HIERARCHY_REQUEST_ERR       if ::new_child's type is not
  814.  *                                         permitted as a child of ::node,
  815.  *                                         or ::new_child is an ancestor of
  816.  *                                         ::node (or is ::node itself), or
  817.  *                                         ::node is of type Document and a
  818.  *                                         second DocumentType or Element is
  819.  *                                         being inserted,
  820.  *         DOM_WRONG_DOCUMENT_ERR          if ::new_child was created from a
  821.  *                                         different document than ::node,
  822.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly, or
  823.  *                                         ::new_child's parent is readonly,
  824.  *         DOM_NOT_FOUND_ERR               if ::old_child is not a child of
  825.  *                                         ::node,
  826.  *         DOM_NOT_SUPPORTED_ERR           if ::node is of type Document and
  827.  *                                         ::new_child is of type
  828.  *                                         DocumentType or Element.
  829.  *
  830.  * If ::new_child is a DocumentFragment, ::old_child is replaced by all of
  831.  * ::new_child's children.
  832.  * If ::new_child is already in the tree, it is first removed.
  833.  *
  834.  * The returned node will have its reference count increased. It is
  835.  * the responsibility of the caller to unref the node once it has
  836.  * finished with it.
  837.  */
  838. dom_exception _dom_node_replace_child(dom_node_internal *node,
  839.                 dom_node_internal *new_child, dom_node_internal *old_child,
  840.                 dom_node_internal **result)
  841. {
  842.         dom_node_internal *n;
  843.  
  844.         /* We don't support replacement of DocumentType or root Elements */
  845.         if (node->type == DOM_DOCUMENT_NODE &&
  846.                         (new_child->type == DOM_DOCUMENT_TYPE_NODE ||
  847.                         new_child->type == DOM_ELEMENT_NODE))
  848.                 return DOM_NOT_SUPPORTED_ERR;
  849.  
  850.         /* Ensure that new_child and node are owned by the same document */
  851.         if (new_child->owner != node->owner)
  852.                 return DOM_WRONG_DOCUMENT_ERR;
  853.  
  854.         /* Ensure node isn't read only */
  855.         if (_dom_node_readonly(node))
  856.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  857.  
  858.         /* Ensure that old_child is a child of node */
  859.         if (old_child->parent != node)
  860.                 return DOM_NOT_FOUND_ERR;
  861.  
  862.         /* Ensure that new_child is not an ancestor of node, nor node itself */
  863.         for (n = node; n != NULL; n = n->parent) {
  864.                 if (n == new_child)
  865.                         return DOM_HIERARCHY_REQUEST_ERR;
  866.         }
  867.  
  868.         /* Ensure that new_child is permitted as a child of node */
  869.         if (new_child->type == DOM_DOCUMENT_FRAGMENT_NODE) {
  870.                 /* If this node is a doc fragment, we should test all its
  871.                  * children nodes */
  872.                 dom_node_internal *c;
  873.                 c = new_child->first_child;
  874.                 while (c != NULL) {
  875.                         if (!_dom_node_permitted_child(node, c))
  876.                                 return DOM_HIERARCHY_REQUEST_ERR;
  877.  
  878.                         c = c->next;
  879.                 }
  880.         } else {
  881.                 if (!_dom_node_permitted_child(node, new_child))
  882.                         return DOM_HIERARCHY_REQUEST_ERR;
  883.         }
  884.  
  885.         /* Attempting to replace a node with itself is a NOP */
  886.         if (new_child == old_child) {
  887.                 dom_node_ref(old_child);
  888.                 *result = old_child;
  889.  
  890.                 return DOM_NO_ERR;
  891.         }
  892.  
  893.         /* If new_child is already in the tree and
  894.          * its parent isn't read only, remove it */
  895.         if (new_child->parent != NULL) {
  896.                 if (_dom_node_readonly(new_child->parent))
  897.                         return DOM_NO_MODIFICATION_ALLOWED_ERR;
  898.  
  899.                 _dom_node_detach(new_child);
  900.         }
  901.  
  902.         /* When a Node is attached, it should be removed from the pending
  903.          * list */
  904.         dom_node_remove_pending(new_child);
  905.  
  906.         /* Perform the replacement */
  907.         _dom_node_replace(old_child, new_child);
  908.  
  909.         /* Sort out the return value */
  910.         dom_node_ref(old_child);
  911.         /* The replaced node should be marded pending */
  912.         dom_node_mark_pending(old_child);
  913.         *result = old_child;
  914.  
  915.         return DOM_NO_ERR;
  916. }
  917.  
  918. /**
  919.  * Remove a child from a node
  920.  *
  921.  * \param node       Node whose child to replace
  922.  * \param old_child  Child to remove
  923.  * \param result     Pointer to location to receive removed node
  924.  * \return DOM_NO_ERR                      on success,
  925.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly
  926.  *         DOM_NOT_FOUND_ERR               if ::old_child is not a child of
  927.  *                                         ::node,
  928.  *         DOM_NOT_SUPPORTED_ERR           if ::node is of type Document and
  929.  *                                         ::new_child is of type
  930.  *                                         DocumentType or Element.
  931.  *
  932.  * The returned node will have its reference count increased. It is
  933.  * the responsibility of the caller to unref the node once it has
  934.  * finished with it.
  935.  */
  936. dom_exception _dom_node_remove_child(dom_node_internal *node,
  937.                 dom_node_internal *old_child,
  938.                 dom_node_internal **result)
  939. {
  940.         dom_exception err;
  941.         bool success = true;
  942.  
  943.         /* We don't support removal of DocumentType or root Element nodes */
  944.         if (node->type == DOM_DOCUMENT_NODE &&
  945.                         (old_child->type == DOM_DOCUMENT_TYPE_NODE ||
  946.                         old_child->type == DOM_ELEMENT_NODE))
  947.                 return DOM_NOT_SUPPORTED_ERR;
  948.  
  949.         /* Ensure old_child is a child of node */
  950.         if (old_child->parent != node)
  951.                 return DOM_NOT_FOUND_ERR;
  952.  
  953.         /* Ensure node is writable */
  954.         if (_dom_node_readonly(node))
  955.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  956.  
  957.         /* Dispatch a DOMNodeRemoval event */
  958.         err = dom_node_dispatch_node_change_event(node->owner, old_child, node,
  959.                         DOM_MUTATION_REMOVAL, &success);
  960.         if (err != DOM_NO_ERR)
  961.                 return err;
  962.  
  963.         /* Detach the node */
  964.         _dom_node_detach(old_child);
  965.  
  966.         /* When a Node is removed, it should be destroy. When its refcnt is not
  967.          * zero, it will be added to the document's deletion pending list.
  968.          * When a Node is removed, its parent should be NULL, but its owner
  969.          * should remain to be the document. */
  970.         dom_node_ref(old_child);
  971.         dom_node_try_destroy(old_child);
  972.         *result = old_child;
  973.  
  974.         success = true;
  975.         err = _dom_dispatch_subtree_modified_event(node->owner, node,
  976.                         &success);
  977.         if (err != DOM_NO_ERR)
  978.                 return err;
  979.  
  980.         return DOM_NO_ERR;
  981. }
  982.  
  983. /**
  984.  * Append a child to the end of a node's child list
  985.  *
  986.  * \param node       Node to insert into
  987.  * \param new_child  Node to append
  988.  * \param result     Pointer to location to receive node being inserted
  989.  * \return DOM_NO_ERR                      on success,
  990.  *         DOM_HIERARCHY_REQUEST_ERR       if ::new_child's type is not
  991.  *                                         permitted as a child of ::node,
  992.  *                                         or ::new_child is an ancestor of
  993.  *                                         ::node (or is ::node itself), or
  994.  *                                         ::node is of type Document and a
  995.  *                                         second DocumentType or Element is
  996.  *                                         being inserted,
  997.  *         DOM_WRONG_DOCUMENT_ERR          if ::new_child was created from a
  998.  *                                         different document than ::node,
  999.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly, or
  1000.  *                                         ::new_child's parent is readonly.
  1001.  *
  1002.  * If ::new_child is a DocumentFragment, all of its children are inserted.
  1003.  * If ::new_child is already in the tree, it is first removed.
  1004.  *
  1005.  * The returned node will have its reference count increased. It is
  1006.  * the responsibility of the caller to unref the node once it has
  1007.  * finished with it.
  1008.  */
  1009. dom_exception _dom_node_append_child(dom_node_internal *node,
  1010.                 dom_node_internal *new_child,
  1011.                 dom_node_internal **result)
  1012. {
  1013.         /* This is just a veneer over insert_before */
  1014.         return dom_node_insert_before(node, new_child, NULL, result);
  1015. }
  1016.  
  1017. /**
  1018.  * Determine if a node has any children
  1019.  *
  1020.  * \param node    Node to inspect
  1021.  * \param result  Pointer to location to receive result
  1022.  * \return DOM_NO_ERR.
  1023.  */
  1024. dom_exception _dom_node_has_child_nodes(dom_node_internal *node, bool *result)
  1025. {
  1026.         *result = node->first_child != NULL;
  1027.  
  1028.         return DOM_NO_ERR;
  1029. }
  1030.  
  1031. /**
  1032.  * Clone a DOM node
  1033.  *
  1034.  * \param node    The node to clone
  1035.  * \param deep    True to deep-clone the node's sub-tree
  1036.  * \param result  Pointer to location to receive result
  1037.  * \return DOM_NO_ERR        on success,
  1038.  *         DOM_NO_MEMORY_ERR on memory exhaustion.
  1039.  *
  1040.  * The returned node will already be referenced.
  1041.  *
  1042.  * The duplicate node will have no parent and no user data.
  1043.  *
  1044.  * If ::node has registered user_data_handlers, then they will be called.
  1045.  *
  1046.  * Cloning an Element copies all attributes & their values (including those
  1047.  * generated by the XML processor to represent defaulted attributes). It
  1048.  * does not copy any child nodes unless it is a deep copy (this includes
  1049.  * text contained within the Element, as the text is contained in a child
  1050.  * Text node).
  1051.  *
  1052.  * Cloning an Attr directly, as opposed to cloning as part of an Element,
  1053.  * returns a specified attribute. Cloning an Attr always clones its children,
  1054.  * since they represent its value, no matter whether this is a deep clone or
  1055.  * not.
  1056.  *
  1057.  * Cloning an EntityReference automatically constructs its subtree if a
  1058.  * corresponding Entity is available, no matter whether this is a deep clone
  1059.  * or not.
  1060.  *
  1061.  * Cloning any other type of node simply returns a copy.
  1062.  *
  1063.  * Note that cloning an immutable subtree results in a mutable copy, but
  1064.  * the children of an EntityReference clone are readonly. In addition, clones
  1065.  * of unspecified Attr nodes are specified.
  1066.  *
  1067.  * \todo work out what happens when cloning Document, DocumentType, Entity
  1068.  * and Notation nodes.
  1069.  *
  1070.  * Note: we adopt a OO paradigm, this clone_node just provide a basic operation
  1071.  * of clone. Special clones like Attr/EntitiReference stated above should
  1072.  * provide their overload of this interface in their implementation file.
  1073.  */
  1074. dom_exception _dom_node_clone_node(dom_node_internal *node, bool deep,
  1075.                 dom_node_internal **result)
  1076. {
  1077.         dom_node_internal *n, *child, *r;
  1078.         dom_exception err;
  1079.         dom_user_data *ud;
  1080.  
  1081.         assert(node->owner != NULL);
  1082.  
  1083.         err = dom_node_copy(node, &n);
  1084.         if (err != DOM_NO_ERR) {
  1085.                 return err;
  1086.         }
  1087.  
  1088.         if (deep) {
  1089.                 child = node->first_child;
  1090.                 while (child != NULL) {
  1091.                         err = dom_node_clone_node(child, deep, (void *) &r);
  1092.                         if (err != DOM_NO_ERR) {
  1093.                                 dom_node_unref(n);
  1094.                                 return err;
  1095.                         }
  1096.  
  1097.                         err = dom_node_append_child(n, r, (void *) &r);
  1098.                         if (err != DOM_NO_ERR) {
  1099.                                 dom_node_unref(n);
  1100.                                 return err;
  1101.                         }
  1102.                        
  1103.                         /* Clean up the new node, we have reference it two
  1104.                          * times */
  1105.                         dom_node_unref(r);
  1106.                         dom_node_unref(r);
  1107.                         child = child->next;
  1108.                 }
  1109.         }
  1110.  
  1111.         *result = n;
  1112.  
  1113.         /* Call the dom_user_data_handlers */
  1114.         ud = node->user_data;
  1115.         while (ud != NULL) {
  1116.                 if (ud->handler != NULL)
  1117.                         ud->handler(DOM_NODE_CLONED, ud->key, ud->data,
  1118.                                         (dom_node *) node, (dom_node *) n);
  1119.                 ud = ud->next;
  1120.         }
  1121.  
  1122.         return DOM_NO_ERR;
  1123. }
  1124.  
  1125. /**
  1126.  * Normalize a DOM node
  1127.  *
  1128.  * \param node  The node to normalize
  1129.  * \return DOM_NO_ERR.
  1130.  *
  1131.  * Puts all Text nodes in the full depth of the sub-tree beneath ::node,
  1132.  * including Attr nodes into "normal" form, where only structure separates
  1133.  * Text nodes.
  1134.  */
  1135. dom_exception _dom_node_normalize(dom_node_internal *node)
  1136. {
  1137.         dom_node_internal *n, *p;
  1138.         dom_exception err;
  1139.  
  1140.         p = node->first_child;
  1141.         if (p == NULL)
  1142.                 return DOM_NO_ERR;
  1143.  
  1144.         n = p->next;
  1145.  
  1146.         while (n != NULL) {
  1147.                 if (n->type == DOM_TEXT_NODE && p->type == DOM_TEXT_NODE) {
  1148.                         err = _dom_merge_adjacent_text(p, n);
  1149.                         if (err != DOM_NO_ERR)
  1150.                                 return err;
  1151.  
  1152.                         _dom_node_detach(n);
  1153.                         dom_node_unref(n);
  1154.                         n = p->next;
  1155.                         continue;
  1156.                 }
  1157.                 if (n->type != DOM_TEXT_NODE) {
  1158.                         err = dom_node_normalize(n);
  1159.                         if (err != DOM_NO_ERR)
  1160.                                 return err;
  1161.                 }
  1162.                 p = n;
  1163.                 n = n->next;
  1164.         }
  1165.  
  1166.         return DOM_NO_ERR;
  1167. }
  1168.  
  1169. /**
  1170.  * Test whether the DOM implementation implements a specific feature and
  1171.  * that feature is supported by the node.
  1172.  *
  1173.  * \param node     The node to test
  1174.  * \param feature  The name of the feature to test
  1175.  * \param version  The version number of the feature to test
  1176.  * \param result   Pointer to location to receive result
  1177.  * \return DOM_NO_ERR.
  1178.  */
  1179. dom_exception _dom_node_is_supported(dom_node_internal *node,
  1180.                 dom_string *feature, dom_string *version,
  1181.                 bool *result)
  1182. {
  1183.         bool has;
  1184.  
  1185.         UNUSED(node);
  1186.  
  1187.         dom_implementation_has_feature(dom_string_data(feature),
  1188.                         dom_string_data(version), &has);
  1189.  
  1190.         *result = has;
  1191.  
  1192.         return DOM_NO_ERR;
  1193. }
  1194.  
  1195. /**
  1196.  * Retrieve the namespace of a DOM node
  1197.  *
  1198.  * \param node    The node to retrieve the namespace of
  1199.  * \param result  Pointer to location to receive node's namespace
  1200.  * \return DOM_NO_ERR.
  1201.  *
  1202.  * The returned string will have its reference count increased. It is
  1203.  * the responsibility of the caller to unref the string once it has
  1204.  * finished with it.
  1205.  */
  1206. dom_exception _dom_node_get_namespace(dom_node_internal *node,
  1207.                 dom_string **result)
  1208. {
  1209.         assert(node->owner != NULL);
  1210.  
  1211.         /* If there is a namespace, increase its reference count */
  1212.         if (node->namespace != NULL)
  1213.                 *result = dom_string_ref(node->namespace);
  1214.         else
  1215.                 *result = NULL;
  1216.  
  1217.         return DOM_NO_ERR;
  1218. }
  1219.  
  1220. /**
  1221.  * Retrieve the prefix of a DOM node
  1222.  *
  1223.  * \param node    The node to retrieve the prefix of
  1224.  * \param result  Pointer to location to receive node's prefix
  1225.  * \return DOM_NO_ERR.
  1226.  *
  1227.  * The returned string will have its reference count increased. It is
  1228.  * the responsibility of the caller to unref the string once it has
  1229.  * finished with it.
  1230.  */
  1231. dom_exception _dom_node_get_prefix(dom_node_internal *node,
  1232.                 dom_string **result)
  1233. {
  1234.         assert(node->owner != NULL);
  1235.        
  1236.         /* If there is a prefix, increase its reference count */
  1237.         if (node->prefix != NULL)
  1238.                 *result = dom_string_ref(node->prefix);
  1239.         else
  1240.                 *result = NULL;
  1241.  
  1242.         return DOM_NO_ERR;
  1243. }
  1244.  
  1245. /**
  1246.  * Set the prefix of a DOM node
  1247.  *
  1248.  * \param node    The node to set the prefix of
  1249.  * \param prefix  Pointer to prefix string
  1250.  * \return DOM_NO_ERR                      on success,
  1251.  *         DOM_INVALID_CHARACTER_ERR       if the specified prefix contains
  1252.  *                                         an illegal character,
  1253.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly,
  1254.  *         DOM_NAMESPACE_ERR               if the specified prefix is
  1255.  *                                         malformed, if the namespaceURI of
  1256.  *                                         ::node is null, if the specified
  1257.  *                                         prefix is "xml" and the
  1258.  *                                         namespaceURI is different from
  1259.  *                                         "http://www.w3.org/XML/1998/namespace",
  1260.  *                                         if ::node is an attribute and the
  1261.  *                                         specified prefix is "xmlns" and
  1262.  *                                         the namespaceURI is different from
  1263.  *                                         "http://www.w3.org/2000/xmlns",
  1264.  *                                         or if this node is an attribute
  1265.  *                                         and the qualifiedName of ::node
  1266.  *                                         is "xmlns".
  1267.  */
  1268. dom_exception _dom_node_set_prefix(dom_node_internal *node,
  1269.                 dom_string *prefix)
  1270. {
  1271.         /* Only Element and Attribute nodes created using
  1272.          * namespace-aware methods may have a prefix */
  1273.         if ((node->type != DOM_ELEMENT_NODE &&
  1274.                         node->type != DOM_ATTRIBUTE_NODE) ||
  1275.                         node->namespace == NULL) {
  1276.                 return DOM_NO_ERR;
  1277.         }
  1278.  
  1279.         /** \todo validate prefix */
  1280.  
  1281.         /* Ensure node is writable */
  1282.         if (_dom_node_readonly(node)) {
  1283.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  1284.         }
  1285.  
  1286.         /* No longer want existing prefix */
  1287.         if (node->prefix != NULL) {
  1288.                 dom_string_unref(node->prefix);
  1289.         }
  1290.  
  1291.         /* Set the prefix */
  1292.         if (prefix != NULL) {
  1293.                 /* Empty string is treated as NULL */
  1294.                 if (dom_string_length(prefix) == 0) {
  1295.                         node->prefix = NULL;
  1296.                 } else {
  1297.                         node->prefix = dom_string_ref(prefix);
  1298.                 }
  1299.         } else {
  1300.                 node->prefix = NULL;
  1301.         }
  1302.  
  1303.         return DOM_NO_ERR;
  1304. }
  1305.  
  1306. /**
  1307.  * Retrieve the local part of a node's qualified name
  1308.  *
  1309.  * \param node    The node to retrieve the local name of
  1310.  * \param result  Pointer to location to receive local name
  1311.  * \return DOM_NO_ERR.
  1312.  *
  1313.  * The returned string will have its reference count increased. It is
  1314.  * the responsibility of the caller to unref the string once it has
  1315.  * finished with it.
  1316.  */
  1317. dom_exception _dom_node_get_local_name(dom_node_internal *node,
  1318.                 dom_string **result)
  1319. {      
  1320.         assert(node->owner != NULL);
  1321.        
  1322.         /* Only Element and Attribute nodes may have a local name */
  1323.         if (node->type != DOM_ELEMENT_NODE &&
  1324.                         node->type != DOM_ATTRIBUTE_NODE) {
  1325.                 *result = NULL;
  1326.                 return DOM_NO_ERR;
  1327.         }
  1328.  
  1329.         /* The node may have a local name, reference it if so */
  1330.         if (node->name != NULL)
  1331.                 *result = dom_string_ref(node->name);
  1332.         else
  1333.                 *result = NULL;
  1334.  
  1335.         return DOM_NO_ERR;
  1336. }
  1337.  
  1338. /**
  1339.  * Determine if a node has any attributes
  1340.  *
  1341.  * \param node    Node to inspect
  1342.  * \param result  Pointer to location to receive result
  1343.  * \return DOM_NO_ERR.
  1344.  */
  1345. dom_exception _dom_node_has_attributes(dom_node_internal *node, bool *result)
  1346. {
  1347.         UNUSED(node);
  1348.         *result = false;
  1349.  
  1350.         return DOM_NO_ERR;
  1351. }
  1352.  
  1353. /**
  1354.  * Retrieve the base URI of a DOM node
  1355.  *
  1356.  * \param node    The node to retrieve the base URI of
  1357.  * \param result  Pointer to location to receive base URI
  1358.  * \return DOM_NO_ERR.
  1359.  *
  1360.  * The returned string will have its reference count increased. It is
  1361.  * the responsibility of the caller to unref the string once it has
  1362.  * finished with it.
  1363.  *
  1364.  * We don't support this API now, so this function call should always
  1365.  * return DOM_NOT_SUPPORTED_ERR.
  1366.  */
  1367. dom_exception _dom_node_get_base(dom_node_internal *node,
  1368.                 dom_string **result)
  1369. {
  1370.         struct dom_document *doc = node->owner;
  1371.         assert(doc != NULL);
  1372.  
  1373.         return dom_document_get_base(doc, result);
  1374. }
  1375.  
  1376. /**
  1377.  * Compare the positions of two nodes in a DOM tree
  1378.  *
  1379.  * \param node   The reference node
  1380.  * \param other  The node to compare
  1381.  * \param result Pointer to location to receive result
  1382.  * \return DOM_NO_ERR            on success,
  1383.  *         DOM_NOT_SUPPORTED_ERR when the nodes are from different DOM
  1384.  *                               implementations.
  1385.  *
  1386.  * The result is a bitfield of dom_document_position values.
  1387.  *
  1388.  * We don't support this API now, so this function call should always
  1389.  * return DOM_NOT_SUPPORTED_ERR.
  1390.  */
  1391. dom_exception _dom_node_compare_document_position(dom_node_internal *node,
  1392.                 dom_node_internal *other, uint16_t *result)
  1393. {
  1394.         UNUSED(node);
  1395.         UNUSED(other);
  1396.         UNUSED(result);
  1397.  
  1398.         return DOM_NOT_SUPPORTED_ERR;
  1399. }
  1400.  
  1401. /**
  1402.  * Retrieve the text content of a DOM node
  1403.  *
  1404.  * \param node    The node to retrieve the text content of
  1405.  * \param result  Pointer to location to receive text content
  1406.  * \return DOM_NO_ERR.
  1407.  *
  1408.  * The returned string will have its reference count increased. It is
  1409.  * the responsibility of the caller to unref the string once it has
  1410.  * finished with it.
  1411.  *
  1412.  * If there is no text content in the code, NULL will returned in \a result.
  1413.  *
  1414.  * DOM3Core states that this can raise DOMSTRING_SIZE_ERR. It will not in
  1415.  * this implementation; dom_strings are unbounded.
  1416.  */
  1417. dom_exception _dom_node_get_text_content(dom_node_internal *node,
  1418.                 dom_string **result)
  1419. {
  1420.         dom_node_internal *n;
  1421.         dom_string *str = NULL;
  1422.         dom_string *ret = NULL;
  1423.  
  1424.         assert(node->owner != NULL);
  1425.        
  1426.         for (n = node->first_child; n != NULL; n = n->next) {
  1427.                 if (n->type == DOM_COMMENT_NODE ||
  1428.                     n->type == DOM_PROCESSING_INSTRUCTION_NODE)
  1429.                         continue;
  1430.                 dom_node_get_text_content(n, (str == NULL) ? &str : &ret);
  1431.                 if (ret != NULL) {
  1432.                         dom_string *new_str;
  1433.                         dom_string_concat(str, ret, &new_str);
  1434.                         dom_string_unref(str);
  1435.                         dom_string_unref(ret);
  1436.                         str = new_str;
  1437.                 }
  1438.         }
  1439.        
  1440.         *result = str;
  1441.  
  1442.         return DOM_NO_ERR;
  1443. }
  1444.  
  1445. /**
  1446.  * Set the text content of a DOM node
  1447.  *
  1448.  * \param node     The node to set the text content of
  1449.  * \param content  New text content for node
  1450.  * \return DOM_NO_ERR                      on success,
  1451.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly.
  1452.  *
  1453.  * Any child nodes ::node may have are removed and replaced with a single
  1454.  * Text node containing the new content.
  1455.  */
  1456. dom_exception _dom_node_set_text_content(dom_node_internal *node,
  1457.                 dom_string *content)
  1458. {
  1459.         dom_node_internal *n, *p, *r;
  1460.         dom_document *doc;
  1461.         dom_text *text;
  1462.         dom_exception err;
  1463.  
  1464.         n = node->first_child;
  1465.  
  1466.         while (n != NULL) {
  1467.                 p = n;
  1468.                 n = n->next;
  1469.                 /* Add the (void *) casting to avoid gcc warning:
  1470.                  * dereferencing type-punned pointer will break
  1471.                  * strict-aliasing rules */
  1472.                 err = dom_node_remove_child(node, p, (void *) &r);
  1473.                 if (err != DOM_NO_ERR)
  1474.                         return err;
  1475.         }
  1476.  
  1477.         doc = node->owner;
  1478.         assert(doc != NULL);
  1479.  
  1480.         err = dom_document_create_text_node(doc, content, &text);
  1481.         if (err != DOM_NO_ERR)
  1482.                 return err;
  1483.        
  1484.         err = dom_node_append_child(node, text, (void *) &r);
  1485.         if (err != DOM_NO_ERR)
  1486.                 return err;
  1487.  
  1488.         return DOM_NO_ERR;
  1489. }
  1490.  
  1491. /**
  1492.  * Determine if two DOM nodes are the same
  1493.  *
  1494.  * \param node    The node to compare
  1495.  * \param other   The node to compare against
  1496.  * \param result  Pointer to location to receive result
  1497.  * \return DOM_NO_ERR.
  1498.  *
  1499.  * This tests if the two nodes reference the same object.
  1500.  */
  1501. dom_exception _dom_node_is_same(dom_node_internal *node,
  1502.                 dom_node_internal *other, bool *result)
  1503. {
  1504.         *result = (node == other);
  1505.  
  1506.         return DOM_NO_ERR;
  1507. }
  1508.  
  1509. /**
  1510.  * Lookup the prefix associated with the given namespace URI
  1511.  *
  1512.  * \param node       The node to start prefix search from
  1513.  * \param namespace  The namespace URI
  1514.  * \param result     Pointer to location to receive result
  1515.  * \return DOM_NO_ERR.
  1516.  *
  1517.  * The returned string will have its reference count increased. It is
  1518.  * the responsibility of the caller to unref the string once it has
  1519.  * finished with it.
  1520.  */
  1521. dom_exception _dom_node_lookup_prefix(dom_node_internal *node,
  1522.                 dom_string *namespace, dom_string **result)
  1523. {
  1524.         if (node->parent != NULL)
  1525.                 return dom_node_lookup_prefix(node, namespace, result);
  1526.         else
  1527.                 *result = NULL;
  1528.  
  1529.         return DOM_NO_ERR;
  1530. }
  1531.  
  1532. /**
  1533.  * Determine if the specified namespace is the default namespace
  1534.  *
  1535.  * \param node       The node to query
  1536.  * \param namespace  The namespace URI to test
  1537.  * \param result     Pointer to location to receive result
  1538.  * \return DOM_NO_ERR.
  1539.  */
  1540. dom_exception _dom_node_is_default_namespace(dom_node_internal *node,
  1541.                 dom_string *namespace, bool *result)
  1542. {
  1543.         if (node->parent != NULL)
  1544.                 return dom_node_is_default_namespace(node, namespace, result);
  1545.         else
  1546.                 *result = false;
  1547.         return DOM_NO_ERR;
  1548. }
  1549.  
  1550. /**
  1551.  * Lookup the namespace URI associated with the given prefix
  1552.  *
  1553.  * \param node    The node to start namespace search from
  1554.  * \param prefix  The prefix to look for, or NULL to find default.
  1555.  * \param result  Pointer to location to receive result
  1556.  * \return DOM_NO_ERR.
  1557.  *
  1558.  * The returned string will have its reference count increased. It is
  1559.  * the responsibility of the caller to unref the string once it has
  1560.  * finished with it.
  1561.  */
  1562. dom_exception _dom_node_lookup_namespace(dom_node_internal *node,
  1563.                 dom_string *prefix, dom_string **result)
  1564. {
  1565.         if (node->parent != NULL)
  1566.                 return dom_node_lookup_namespace(node->parent, prefix, result);
  1567.         else
  1568.                 *result = NULL;
  1569.  
  1570.         return DOM_NO_ERR;
  1571. }
  1572.  
  1573. /**
  1574.  * Determine if two DOM nodes are equal
  1575.  *
  1576.  * \param node    The node to compare
  1577.  * \param other   The node to compare against
  1578.  * \param result  Pointer to location to receive result
  1579.  * \return DOM_NO_ERR.
  1580.  *
  1581.  * Two nodes are equal iff:
  1582.  *   + They are of the same type
  1583.  *   + nodeName, localName, namespaceURI, prefix, nodeValue are equal
  1584.  *   + The node attributes are equal
  1585.  *   + The child nodes are equal
  1586.  *
  1587.  * Two DocumentType nodes are equal iff:
  1588.  *   + publicId, systemId, internalSubset are equal
  1589.  *   + The node entities are equal
  1590.  *   + The node notations are equal
  1591.  * TODO: in document_type, we should override this virtual function
  1592.  */
  1593. dom_exception _dom_node_is_equal(dom_node_internal *node,
  1594.                 dom_node_internal *other, bool *result)
  1595. {
  1596.         dom_exception err;
  1597.         dom_string *s1, *s2;
  1598.         dom_namednodemap *m1, *m2;
  1599.         dom_nodelist *l1, *l2;
  1600.  
  1601.         if (node->type != other->type){
  1602.                 *result = false;
  1603.                 return DOM_NO_ERR;
  1604.         }
  1605.  
  1606.         assert(node->owner != NULL);
  1607.         assert(other->owner != NULL);
  1608.  
  1609.         err = dom_node_get_node_name(node, &s1);
  1610.         if (err != DOM_NO_ERR)
  1611.                 return err;
  1612.  
  1613.         err = dom_node_get_node_name(other, &s2);
  1614.         if (err != DOM_NO_ERR)
  1615.                 return err;
  1616.  
  1617.         if (dom_string_isequal(s1, s2) == false) {
  1618.                 *result = false;
  1619.                 return DOM_NO_ERR;
  1620.         }
  1621.        
  1622.         if (node->name != other->name ||
  1623.                         node->namespace != other->namespace ||
  1624.                         node->prefix != other->prefix) {
  1625.                 *result = false;
  1626.                 return DOM_NO_ERR;
  1627.         }
  1628.  
  1629.         if (dom_string_isequal(node->value, other->value) == false) {
  1630.                 *result = false;
  1631.                 return DOM_NO_ERR;
  1632.         }
  1633.  
  1634.         // Following comes the attributes
  1635.         err = dom_node_get_attributes(node, &m1);
  1636.         if (err != DOM_NO_ERR)
  1637.                 return err;
  1638.        
  1639.         err = dom_node_get_attributes(other, &m2);
  1640.         if (err != DOM_NO_ERR)
  1641.                 return err;
  1642.  
  1643.         if (dom_namednodemap_equal(m1, m2) != true) {
  1644.                 *result = false;
  1645.                 return DOM_NO_ERR;
  1646.         }
  1647.  
  1648.         // Finally the childNodes
  1649.         err = dom_node_get_child_nodes(node, &l1);
  1650.         if (err != DOM_NO_ERR)
  1651.                 return err;
  1652.  
  1653.         err = dom_node_get_child_nodes(other, &l2);
  1654.         if (err != DOM_NO_ERR)
  1655.                 return err;
  1656.  
  1657.         if (dom_nodelist_equal(l1, l2) != true) {
  1658.                 *result = false;
  1659.                 return DOM_NO_ERR;
  1660.         }
  1661.  
  1662.         *result = true;
  1663.  
  1664.         return DOM_NO_ERR;
  1665. }
  1666.  
  1667. /**
  1668.  * Retrieve an object which implements the specialized APIs of the specified
  1669.  * feature and version.
  1670.  *
  1671.  * \param node     The node to query
  1672.  * \param feature  The requested feature
  1673.  * \param version  The version number of the feature
  1674.  * \param result   Pointer to location to receive result
  1675.  * \return DOM_NO_ERR.
  1676.  */
  1677. dom_exception _dom_node_get_feature(dom_node_internal *node,
  1678.                 dom_string *feature, dom_string *version,
  1679.                 void **result)
  1680. {
  1681.         bool has;
  1682.  
  1683.         dom_implementation_has_feature(dom_string_data(feature),
  1684.                         dom_string_data(version), &has);
  1685.  
  1686.         if (has) {
  1687.                 *result = node;
  1688.         } else {
  1689.                 *result = NULL;
  1690.         }
  1691.  
  1692.         return DOM_NO_ERR;
  1693. }
  1694.  
  1695. /**
  1696.  * Associate an object to a key on this node
  1697.  *
  1698.  * \param node     The node to insert object into
  1699.  * \param key      The key associated with the object
  1700.  * \param data     The object to associate with key, or NULL to remove
  1701.  * \param handler  User handler function, or NULL if none
  1702.  * \param result   Pointer to location to receive previously associated object
  1703.  * \return DOM_NO_ERR.
  1704.  */
  1705. dom_exception _dom_node_set_user_data(dom_node_internal *node,
  1706.                 dom_string *key, void *data,
  1707.                 dom_user_data_handler handler, void **result)
  1708. {
  1709.         struct dom_user_data *ud = NULL;
  1710.         void *prevdata = NULL;
  1711.  
  1712.         /* Search for user data */
  1713.         for (ud = node->user_data; ud != NULL; ud = ud->next) {
  1714.                 if (dom_string_isequal(ud->key, key))
  1715.                         break;
  1716.         };
  1717.  
  1718.         /* Remove it, if found and no new data */
  1719.         if (data == NULL && ud != NULL) {
  1720.                 dom_string_unref(ud->key);
  1721.  
  1722.                 if (ud->next != NULL)
  1723.                         ud->next->prev = ud->prev;
  1724.                 if (ud->prev != NULL)
  1725.                         ud->prev->next = ud->next;
  1726.                 else
  1727.                         node->user_data = ud->next;
  1728.  
  1729.                 *result = ud->data;
  1730.  
  1731.                 free(ud);
  1732.  
  1733.                 return DOM_NO_ERR;
  1734.         }
  1735.  
  1736.         /* Otherwise, create a new user data object if one wasn't found */
  1737.         if (ud == NULL) {
  1738.                 ud = malloc(sizeof(struct dom_user_data));
  1739.                 if (ud == NULL)
  1740.                         return DOM_NO_MEM_ERR;
  1741.  
  1742.                 dom_string_ref(key);
  1743.                 ud->key = key;
  1744.                 ud->data = NULL;
  1745.                 ud->handler = NULL;
  1746.  
  1747.                 /* Insert into list */
  1748.                 ud->prev = NULL;
  1749.                 ud->next = node->user_data;
  1750.                 if (node->user_data)
  1751.                         node->user_data->prev = ud;
  1752.                 node->user_data = ud;
  1753.         }
  1754.  
  1755.         prevdata = ud->data;
  1756.  
  1757.         /* And associate data with it */
  1758.         ud->data = data;
  1759.         ud->handler = handler;
  1760.  
  1761.         *result = prevdata;
  1762.  
  1763.         return DOM_NO_ERR;
  1764. }
  1765.  
  1766. /**
  1767.  * Retrieves the object associated to a key on this node
  1768.  *
  1769.  * \param node    The node to retrieve object from
  1770.  * \param key     The key to search for
  1771.  * \param result  Pointer to location to receive result
  1772.  * \return DOM_NO_ERR.
  1773.  */
  1774. dom_exception _dom_node_get_user_data(dom_node_internal *node,
  1775.                 dom_string *key, void **result)
  1776. {
  1777.         struct dom_user_data *ud = NULL;
  1778.  
  1779.         /* Search for user data */
  1780.         for (ud = node->user_data; ud != NULL; ud = ud->next) {
  1781.                 if (dom_string_isequal(ud->key, key))
  1782.                         break;
  1783.         };
  1784.  
  1785.         if (ud != NULL)
  1786.                 *result = ud->data;
  1787.         else
  1788.                 *result = NULL;
  1789.  
  1790.         return DOM_NO_ERR;
  1791. }
  1792.  
  1793.  
  1794. /*--------------------------------------------------------------------------*/
  1795.  
  1796. /* The protected virtual functions */
  1797.  
  1798. /* Copy the internal attributes of a Node from old to new */
  1799. dom_exception _dom_node_copy(dom_node_internal *old, dom_node_internal **copy)
  1800. {
  1801.         dom_node_internal *new_node;
  1802.         dom_exception err;
  1803.  
  1804.         new_node = malloc(sizeof(dom_node_internal));
  1805.         if (new_node == NULL)
  1806.                 return DOM_NO_MEM_ERR;
  1807.  
  1808.         err = _dom_node_copy_internal(old, new_node);
  1809.         if (err != DOM_NO_ERR) {
  1810.                 free(new_node);
  1811.                 return err;
  1812.         }
  1813.  
  1814.         *copy = new_node;
  1815.  
  1816.         return DOM_NO_ERR;
  1817. }
  1818.  
  1819. dom_exception _dom_node_copy_internal(dom_node_internal *old,
  1820.                 dom_node_internal *new)
  1821. {
  1822.         new->base.vtable = old->base.vtable;
  1823.         new->vtable = old->vtable;
  1824.  
  1825.         new->name = dom_string_ref(old->name);
  1826.  
  1827.         /* Value - see below */
  1828.  
  1829.         new->type = old->type;
  1830.         new->parent = NULL;
  1831.         new->first_child = NULL;
  1832.         new->last_child = NULL;
  1833.         new->previous = NULL;
  1834.         new->next = NULL;
  1835.  
  1836.         assert(old->owner != NULL);
  1837.  
  1838.         new->owner = old->owner;
  1839.  
  1840.         if (old->namespace != NULL)
  1841.                 new->namespace = dom_string_ref(old->namespace);
  1842.         else
  1843.                 new->namespace = NULL;
  1844.  
  1845.         if (old->prefix != NULL)
  1846.                 new->prefix = dom_string_ref(old->prefix);
  1847.         else
  1848.                 new->prefix = NULL;
  1849.  
  1850.         new->user_data = NULL;
  1851.         new->base.refcnt = 1;
  1852.  
  1853.         list_init(&new->pending_list);
  1854.  
  1855.         /* Value */    
  1856.         if (old->value != NULL) {
  1857.                 dom_string_ref(old->value);
  1858.  
  1859.                 new->value = old->value;
  1860.         } else {
  1861.                 new->value = NULL;
  1862.         }
  1863.        
  1864.         /* The new copyed node has no parent,
  1865.          * so it should be put in the pending list. */
  1866.         dom_node_mark_pending(new);
  1867.  
  1868.         /* Intialise the EventTarget interface */
  1869.         return _dom_event_target_internal_initialise(&new->eti);
  1870. }
  1871.  
  1872.  
  1873. /*--------------------------------------------------------------------------*/
  1874.  
  1875. /*  The helper functions */
  1876.  
  1877. /**
  1878.  * Determine if a node is permitted as a child of another node
  1879.  *
  1880.  * \param parent  Prospective parent
  1881.  * \param child   Prospective child
  1882.  * \return true if ::child is permitted as a child of ::parent, false otherwise.
  1883.  */
  1884. bool _dom_node_permitted_child(const dom_node_internal *parent,
  1885.                 const dom_node_internal *child)
  1886. {
  1887.         bool valid = false;
  1888.  
  1889.         /* See DOM3Core $1.1.1 for details */
  1890.  
  1891.         switch (parent->type) {
  1892.         case DOM_ELEMENT_NODE:
  1893.         case DOM_ENTITY_REFERENCE_NODE:
  1894.         case DOM_ENTITY_NODE:
  1895.         case DOM_DOCUMENT_FRAGMENT_NODE:
  1896.                 valid = (child->type == DOM_ELEMENT_NODE ||
  1897.                          child->type == DOM_TEXT_NODE ||
  1898.                          child->type == DOM_COMMENT_NODE ||
  1899.                          child->type == DOM_PROCESSING_INSTRUCTION_NODE ||
  1900.                          child->type == DOM_CDATA_SECTION_NODE ||
  1901.                          child->type == DOM_ENTITY_REFERENCE_NODE);
  1902.                 break;
  1903.  
  1904.         case DOM_ATTRIBUTE_NODE:
  1905.                 valid = (child->type == DOM_TEXT_NODE ||
  1906.                          child->type == DOM_ENTITY_REFERENCE_NODE);
  1907.                 break;
  1908.  
  1909.         case DOM_TEXT_NODE:
  1910.         case DOM_CDATA_SECTION_NODE:
  1911.         case DOM_PROCESSING_INSTRUCTION_NODE:
  1912.         case DOM_COMMENT_NODE:
  1913.         case DOM_DOCUMENT_TYPE_NODE:
  1914.         case DOM_NOTATION_NODE:
  1915.                 valid = false;
  1916.                 break;
  1917.  
  1918.         case DOM_DOCUMENT_NODE:
  1919.                 valid = (child->type == DOM_ELEMENT_NODE ||
  1920.                          child->type == DOM_PROCESSING_INSTRUCTION_NODE ||
  1921.                          child->type == DOM_COMMENT_NODE ||
  1922.                          child->type == DOM_DOCUMENT_TYPE_NODE);
  1923.  
  1924.                 /* Ensure that the document doesn't already
  1925.                  * have a root element */
  1926.                 if (child->type == DOM_ELEMENT_NODE) {
  1927.                         dom_node_internal *n;
  1928.                         for (n = parent->first_child;
  1929.                                         n != NULL; n = n->next) {
  1930.                                 if (n->type == DOM_ELEMENT_NODE)
  1931.                                         valid = false;
  1932.                         }
  1933.                 }
  1934.  
  1935.                 /* Ensure that the document doesn't already
  1936.                  * have a document type */
  1937.                 if (child->type == DOM_DOCUMENT_TYPE_NODE) {
  1938.                         dom_node_internal *n;
  1939.                         for (n = parent->first_child;
  1940.                                         n != NULL; n = n->next) {
  1941.                                 if (n->type == DOM_DOCUMENT_TYPE_NODE)
  1942.                                         valid = false;
  1943.                         }
  1944.                 }
  1945.  
  1946.                 break;
  1947.         }
  1948.  
  1949.         return valid;
  1950. }
  1951.  
  1952. /**
  1953.  * Determine if a node is read only
  1954.  *
  1955.  * \param node  The node to consider
  1956.  */
  1957. bool _dom_node_readonly(const dom_node_internal *node)
  1958. {
  1959.         const dom_node_internal *n = node;
  1960.  
  1961.         /* DocumentType and Notation ns are read only */
  1962.         if (n->type == DOM_DOCUMENT_TYPE_NODE ||
  1963.                         n->type == DOM_NOTATION_NODE)
  1964.                 return true;
  1965.        
  1966.         /* Some Attr node are readonly */
  1967.         if (n->type == DOM_ATTRIBUTE_NODE)
  1968.                 return _dom_attr_readonly((const dom_attr *) n);
  1969.  
  1970.         /* Entity ns and their descendants are read only
  1971.          * EntityReference ns and their descendants are read only */
  1972.         for (n = node; n != NULL; n = n->parent) {
  1973.                 if (n->type == DOM_ENTITY_NODE
  1974.                                 || n->type == DOM_ENTITY_REFERENCE_NODE)
  1975.                         return true;
  1976.         }
  1977.  
  1978.         /* Otherwise, it's writable */
  1979.         return false;
  1980. }
  1981.  
  1982. /**
  1983.  * Attach a node to the tree
  1984.  *
  1985.  * \param node      The node to attach
  1986.  * \param parent    Node to attach ::node as child of
  1987.  * \param previous  Previous node in sibling list, or NULL if none
  1988.  * \param next      Next node in sibling list, or NULL if none
  1989.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  1990.  */
  1991. dom_exception _dom_node_attach(dom_node_internal *node,
  1992.                 dom_node_internal *parent, dom_node_internal *previous,
  1993.                 dom_node_internal *next)
  1994. {
  1995.         return _dom_node_attach_range(node, node, parent, previous, next);
  1996. }
  1997.  
  1998. /**
  1999.  * Detach a node from the tree
  2000.  *
  2001.  * \param node  The node to detach
  2002.  */
  2003. void _dom_node_detach(dom_node_internal *node)
  2004. {
  2005.         /* When a Node is not in the document tree, it must be in the
  2006.          * pending list */
  2007.         dom_node_mark_pending(node);
  2008.  
  2009.         _dom_node_detach_range(node, node);
  2010. }
  2011.  
  2012. /**
  2013.  * Attach a range of nodes to the tree
  2014.  *
  2015.  * \param first     First node in the range
  2016.  * \param last      Last node in the range
  2017.  * \param parent    Node to attach range to
  2018.  * \param previous  Previous node in sibling list, or NULL if none
  2019.  * \param next      Next node in sibling list, or NULL if none
  2020.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  2021.  *
  2022.  * The range is assumed to be a linked list of sibling nodes.
  2023.  */
  2024. dom_exception _dom_node_attach_range(dom_node_internal *first,
  2025.                 dom_node_internal *last,
  2026.                 dom_node_internal *parent,
  2027.                 dom_node_internal *previous,
  2028.                 dom_node_internal *next)
  2029. {
  2030.         dom_exception err;
  2031.         bool success = true;
  2032.         dom_node_internal *n;
  2033.  
  2034.         first->previous = previous;
  2035.         last->next = next;
  2036.  
  2037.         if (previous != NULL)
  2038.                 previous->next = first;
  2039.         else
  2040.                 parent->first_child = first;
  2041.  
  2042.         if (next != NULL)
  2043.                 next->previous = last;
  2044.         else
  2045.                 parent->last_child = last;
  2046.  
  2047.         for (n = first; n != last->next; n = n->next) {
  2048.                 n->parent = parent;
  2049.                 /* Dispatch a DOMNodeInserted event */
  2050.                 err = dom_node_dispatch_node_change_event(parent->owner,
  2051.                                 n, parent, DOM_MUTATION_ADDITION, &success);
  2052.                 if (err != DOM_NO_ERR)
  2053.                         return err;
  2054.         }
  2055.  
  2056.         success = true;
  2057.         err = _dom_dispatch_subtree_modified_event(parent->owner, parent,
  2058.                         &success);
  2059.         if (err != DOM_NO_ERR)
  2060.                 return err;
  2061.  
  2062.         return DOM_NO_ERR;
  2063. }
  2064.  
  2065. /**
  2066.  * Detach a range of nodes from the tree
  2067.  *
  2068.  * \param first  The first node in the range
  2069.  * \param last   The last node in the range
  2070.  *
  2071.  * The range is assumed to be a linked list of sibling nodes.
  2072.  */
  2073. void _dom_node_detach_range(dom_node_internal *first,
  2074.                 dom_node_internal *last)
  2075. {
  2076.         bool success = true;
  2077.         dom_node_internal *parent;
  2078.         dom_node_internal *n;
  2079.  
  2080.         if (first->previous != NULL)
  2081.                 first->previous->next = last->next;
  2082.         else
  2083.                 first->parent->first_child = last->next;
  2084.  
  2085.         if (last->next != NULL)
  2086.                 last->next->previous = first->previous;
  2087.         else
  2088.                 last->parent->last_child = first->previous;
  2089.  
  2090.         parent = first->parent;
  2091.         for (n = first; n != last->next; n = n->next) {
  2092.                 /* Dispatch a DOMNodeRemoval event */
  2093.                 dom_node_dispatch_node_change_event(n->owner, n, n->parent,
  2094.                                 DOM_MUTATION_REMOVAL, &success);
  2095.  
  2096.                 n->parent = NULL;
  2097.         }
  2098.  
  2099.         success = true;
  2100.         _dom_dispatch_subtree_modified_event(parent->owner, parent,
  2101.                         &success);
  2102.  
  2103.         first->previous = NULL;
  2104.         last->next = NULL;
  2105. }
  2106.  
  2107. /**
  2108.  * Replace a node in the tree
  2109.  *
  2110.  * \param old          Node to replace
  2111.  * \param replacement  Replacement node
  2112.  *
  2113.  * This is not implemented in terms of attach/detach in case
  2114.  * we want to perform any special replacement-related behaviour
  2115.  * at a later date.
  2116.  */
  2117. void _dom_node_replace(dom_node_internal *old,
  2118.                 dom_node_internal *replacement)
  2119. {
  2120.         dom_node_internal *first, *last;
  2121.         dom_node_internal *n;
  2122.  
  2123.         if (replacement->type == DOM_DOCUMENT_FRAGMENT_NODE) {
  2124.                 first = replacement->first_child;
  2125.                 last = replacement->last_child;
  2126.  
  2127.                 replacement->first_child = replacement->last_child = NULL;
  2128.         } else {
  2129.                 first = replacement;
  2130.                 last = replacement;
  2131.         }
  2132.  
  2133.         first->previous = old->previous;
  2134.         last->next = old->next;
  2135.  
  2136.         if (old->previous != NULL)
  2137.                 old->previous->next = first;
  2138.         else
  2139.                 old->parent->first_child = first;
  2140.  
  2141.         if (old->next != NULL)
  2142.                 old->next->previous = last;
  2143.         else
  2144.                 old->parent->last_child = last;
  2145.  
  2146.         for (n = first; n != last->next; n = n->next) {
  2147.                 n->parent = old->parent;
  2148.         }
  2149.  
  2150.         old->previous = old->next = old->parent = NULL;
  2151. }
  2152.  
  2153. /**
  2154.  * Merge two adjacent text nodes into one text node.
  2155.  *
  2156.  * \param p  The first text node
  2157.  * \param n  The second text node
  2158.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  2159.  */
  2160. dom_exception _dom_merge_adjacent_text(dom_node_internal *p,
  2161.                 dom_node_internal *n)
  2162. {
  2163.         dom_string *str;
  2164.         dom_exception err;
  2165.  
  2166.         assert(p->type = DOM_TEXT_NODE);
  2167.         assert(n->type = DOM_TEXT_NODE);
  2168.  
  2169.         err = dom_text_get_whole_text(n, &str);
  2170.         if (err != DOM_NO_ERR)
  2171.                 return err;
  2172.        
  2173.         err = dom_characterdata_append_data(p, str);
  2174.         if (err != DOM_NO_ERR)
  2175.                 return err;
  2176.  
  2177.         dom_string_unref(str);
  2178.  
  2179.         return DOM_NO_ERR;
  2180. }
  2181.  
  2182. /**
  2183.  * Try to destroy this node.
  2184.  *
  2185.  * \param node  The node to destroy
  2186.  *
  2187.  * When some node owns this node, (such as an elment owns its attribute nodes)
  2188.  * when this node being not owned, the owner should call this function to try
  2189.  * to destroy this node.
  2190.  *
  2191.  * @note: Owning a node does not means this node's refcnt is above zero.
  2192.  */
  2193. dom_exception _dom_node_try_destroy(dom_node_internal *node)
  2194. {
  2195.         if (node == NULL)
  2196.                 return DOM_NO_ERR;
  2197.  
  2198.         if (node->parent == NULL) {
  2199.                 if (node->base.refcnt == 0) {
  2200.                         dom_node_destroy(node);
  2201.                 } else if (node->pending_list.prev == &node->pending_list){
  2202.                         assert (node->pending_list.next == &node->pending_list);
  2203.                         list_append(&node->owner->pending_nodes,
  2204.                                         &node->pending_list);
  2205.                 }
  2206.         }
  2207.        
  2208.         return DOM_NO_ERR;
  2209. }
  2210.  
  2211. /**
  2212.  * To add some node to the pending list, when a node is removed from its parent
  2213.  * or an attribute is removed from its element
  2214.  *
  2215.  * \param node  The Node instance
  2216.  */
  2217. void _dom_node_mark_pending(dom_node_internal *node)
  2218. {
  2219.         struct dom_document *doc = node->owner;
  2220.  
  2221.         /* TODO: the pending_list is located at in dom_document, but some
  2222.          * nodes can be created without a document created, such as a
  2223.          * dom_document_type node. For this reason, we should test whether
  2224.          * the doc is NULL. */
  2225.         if (doc != NULL) {
  2226.                 /* The node must not be in the pending list */
  2227.                 assert(node->pending_list.prev == &node->pending_list);
  2228.  
  2229.                 list_append(&doc->pending_nodes, &node->pending_list);
  2230.         }
  2231. }
  2232.  
  2233. /**
  2234.  * To remove the node from the pending list, this may happen when
  2235.  * a node is removed and then appended to another parent
  2236.  *
  2237.  * \param node  The Node instance
  2238.  */
  2239. void _dom_node_remove_pending(dom_node_internal *node)
  2240. {
  2241.         struct dom_document *doc = node->owner;
  2242.  
  2243.         if (doc != NULL) {
  2244.                 /* The node must be in the pending list */
  2245.                 assert(node->pending_list.prev != &node->pending_list);
  2246.  
  2247.                 list_del(&node->pending_list);
  2248.         }
  2249. }
  2250.  
  2251. /******************************************************************************
  2252.  * Event Target API                                                           *
  2253.  ******************************************************************************/
  2254.  
  2255. dom_exception _dom_node_add_event_listener(dom_event_target *et,
  2256.                 dom_string *type, struct dom_event_listener *listener,
  2257.                 bool capture)
  2258. {
  2259.         dom_node_internal *node = (dom_node_internal *) et;
  2260.  
  2261.         return _dom_event_target_add_event_listener(&node->eti, type,
  2262.                         listener, capture);
  2263. }
  2264.  
  2265. dom_exception _dom_node_remove_event_listener(dom_event_target *et,
  2266.                 dom_string *type, struct dom_event_listener *listener,
  2267.                 bool capture)
  2268. {
  2269.         dom_node_internal *node = (dom_node_internal *) et;
  2270.  
  2271.         return _dom_event_target_remove_event_listener(&node->eti,
  2272.                         type, listener, capture);
  2273. }
  2274.  
  2275. dom_exception _dom_node_add_event_listener_ns(dom_event_target *et,
  2276.                 dom_string *namespace, dom_string *type,
  2277.                 struct dom_event_listener *listener, bool capture)
  2278. {
  2279.         dom_node_internal *node = (dom_node_internal *) et;
  2280.  
  2281.         return _dom_event_target_add_event_listener_ns(&node->eti,
  2282.                         namespace, type, listener, capture);
  2283. }
  2284.  
  2285. dom_exception _dom_node_remove_event_listener_ns(dom_event_target *et,
  2286.                 dom_string *namespace, dom_string *type,
  2287.                 struct dom_event_listener *listener, bool capture)
  2288. {
  2289.         dom_node_internal *node = (dom_node_internal *) et;
  2290.  
  2291.         return _dom_event_target_remove_event_listener_ns(&node->eti,
  2292.                         namespace, type, listener, capture);
  2293. }
  2294.  
  2295. /**
  2296.  * Dispatch an event into the implementation's event model
  2297.  *
  2298.  * \param et       The EventTarget object
  2299.  * \param eti      Internal EventTarget
  2300.  * \param evt      The event object
  2301.  * \param success  Indicates whether any of the listeners which handled the
  2302.  *                 event called Event.preventDefault(). If
  2303.  *                 Event.preventDefault() was called the returned value is
  2304.  *                 false, else it is true.
  2305.  * \return DOM_NO_ERR                     on success
  2306.  *         DOM_DISPATCH_REQUEST_ERR       If the event is already in dispatch
  2307.  *         DOM_UNSPECIFIED_EVENT_TYPE_ERR If the type of the event is Null or
  2308.  *                                        empty string.
  2309.  *         DOM_NOT_SUPPORTED_ERR          If the event is not created by
  2310.  *                                        Document.createEvent
  2311.  *         DOM_INVALID_CHARACTER_ERR      If the type of this event is not a
  2312.  *                                        valid NCName.
  2313.  */
  2314. dom_exception _dom_node_dispatch_event(dom_event_target *et,
  2315.                 struct dom_event *evt, bool *success)
  2316. {
  2317.         dom_exception err, ret = DOM_NO_ERR;
  2318.         dom_node_internal *target = (dom_node_internal *) et;
  2319.         dom_document *doc;
  2320.         dom_document_event_internal *dei;
  2321.         dom_event_target **targets;
  2322.         uint32_t ntargets, ntargets_allocated, targetnr;
  2323.         void *pw;
  2324.  
  2325.         assert(et != NULL);
  2326.         assert(evt != NULL);
  2327.  
  2328.         /* To test whether this event is in dispatch */
  2329.         if (evt->in_dispatch == true) {
  2330.                 return DOM_DISPATCH_REQUEST_ERR;
  2331.         } else {
  2332.                 evt->in_dispatch = true;
  2333.         }
  2334.  
  2335.         if (evt->type == NULL || dom_string_byte_length(evt->type) == 0) {
  2336.                 return DOM_UNSPECIFIED_EVENT_TYPE_ERR;
  2337.         }
  2338.  
  2339.         if (evt->doc == NULL)
  2340.                 return DOM_NOT_SUPPORTED_ERR;
  2341.        
  2342.         doc = dom_node_get_owner(et);
  2343.         if (doc == NULL) {
  2344.                 /* TODO: In the progress of parsing, many Nodes in the DTD has
  2345.                  * no document at all, do nothing for this kind of node */
  2346.                 return DOM_NO_ERR;
  2347.         }
  2348.        
  2349.         *success = true;
  2350.  
  2351.         /* Compose the event target list */
  2352.         ntargets = 0;
  2353.         ntargets_allocated = 64;
  2354.         targets = calloc(sizeof(*targets), ntargets_allocated);
  2355.         if (targets == NULL) {
  2356.                 /** \todo Report memory exhaustion? */
  2357.                 return DOM_NO_ERR;
  2358.         }
  2359.         targets[ntargets++] = (dom_event_target *)dom_node_ref(et);
  2360.         target = target->parent;
  2361.  
  2362.         while (target != NULL) {
  2363.                 if (ntargets == ntargets_allocated) {
  2364.                         dom_event_target **newtargets = realloc(
  2365.                                 targets,
  2366.                                 ntargets_allocated * 2 * sizeof(*targets));
  2367.                         if (newtargets == NULL)
  2368.                                 goto cleanup;
  2369.                         memset(newtargets + ntargets_allocated,
  2370.                                0, ntargets_allocated * sizeof(*newtargets));
  2371.                         targets = newtargets;
  2372.                         ntargets_allocated *= 2;
  2373.                 }
  2374.                 targets[ntargets++] = (dom_event_target *)dom_node_ref(target);
  2375.                 target = target->parent;
  2376.         }
  2377.  
  2378.         /* Fill the target of the event */
  2379.         evt->target = et;
  2380.         evt->phase = DOM_CAPTURING_PHASE;
  2381.  
  2382.         /* The started callback of default action */
  2383.         dei = &doc->dei;
  2384.         pw = dei->actions_ctx;
  2385.         if (dei->actions != NULL) {
  2386.                 dom_default_action_callback cb = dei->actions(evt->type,
  2387.                                 DOM_DEFAULT_ACTION_STARTED, &pw);
  2388.                 if (cb != NULL) {
  2389.                         cb(evt, pw);
  2390.                 }
  2391.         }
  2392.  
  2393.         /* The capture phase */
  2394.         for (targetnr = ntargets; targetnr > 0; --targetnr) {
  2395.                 dom_node_internal *node =
  2396.                         (dom_node_internal *) targets[targetnr - 1];
  2397.  
  2398.                 err = _dom_event_target_dispatch(targets[targetnr - 1],
  2399.                                 &node->eti, evt, DOM_CAPTURING_PHASE, success);
  2400.                 if (err != DOM_NO_ERR) {
  2401.                         ret = err;
  2402.                         goto cleanup;
  2403.                 }
  2404.                 /* If the stopImmediatePropagation or stopPropagation is
  2405.                  * called, we should break */
  2406.                 if (evt->stop_now == true || evt->stop == true)
  2407.                         goto cleanup;
  2408.         }
  2409.  
  2410.         /* Target phase */
  2411.         evt->phase = DOM_AT_TARGET;
  2412.         evt->current = et;
  2413.         err = _dom_event_target_dispatch(et, &((dom_node_internal *) et)->eti,
  2414.                         evt, DOM_AT_TARGET, success);
  2415.         if (err != DOM_NO_ERR) {
  2416.                 ret = err;
  2417.                 goto cleanup;
  2418.         }
  2419.         if (evt->stop_now == true || evt->stop == true)
  2420.                 goto cleanup;
  2421.  
  2422.         /* Bubbling phase */
  2423.         evt->phase = DOM_BUBBLING_PHASE;
  2424.  
  2425.         for (targetnr = 0; targetnr < ntargets; ++targetnr) {
  2426.                 dom_node_internal *node =
  2427.                         (dom_node_internal *) targets[targetnr];
  2428.                 err = _dom_event_target_dispatch(targets[targetnr],
  2429.                                 &node->eti, evt, DOM_BUBBLING_PHASE, success);
  2430.                 if (err != DOM_NO_ERR) {
  2431.                         ret = err;
  2432.                         goto cleanup;
  2433.                 }
  2434.                 /* If the stopImmediatePropagation or stopPropagation is
  2435.                  * called, we should break */
  2436.                 if (evt->stop_now == true || evt->stop == true)
  2437.                         goto cleanup;
  2438.         }
  2439.  
  2440.         if (dei->actions == NULL)
  2441.                 goto cleanup;
  2442.  
  2443.         /* The end callback of default action */
  2444.         if (evt->prevent_default != true) {
  2445.                 dom_default_action_callback cb = dei->actions(evt->type,
  2446.                                 DOM_DEFAULT_ACTION_END, &pw);
  2447.                 if (cb != NULL) {
  2448.                         cb(evt, pw);
  2449.                 }
  2450.         }
  2451.  
  2452.         /* The prevented callback of default action */
  2453.         if (evt->prevent_default != true) {
  2454.                 dom_default_action_callback cb = dei->actions(evt->type,
  2455.                                 DOM_DEFAULT_ACTION_PREVENTED, &pw);
  2456.                 if (cb != NULL) {
  2457.                         cb(evt, pw);
  2458.                 }
  2459.         }
  2460.  
  2461. cleanup:
  2462.         if (evt->prevent_default == true) {
  2463.                 *success = false;
  2464.         }
  2465.  
  2466.         while (ntargets--) {
  2467.                 dom_node_unref(targets[ntargets]);
  2468.         }
  2469.         free(targets);
  2470.  
  2471.         return ret;
  2472. }
  2473.  
  2474. dom_exception _dom_node_dispatch_node_change_event(dom_document *doc,
  2475.                 dom_node_internal *node, dom_node_internal *related,
  2476.                 dom_mutation_type change, bool *success)
  2477. {
  2478.         dom_node_internal *target;
  2479.         dom_exception err;
  2480.  
  2481.         /* Fire change event at immediate target */
  2482.         err = _dom_dispatch_node_change_event(doc, node, related,
  2483.                         change, success);
  2484.         if (err != DOM_NO_ERR)
  2485.                 return err;
  2486.  
  2487.         /* Fire document change event at subtree */
  2488.         target = node->first_child;
  2489.         while (target != NULL) {
  2490.                 err = _dom_dispatch_node_change_document_event(doc, target,
  2491.                                 change, success);
  2492.                 if (err != DOM_NO_ERR)
  2493.                         return err;
  2494.  
  2495.                 if (target->first_child != NULL) {
  2496.                         target = target->first_child;
  2497.                 } else if (target->next != NULL) {
  2498.                         target = target->next;
  2499.                 } else {
  2500.                         dom_node_internal *parent = target->parent;
  2501.  
  2502.                         while (parent != node && target == parent->last_child) {
  2503.                                 target = parent;
  2504.                                 parent = target->parent;
  2505.                         }
  2506.  
  2507.                         target = target->next;
  2508.                 }
  2509.         }
  2510.  
  2511.         return DOM_NO_ERR;
  2512. }
  2513.  
  2514.