diff options
Diffstat (limited to 'src')
91 files changed, 1396 insertions, 240 deletions
diff --git a/src/core/Makefile b/src/core/Makefile index 41fd51f..5d9c969 100644 --- a/src/core/Makefile +++ b/src/core/Makefile @@ -6,6 +6,6 @@ DIR_SOURCES := \ text.c typeinfo.c comment.c \ namednodemap.c nodelist.c \ cdatasection.c document_type.c entity_ref.c pi.c \ - doc_fragment.c document.c + doc_fragment.c document.c tokenlist.c include $(NSBUILD)/Makefile.subdir diff --git a/src/core/attr.c b/src/core/attr.c index e18e2a7..8fcaac3 100644 --- a/src/core/attr.c +++ b/src/core/attr.c @@ -49,7 +49,7 @@ struct dom_attr { }; /* The vtable for dom_attr node */ -static struct dom_attr_vtable attr_vtable = { +static const struct dom_attr_vtable attr_vtable = { { { DOM_NODE_EVENT_TARGET_VTABLE, @@ -60,7 +60,7 @@ static struct dom_attr_vtable attr_vtable = { }; /* The protected vtable for dom_attr */ -static struct dom_node_protect_vtable attr_protect_vtable = { +static const struct dom_node_protect_vtable attr_protect_vtable = { DOM_ATTR_PROTECT_VTABLE }; diff --git a/src/core/cdatasection.c b/src/core/cdatasection.c index c6812e3..efba237 100644 --- a/src/core/cdatasection.c +++ b/src/core/cdatasection.c @@ -20,7 +20,7 @@ struct dom_cdata_section { dom_text base; /**< Base node */ }; -static struct dom_node_protect_vtable cdata_section_protect_vtable = { +static const struct dom_node_protect_vtable cdata_section_protect_vtable = { DOM_CDATA_SECTION_PROTECT_VTABLE }; diff --git a/src/core/characterdata.c b/src/core/characterdata.c index ea665b3..e6f5dbe 100644 --- a/src/core/characterdata.c +++ b/src/core/characterdata.c @@ -21,7 +21,7 @@ /* The virtual functions for dom_characterdata, we make this vtable * public to each child class */ -struct dom_characterdata_vtable characterdata_vtable = { +const struct dom_characterdata_vtable characterdata_vtable = { { { DOM_NODE_EVENT_TARGET_VTABLE diff --git a/src/core/characterdata.h b/src/core/characterdata.h index 0b0889c..c8f4db3 100644 --- a/src/core/characterdata.h +++ b/src/core/characterdata.h @@ -116,7 +116,7 @@ dom_exception _dom_characterdata_copy(dom_node_internal *old, _dom_characterdata_destroy, \ _dom_characterdata_copy -extern struct dom_characterdata_vtable characterdata_vtable; +extern const struct dom_characterdata_vtable characterdata_vtable; dom_exception _dom_characterdata_copy_internal(dom_characterdata *old, dom_characterdata *new); diff --git a/src/core/comment.c b/src/core/comment.c index 0697826..b36a1be 100644 --- a/src/core/comment.c +++ b/src/core/comment.c @@ -21,7 +21,7 @@ struct dom_comment { dom_characterdata base; /**< Base node */ }; -static struct dom_node_protect_vtable comment_protect_vtable = { +static const struct dom_node_protect_vtable comment_protect_vtable = { DOM_COMMENT_PROTECT_VTABLE }; diff --git a/src/core/doc_fragment.c b/src/core/doc_fragment.c index 96cc707..9e10a1a 100644 --- a/src/core/doc_fragment.c +++ b/src/core/doc_fragment.c @@ -22,14 +22,14 @@ struct dom_document_fragment { dom_node_internal base; /**< Base node */ }; -static struct dom_node_vtable df_vtable = { +static const struct dom_node_vtable df_vtable = { { DOM_NODE_EVENT_TARGET_VTABLE }, DOM_NODE_VTABLE }; -static struct dom_node_protect_vtable df_protect_vtable = { +static const struct dom_node_protect_vtable df_protect_vtable = { DOM_DF_PROTECT_VTABLE }; diff --git a/src/core/document.c b/src/core/document.c index 7c0bcdc..40d4cd9 100644 --- a/src/core/document.c +++ b/src/core/document.c @@ -42,7 +42,7 @@ struct dom_doc_nl { }; /* The virtual functions of this dom_document */ -static struct dom_document_vtable document_vtable = { +static const struct dom_document_vtable document_vtable = { { { DOM_NODE_EVENT_TARGET_VTABLE @@ -52,7 +52,7 @@ static struct dom_document_vtable document_vtable = { DOM_DOCUMENT_VTABLE }; -static struct dom_node_protect_vtable document_protect_vtable = { +static const struct dom_node_protect_vtable document_protect_vtable = { DOM_DOCUMENT_PROTECT_VTABLE }; diff --git a/src/core/document_type.c b/src/core/document_type.c index d7b1b99..a0fafdd 100644 --- a/src/core/document_type.c +++ b/src/core/document_type.c @@ -27,7 +27,7 @@ struct dom_document_type { dom_string *system_id; /**< Doctype system ID */ }; -static struct dom_document_type_vtable document_type_vtable = { +static const struct dom_document_type_vtable document_type_vtable = { { { DOM_NODE_EVENT_TARGET_VTABLE @@ -37,7 +37,7 @@ static struct dom_document_type_vtable document_type_vtable = { DOM_DOCUMENT_TYPE_VTABLE }; -static struct dom_node_protect_vtable dt_protect_vtable = { +static const struct dom_node_protect_vtable dt_protect_vtable = { DOM_DT_PROTECT_VTABLE }; diff --git a/src/core/element.c b/src/core/element.c index 771226b..05dc8c6 100644 --- a/src/core/element.c +++ b/src/core/element.c @@ -32,7 +32,7 @@ #include "utils/list.h" #include "events/mutation_event.h" -struct dom_element_vtable _dom_element_vtable = { +const struct dom_element_vtable _dom_element_vtable = { { { DOM_NODE_EVENT_TARGET_VTABLE @@ -42,7 +42,7 @@ struct dom_element_vtable _dom_element_vtable = { DOM_ELEMENT_VTABLE }; -static struct dom_element_protected_vtable element_protect_vtable = { +static const struct dom_element_protected_vtable element_protect_vtable = { { DOM_NODE_PROTECT_VTABLE_ELEMENT }, @@ -1232,9 +1232,11 @@ dom_exception _dom_element_has_class(struct dom_element *element, /** * Get a named ancestor node * + * The caller is responsible for unreffing the returned node. + * * \param element Element to consider * \param name Node name to look for - * \param ancestor Pointer to location to receive node pointer + * \param ancestor Pointer to location to receive node. * \return DOM_NO_ERR. */ dom_exception dom_element_named_ancestor_node(dom_element *element, @@ -1251,7 +1253,7 @@ dom_exception dom_element_named_ancestor_node(dom_element *element, assert(node->name != NULL); if (dom_string_caseless_lwc_isequal(node->name, name)) { - *ancestor = (dom_element *)node; + *ancestor = (dom_element *)dom_node_ref(node); break; } } @@ -1262,6 +1264,8 @@ dom_exception dom_element_named_ancestor_node(dom_element *element, /** * Get a named parent node * + * The caller is responsible for unreffing the returned node. + * * \param element Element to consider * \param name Node name to look for * \param parent Pointer to location to receive node pointer @@ -1281,7 +1285,7 @@ dom_exception dom_element_named_parent_node(dom_element *element, assert(node->name != NULL); if (dom_string_caseless_lwc_isequal(node->name, name)) { - *parent = (dom_element *)node; + *parent = (dom_element *)dom_node_ref(node); } break; } @@ -1292,6 +1296,8 @@ dom_exception dom_element_named_parent_node(dom_element *element, /** * Get a named parent node * + * The caller is responsible for unreffing the returned node. + * * \param element Element to consider * \param name Node name to look for * \param parent Pointer to location to receive node pointer @@ -1308,7 +1314,7 @@ dom_exception dom_element_parent_node(dom_element *element, if (node->type != DOM_ELEMENT_NODE) continue; - *parent = (dom_element *)node; + *parent = (dom_element *)dom_node_ref(node); break; } @@ -1414,7 +1420,12 @@ dom_exception _dom_element_is_default_namespace(dom_node_internal *node, return DOM_NO_ERR; } - return dom_node_is_default_namespace(node->parent, namespace, result); + if (node->parent != NULL) { + return dom_node_is_default_namespace(node->parent, namespace, result); + } else { + *result = false; + } + return DOM_NO_ERR; } /** diff --git a/src/core/element.h b/src/core/element.h index c89ddc0..fb946b7 100644 --- a/src/core/element.h +++ b/src/core/element.h @@ -238,6 +238,6 @@ dom_exception _dom_element_copy_internal(dom_element *old, dom_exception _dom_element_get_id(struct dom_element *ele, dom_string **id); -extern struct dom_element_vtable _dom_element_vtable; +extern const struct dom_element_vtable _dom_element_vtable; #endif diff --git a/src/core/entity_ref.c b/src/core/entity_ref.c index aa32111..bc6fbab 100644 --- a/src/core/entity_ref.c +++ b/src/core/entity_ref.c @@ -20,14 +20,14 @@ struct dom_entity_reference { dom_node_internal base; /**< Base node */ }; -static struct dom_node_vtable er_vtable = { +static const struct dom_node_vtable er_vtable = { { DOM_NODE_EVENT_TARGET_VTABLE }, DOM_NODE_VTABLE }; -static struct dom_node_protect_vtable er_protect_vtable = { +static const struct dom_node_protect_vtable er_protect_vtable = { DOM_ER_PROTECT_VTABLE }; diff --git a/src/core/node.c b/src/core/node.c index 87ad837..1218742 100644 --- a/src/core/node.c +++ b/src/core/node.c @@ -55,14 +55,14 @@ static inline dom_exception _dom_node_detach_range(dom_node_internal *first, static inline void _dom_node_replace(dom_node_internal *old, dom_node_internal *replacement); -static struct dom_node_vtable node_vtable = { +static const struct dom_node_vtable node_vtable = { { DOM_NODE_EVENT_TARGET_VTABLE }, DOM_NODE_VTABLE }; -static struct dom_node_protect_vtable node_protect_vtable = { +static const struct dom_node_protect_vtable node_protect_vtable = { DOM_NODE_PROTECT_VTABLE }; @@ -1827,8 +1827,8 @@ dom_exception _dom_node_set_user_data(dom_node_internal *node, * \param result Pointer to location to receive result * \return DOM_NO_ERR. */ -dom_exception _dom_node_get_user_data(dom_node_internal *node, - dom_string *key, void **result) +dom_exception _dom_node_get_user_data(const dom_node_internal *node, + const dom_string *key, void **result) { struct dom_user_data *ud = NULL; @@ -2172,7 +2172,9 @@ dom_exception _dom_node_detach_range(dom_node_internal *first, * * This is not implemented in terms of attach/detach in case * we want to perform any special replacement-related behaviour - * at a later date. + * at a later date. If the replacement is essentially empty (either NULL + * or an empty document fragment node) then this essentially just removes + * the old node from its parent. It is up to the caller to deal with that. */ void _dom_node_replace(dom_node_internal *old, dom_node_internal *replacement) @@ -2190,6 +2192,19 @@ void _dom_node_replace(dom_node_internal *old, last = replacement; } + if (first == NULL) { + /* All we're doing is removing old */ + if (old->previous == NULL) { + old->parent->first_child = old->next; + } + if (old->next == NULL) { + old->parent->last_child = old->previous; + } + old->previous = old->next = old->parent = NULL; + return; + } + + /* We're replacing old with first-to-last */ first->previous = old->previous; last->next = old->next; @@ -2203,7 +2218,7 @@ void _dom_node_replace(dom_node_internal *old, else old->parent->last_child = last; - for (n = first; n != last->next; n = n->next) { + for (n = first; n != NULL && n != last->next; n = n->next) { n->parent = old->parent; } diff --git a/src/core/node.h b/src/core/node.h index 87f3cb3..36cdd7d 100644 --- a/src/core/node.h +++ b/src/core/node.h @@ -53,7 +53,7 @@ typedef struct dom_node_protect_vtable { */ struct dom_node_internal { struct dom_node base; /**< The vtable base */ - void *vtable; /**< The protected vtable */ + const void *vtable; /**< The protected vtable */ dom_string *name; /**< Node name (this is the local part * of a QName in the cases where a @@ -182,8 +182,8 @@ dom_exception _dom_node_get_feature(dom_node_internal *node, dom_exception _dom_node_set_user_data(dom_node_internal *node, dom_string *key, void *data, dom_user_data_handler handler, void **result); -dom_exception _dom_node_get_user_data(dom_node_internal *node, - dom_string *key, void **result); +dom_exception _dom_node_get_user_data(const dom_node_internal *node, + const dom_string *key, void **result); #define DOM_NODE_EVENT_TARGET_VTABLE \ _dom_node_add_event_listener, \ diff --git a/src/core/pi.c b/src/core/pi.c index d12f109..3e69841 100644 --- a/src/core/pi.c +++ b/src/core/pi.c @@ -20,14 +20,14 @@ struct dom_processing_instruction { dom_node_internal base; /**< Base node */ }; -static struct dom_node_vtable pi_vtable = { +static const struct dom_node_vtable pi_vtable = { { DOM_NODE_EVENT_TARGET_VTABLE }, DOM_NODE_VTABLE }; -static struct dom_node_protect_vtable pi_protect_vtable = { +static const struct dom_node_protect_vtable pi_protect_vtable = { DOM_PI_PROTECT_VTABLE }; /** diff --git a/src/core/text.c b/src/core/text.c index b73e86d..f63fabe 100644 --- a/src/core/text.c +++ b/src/core/text.c @@ -20,7 +20,7 @@ #include "utils/utils.h" /* The virtual table for dom_text */ -struct dom_text_vtable text_vtable = { +const struct dom_text_vtable text_vtable = { { { { @@ -33,7 +33,7 @@ struct dom_text_vtable text_vtable = { DOM_TEXT_VTABLE }; -static struct dom_node_protect_vtable text_protect_vtable = { +static const struct dom_node_protect_vtable text_protect_vtable = { DOM_TEXT_PROTECT_VTABLE }; diff --git a/src/core/text.h b/src/core/text.h index 26424ce..3f5739b 100644 --- a/src/core/text.h +++ b/src/core/text.h @@ -66,7 +66,7 @@ dom_exception _dom_text_copy(dom_node_internal *old, dom_node_internal **copy); __dom_text_destroy, \ _dom_text_copy -extern struct dom_text_vtable text_vtable; +extern const struct dom_text_vtable text_vtable; dom_exception _dom_text_copy_internal(dom_text *old, dom_text *new); #define dom_text_copy_internal(o, n) \ diff --git a/src/core/tokenlist.c b/src/core/tokenlist.c new file mode 100644 index 0000000..cc93a8c --- /dev/null +++ b/src/core/tokenlist.c @@ -0,0 +1,547 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2022 Daniel Silverstone <dsilvers@digital-scurf.org> + */ + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include <dom/core/element.h> +#include <dom/core/nodelist.h> +#include <dom/core/tokenlist.h> +#include <dom/core/string.h> +#include <dom/events/event.h> +#include <dom/events/event_target.h> +#include <dom/events/event_listener.h> +#include <dom/events/mutation_event.h> + +#include "core/element.h" +#include "core/document.h" + +#include "utils/utils.h" + +#define DOM_TOKENLIST_GROW_INCREMENT 4 + +struct dom_tokenlist { + uint32_t refcnt; + dom_element *ele; + dom_string *attr; + dom_event_listener *listener; + dom_string *last_set; + bool needs_parse; + /* Parsed content, for optimal access */ + dom_string **entries; + uint32_t len; + uint32_t alloc; +}; + +/* Handle a DOMAttrModified event which might be to do with our attribute */ + +static void _dom_tokenlist_handle_attrmodified(dom_event *evt, void *pw) +{ + dom_mutation_event *mutevt = (dom_mutation_event *)evt; + dom_tokenlist *list = (dom_tokenlist *)pw; + dom_exception exc; + dom_string *value; + + { + dom_event_target *target; + exc = dom_event_get_target(evt, &target); + if (exc != DOM_NO_ERR) + return; + dom_node_unref(target); + if (target != (dom_event_target *)list->ele) + return; + } + + { + dom_string *attr; + exc = dom_mutation_event_get_attr_name(mutevt, &attr); + if (exc != DOM_NO_ERR) + return; + if (!dom_string_isequal(attr, list->attr)) { + dom_string_unref(attr); + return; + } + dom_string_unref(attr); + } + + /* At this point we know that this is a mutation of our attribute on our + * node */ + + exc = dom_mutation_event_get_new_value(mutevt, &value); + if (exc != DOM_NO_ERR) + return; + + if (list->last_set != NULL && + dom_string_isequal(list->last_set, value)) { + /* We've just seen the mutation event for one of our own set + * operations */ + dom_string_unref(value); + return; + } + + /* Mark that we need to re-parse the tokenlist on the next request */ + list->needs_parse = true; + + dom_string_unref(value); +} + +static dom_exception _dom_tokenlist_make_room(dom_tokenlist *list) +{ + if (list->len == list->alloc) { + uint32_t new_alloc = list->alloc + DOM_TOKENLIST_GROW_INCREMENT; + dom_string **new_entries = realloc( + list->entries, new_alloc * sizeof(dom_string *)); + if (new_entries == NULL) + return DOM_NO_MEM_ERR; + list->alloc = new_alloc; + list->entries = new_entries; + } + + return DOM_NO_ERR; +} + +static dom_exception _dom_tokenlist_reparse(dom_tokenlist *list) +{ + dom_exception exc; + dom_string *value; + const char *pos; + uint32_t remaining, check; + uint32_t n_entries = 0; + dom_string *temp; + bool found; + + if (!list->needs_parse) + return DOM_NO_ERR; + + /* Clean down the current entries */ + while (list->len-- > 0) + dom_string_unref(list->entries[list->len]); + list->len = 0; + + /* Get the "new" attribute value */ + exc = dom_element_get_attribute(list->ele, list->attr, &value); + if (exc != DOM_NO_ERR) + return exc; + + /* If there is no value, we're an empty list and we're done */ + if (value == NULL) { + list->needs_parse = false; + return DOM_NO_ERR; + } + + /* OK, there's something here to do, so let's do it... */ + + /* Count number of entries */ + for (pos = dom_string_data(value), remaining = dom_string_length(value); + remaining > 0;) { + if (*pos != ' ') { + while (*pos != ' ' && remaining > 0) { + remaining--; + pos++; + } + n_entries++; + } else { + while (*pos == ' ' && remaining > 0) { + remaining--; + pos++; + } + } + } + + /* If there are no entries (all whitespace) just bail here */ + if (n_entries == 0) { + list->needs_parse = false; + dom_string_unref(value); + return DOM_NO_ERR; + } + + /* If we need more room, reallocate the buffer */ + if (list->alloc < n_entries) { + dom_string **new_alloc = realloc( + list->entries, n_entries * sizeof(dom_string *)); + if (new_alloc == NULL) { + dom_string_unref(value); + return DOM_NO_MEM_ERR; + } + list->entries = new_alloc; + list->alloc = n_entries; + } + + /* And now parse those entries into the buffer */ + for (pos = dom_string_data(value), + remaining = dom_string_length(value), + n_entries = 0; + remaining > 0;) { + if (*pos != ' ') { + const char *s = pos; + while (*pos != ' ' && remaining > 0) { + pos++; + remaining--; + } + exc = dom_string_create_interned((const uint8_t *)s, + pos - s, + &temp); + if (exc != DOM_NO_ERR) { + dom_string_unref(value); + return exc; + } + found = false; + for (check = 0; check < list->len; check++) { + if (dom_string_isequal(temp, + list->entries[check])) { + found = true; + break; + } + } + if (found == true) { + dom_string_unref(temp); + } else { + list->entries[list->len] = temp; + list->len++; + } + } else { + while (*pos == ' ' && remaining > 0) { + pos++; + remaining--; + } + } + } + + dom_string_unref(value); + list->needs_parse = false; + + return DOM_NO_ERR; +} + +static dom_exception _dom_tokenlist_reify(dom_tokenlist *list) +{ + dom_exception exc; + uint32_t nchars = 0, n; + char *buffer, *next; + dom_string *output; + + if (list->len == 0) { + if (list->last_set != NULL) { + dom_string_unref(list->last_set); + } + list->last_set = dom_string_ref( + list->ele->base.owner->_memo_empty); + return dom_element_set_attribute(list->ele, + list->attr, + list->last_set); + } + + for (n = 0; n < list->len; ++n) + nchars += dom_string_length(list->entries[n]); + + buffer = calloc(1, nchars + list->len); + if (buffer == NULL) + return DOM_NO_MEM_ERR; + + for (next = buffer, n = 0; n < list->len; ++n) { + uint32_t slen = dom_string_length(list->entries[n]); + memcpy(next, dom_string_data(list->entries[n]), slen); + next[slen] = ' '; + next += slen + 1; + } + + exc = dom_string_create_interned((const uint8_t *)buffer, + nchars + list->len - 1, + &output); + free(buffer); + if (exc != DOM_NO_ERR) + return exc; + + if (list->last_set != NULL) { + dom_string_unref(list->last_set); + } + list->last_set = output; + + return dom_element_set_attribute(list->ele, list->attr, list->last_set); +} + +/**********************************************************************************/ + +/** + * Create a tokenlist + * + * \param ele The element which owns the tokenlist attribute + * \param attr The name of the attribute we are treating as a tokenlist + * \param list The tokenlist output which is set on success + * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion + * + * The returned list will already be referenced, so the client need not + * do so explicitly. The client must unref the list once finished with it. + * + * This list will take its own references to ::ele and ::attr + */ +dom_exception +dom_tokenlist_create(dom_element *ele, dom_string *attr, dom_tokenlist **list) +{ + dom_tokenlist *l; + dom_exception exc; + + l = calloc(1, sizeof(dom_tokenlist)); + if (l == NULL) + return DOM_NO_MEM_ERR; + + l->refcnt = 1; + l->ele = (dom_element *)dom_node_ref(ele); + l->attr = dom_string_ref(attr); + l->needs_parse = true; + + exc = dom_event_listener_create(_dom_tokenlist_handle_attrmodified, + l, + &l->listener); + if (exc != DOM_NO_ERR) + goto fail; + + exc = dom_event_target_add_event_listener( + ele, + ele->base.owner->_memo_domattrmodified, + l->listener, + false); + + if (exc != DOM_NO_ERR) + goto fail; + + *list = l; + + return DOM_NO_ERR; + +fail: + if (l->listener != NULL) + dom_event_listener_unref(l->listener); + dom_node_unref(l->ele); + dom_string_unref(l->attr); + free(l); + return exc; +} + +/** + * Claim a ref on a tokenlist + * + * \param list The tokenlist to claim a ref on + */ +void dom_tokenlist_ref(dom_tokenlist *list) +{ + assert(list != NULL); + list->refcnt++; +} + +/** + * Release a ref on a tokenlist + * + * \param list The list to release the reference of + * + * If you release the last ref, this cleans up the tokenlist + */ +void dom_tokenlist_unref(dom_tokenlist *list) +{ + assert(list != NULL); + + if (--list->refcnt > 0) + return; + + if (list->alloc > 0) { + while (list->len-- > 0) + dom_string_unref(list->entries[list->len]); + free(list->entries); + } + + dom_event_target_remove_event_listener( + list->ele, + list->ele->base.owner->_memo_domattrmodified, + list->listener, + false); + + dom_event_listener_unref(list->listener); + + if (list->last_set != NULL) + dom_string_unref(list->last_set); + + dom_string_unref(list->attr); + dom_node_unref(list->ele); + + free(list); +} + +/** + * Get the length of the tokenlist + * + * \param list The list to get the length of + * \param length Length of the list outputs here + * \return DOM_NO_ERR on success, otherwise the failure code + */ +dom_exception dom_tokenlist_get_length(dom_tokenlist *list, uint32_t *length) +{ + dom_exception exc; + assert(list != NULL); + + exc = _dom_tokenlist_reparse(list); + if (exc != DOM_NO_ERR) + return exc; + + *length = list->len; + + return DOM_NO_ERR; +} + +/** + * Get a particular item from the tokenlist + * + * \param list The list to retrieve the item from + * \param index The index of the item to retrieve + * \param value The value of the item returns here + * \return DOM_NO_ERR on success, otherwise the failure code + */ +dom_exception +_dom_tokenlist_item(dom_tokenlist *list, uint32_t index, dom_string **value) +{ + dom_exception exc; + assert(list != NULL); + + exc = _dom_tokenlist_reparse(list); + if (exc != DOM_NO_ERR) + return exc; + + if (index >= list->len) { + *value = NULL; + return DOM_NO_ERR; + } + + *value = dom_string_ref(list->entries[index]); + return DOM_NO_ERR; +} + +/** + * Retrieve the value of the tokenlist as a string + * + * \param list The list to retrieve the value of + * \param value The value of the list returns here + * \return DOM_NO_ERR on success, otherwise the failure code + */ +dom_exception dom_tokenlist_get_value(dom_tokenlist *list, dom_string **value) +{ + assert(list != NULL); + + return dom_element_get_attribute(list->ele, list->attr, value); +} + +/** + * Set the value of the tokenlist as a string + * + * \param list The list to set the value of + * \param value The value to set + * \return DOM_NO_ERR on success, otherwise the failure code + * + */ +dom_exception dom_tokenlist_set_value(dom_tokenlist *list, dom_string *value) +{ + assert(list != NULL); + + return dom_element_set_attribute(list->ele, list->attr, value); +} + +/** + * Check if the given value is in the tokenlist + * + * \param list The list to scan for the given value + * \param value The value to look for in the token list + * \param contains This will be set based on whether or not the value is present + * \return DOM_NO_ERR on success, otherwise the failure code + */ +dom_exception +dom_tokenlist_contains(dom_tokenlist *list, dom_string *value, bool *contains) +{ + dom_exception exc; + uint32_t n; + + assert(list != NULL); + + exc = _dom_tokenlist_reparse(list); + if (exc != DOM_NO_ERR) + return exc; + + *contains = false; + + for (n = 0; n < list->len; n++) { + if (dom_string_isequal(value, list->entries[n])) { + *contains = true; + break; + } + } + + return DOM_NO_ERR; +} + +/** + * Add the given value to the tokenlist + * + * \param list The list to add to + * \param value The value to add + * \return DOM_NO_ERR on success, otherwise the failure code + */ +dom_exception dom_tokenlist_add(dom_tokenlist *list, dom_string *value) +{ + dom_exception exc; + bool present = false; + + assert(list != NULL); + + exc = dom_tokenlist_contains(list, value, &present); + if (exc != DOM_NO_ERR) + return exc; + + if (present == true) + return DOM_NO_ERR; + + exc = _dom_tokenlist_make_room(list); + if (exc != DOM_NO_ERR) + return exc; + + list->entries[list->len++] = dom_string_ref(value); + + exc = _dom_tokenlist_reify(list); + + return exc; +} + +/** + * Remove the given value from the tokenlist + * + * \param list The list to remove from + * \param value The value to remove + * \return DOM_NO_ERR on success, otherwise the failure code + */ +dom_exception dom_tokenlist_remove(dom_tokenlist *list, dom_string *value) +{ + dom_exception exc; + uint32_t n, m; + + assert(list != NULL); + + exc = _dom_tokenlist_reparse(list); + if (exc != DOM_NO_ERR) + return false; + + for (n = 0; n < list->len; ++n) { + if (dom_string_isequal(value, list->entries[n])) { + dom_string_unref(list->entries[n]); + for (m = n + 1; m < list->len; ++m) { + list->entries[m - 1] = list->entries[m]; + } + list->len--; + break; + } + } + + exc = _dom_tokenlist_reify(list); + + return exc; +} diff --git a/src/core/tokenlist.h b/src/core/tokenlist.h new file mode 100644 index 0000000..325d726 --- /dev/null +++ b/src/core/tokenlist.h @@ -0,0 +1,18 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org> + */ + +#ifndef dom_internal_core_tokenlist_h_ +#define dom_internal_core_tokenlist_h_ + +#include <stdbool.h> + +#include <dom/core/tokenlist.h> + +struct dom_element; +struct dom_string; + +#endif diff --git a/src/events/dispatch.c b/src/events/dispatch.c index 0e0048d..a8b8ad7 100644 --- a/src/events/dispatch.c +++ b/src/events/dispatch.c @@ -56,7 +56,7 @@ dom_exception __dom_dispatch_node_change_event(dom_document *doc, goto cleanup; cleanup: - _dom_mutation_event_destroy(evt); + dom_event_unref(evt); return err; } @@ -101,7 +101,7 @@ dom_exception __dom_dispatch_node_change_document_event(dom_document *doc, goto cleanup; cleanup: - _dom_mutation_event_destroy(evt); + dom_event_unref(evt); return err; } @@ -145,7 +145,7 @@ dom_exception __dom_dispatch_attr_modified_event(dom_document *doc, err = dom_event_target_dispatch_event(et, evt, success); cleanup: - _dom_mutation_event_destroy(evt); + dom_event_unref(evt); return err; } @@ -188,7 +188,7 @@ dom_exception __dom_dispatch_characterdata_modified_event( err = dom_event_target_dispatch_event(et, evt, success); cleanup: - _dom_mutation_event_destroy(evt); + dom_event_unref(evt); return err; } @@ -224,7 +224,7 @@ dom_exception __dom_dispatch_subtree_modified_event(dom_document *doc, err = dom_event_target_dispatch_event(et, evt, success); cleanup: - _dom_mutation_event_destroy(evt); + dom_event_unref(evt); return err; } @@ -263,7 +263,7 @@ dom_exception _dom_dispatch_generic_event(dom_document *doc, err = dom_event_target_dispatch_event(et, evt, success); cleanup: - _dom_event_destroy(evt); + dom_event_unref(evt); return err; } diff --git a/src/events/event.c b/src/events/event.c index 3fe9978..26b245e 100644 --- a/src/events/event.c +++ b/src/events/event.c @@ -18,7 +18,7 @@ static void _virtual_dom_event_destroy(dom_event *evt); -static struct dom_event_private_vtable _event_vtable = { +static const struct dom_event_private_vtable _event_vtable = { _virtual_dom_event_destroy }; diff --git a/src/events/event.h b/src/events/event.h index 857f20a..7cada7b 100644 --- a/src/events/event.h +++ b/src/events/event.h @@ -45,7 +45,7 @@ struct dom_event { uint32_t refcnt; /**< The reference count of this object */ - struct dom_event_private_vtable *vtable; + const struct dom_event_private_vtable *vtable; /**< The private virtual function table of Event */ bool in_dispatch; /**< Whether this event is in dispatch */ bool is_initialised; /**< Whether this event is initialised */ diff --git a/src/events/keyboard_event.c b/src/events/keyboard_event.c index fb29c18..d1fa1ca 100644 --- a/src/events/keyboard_event.c +++ b/src/events/keyboard_event.c @@ -15,14 +15,14 @@ static void _virtual_dom_keyboard_event_destroy(struct dom_event *evt); -static struct dom_event_private_vtable _event_vtable = { +static const struct dom_event_private_vtable _event_vtable = { _virtual_dom_keyboard_event_destroy }; /* Constructor */ dom_exception _dom_keyboard_event_create(struct dom_keyboard_event **evt) { - *evt = malloc(sizeof(dom_keyboard_event)); + *evt = calloc(1, sizeof(dom_keyboard_event)); if (*evt == NULL) return DOM_NO_MEM_ERR; @@ -42,8 +42,16 @@ void _dom_keyboard_event_destroy(struct dom_keyboard_event *evt) /* Initialise function */ dom_exception _dom_keyboard_event_initialise(struct dom_keyboard_event *evt) { - evt->key_ident = NULL; - evt->modifier_state = 0; + dom_exception err; + dom_string *empty_string; + + err = dom_string_create((const uint8_t *)"", 0, &empty_string); + if (err != DOM_NO_ERR) { + return err; + } + + evt->key = empty_string; + evt->code = dom_string_ref(empty_string); return _dom_ui_event_initialise(&evt->base); } @@ -51,6 +59,11 @@ dom_exception _dom_keyboard_event_initialise(struct dom_keyboard_event *evt) /* Finalise function */ void _dom_keyboard_event_finalise(struct dom_keyboard_event *evt) { + if (evt->key != NULL) + dom_string_unref(evt->key); + if (evt->code != NULL) + dom_string_unref(evt->code); + _dom_ui_event_finalise(&evt->base); } @@ -64,17 +77,31 @@ void _virtual_dom_keyboard_event_destroy(struct dom_event *evt) /* The public API */ /** - * Get the key identifier + * Get the key * * \param evt The Event object - * \param ident The returned key identifier + * \param key The returned key + * \return DOM_NO_ERR. + */ +dom_exception _dom_keyboard_event_get_key(dom_keyboard_event *evt, + dom_string **key) +{ + *key = dom_string_ref(evt->key); + + return DOM_NO_ERR; +} + +/** + * Get the code + * + * \param evt The Event object + * \param code The returned code * \return DOM_NO_ERR. */ -dom_exception _dom_keyboard_event_get_key_identifier(dom_keyboard_event *evt, - dom_string **ident) +dom_exception _dom_keyboard_event_get_code(dom_keyboard_event *evt, + dom_string **code) { - *ident = evt->key_ident; - dom_string_ref(*ident); + *code = dom_string_ref(evt->code); return DOM_NO_ERR; } @@ -83,13 +110,13 @@ dom_exception _dom_keyboard_event_get_key_identifier(dom_keyboard_event *evt, * Get the key location * * \param evt The Event object - * \param loc The returned key location + * \param location The returned key location * \return DOM_NO_ERR. */ -dom_exception _dom_keyboard_event_get_key_location(dom_keyboard_event *evt, - dom_key_location *loc) +dom_exception _dom_keyboard_event_get_location(dom_keyboard_event *evt, + dom_key_location *location) { - *loc = evt->key_loc; + *location = evt->location; return DOM_NO_ERR; } @@ -123,7 +150,7 @@ dom_exception _dom_keyboard_event_get_shift_key(dom_keyboard_event *evt, return DOM_NO_ERR; } - + /** * Get the alt key state * @@ -207,70 +234,147 @@ dom_exception _dom_keyboard_event_get_modifier_state(dom_keyboard_event *evt, } /** - * Initialise the keyboard event + * Helper to initialise the keyboard event * - * \param evt The Event object - * \param type The event's type - * \param bubble Whether this is a bubbling event - * \param cancelable Whether this is a cancelable event - * \param view The AbstractView associated with this event - * \param key_indent The key identifier of pressed key - * \param key_loc The key location of the preesed key - * \param modifier_list A string of modifier key identifiers, separated with - * space - * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + * \param evt The Event object + * \param view The AbstractView associated with this event + * \param key The key identifier of pressed key + * \param code The code identifier of pressed key + * \param location The key location of the preesed key + * \param ctrl_key Whether the ctrl_key is pressed + * \param shift_key Whether the shift_key is pressed + * \param alt_key Whether the alt_key is pressed + * \param meta_key Whether the ctrl_key is pressed + * \param repeat Whether this is a repeat press from a held key + * \param is_composing Whether the input is being composed */ -dom_exception _dom_keyboard_event_init(dom_keyboard_event *evt, - dom_string *type, bool bubble, bool cancelable, - struct dom_abstract_view *view, dom_string *key_ident, - dom_key_location key_loc, dom_string *modifier_list) +static void _dom_keyboard_event_init_helper( + dom_keyboard_event *evt, + dom_string *key, + dom_string *code, + dom_key_location location, + bool ctrl_key, + bool shift_key, + bool alt_key, + bool meta_key, + bool repeat, + bool is_composing) { - dom_exception err; + if (key != NULL) { + dom_string_unref(evt->key); + evt->key = dom_string_ref(key); + } + if (code != NULL) { + dom_string_unref(evt->code); + evt->code = dom_string_ref(code); + } - evt->key_ident = key_ident; - dom_string_ref(evt->key_ident); - evt->key_loc = key_loc; + evt->location = location; - err = _dom_parse_modifier_list(modifier_list, &evt->modifier_state); - if (err != DOM_NO_ERR) - return err; + if (ctrl_key) { + evt->modifier_state |= DOM_MOD_CTRL; + } + if (shift_key) { + evt->modifier_state |= DOM_MOD_CTRL; + } + if (alt_key) { + evt->modifier_state |= DOM_MOD_SHIFT; + } + if (meta_key) { + evt->modifier_state |= DOM_MOD_META; + } - return _dom_ui_event_init(&evt->base, type, bubble, cancelable, - view, 0); + evt->repeat = repeat; + evt->is_composing = is_composing; } + + /** * Initialise the keyboard event with namespace * - * \param evt The Event object - * \param namespace The namespace of this event - * \param type The event's type - * \param bubble Whether this is a bubbling event - * \param cancelable Whether this is a cancelable event - * \param view The AbstractView associated with this event - * \param key_indent The key identifier of pressed key - * \param key_loc The key location of the preesed key - * \param modifier_list A string of modifier key identifiers, separated with - * space + * \param evt The Event object + * \param type The event's type + * \param bubble Whether this is a bubbling event + * \param cancelable Whether this is a cancelable event + * \param view The AbstractView associated with this event + * \param key The key identifier of pressed key + * \param code The code identifier of pressed key + * \param location The key location of the preesed key + * \param ctrl_key Whether the ctrl_key is pressed + * \param shift_key Whether the shift_key is pressed + * \param alt_key Whether the alt_key is pressed + * \param meta_key Whether the ctrl_key is pressed + * \param repeat Whether this is a repeat press from a held key + * \param is_composing Whether the input is being composed * \return DOM_NO_ERR on success, appropriate dom_exception on failure. */ -dom_exception _dom_keyboard_event_init_ns(dom_keyboard_event *evt, - dom_string *namespace, dom_string *type, - bool bubble, bool cancelable, struct dom_abstract_view *view, - dom_string *key_ident, dom_key_location key_loc, - dom_string *modifier_list) +dom_exception _dom_keyboard_event_init( + dom_keyboard_event *evt, + dom_string *type, + bool bubble, + bool cancelable, + struct dom_abstract_view *view, + dom_string *key, + dom_string *code, + dom_key_location location, + bool ctrl_key, + bool shift_key, + bool alt_key, + bool meta_key, + bool repeat, + bool is_composing) { - dom_exception err; + _dom_keyboard_event_init_helper(evt, key, code, location, + ctrl_key, shift_key, alt_key, meta_key, + repeat, is_composing); - evt->key_ident = key_ident; - dom_string_ref(evt->key_ident); - evt->key_loc = key_loc; + return _dom_ui_event_init(&evt->base, type, bubble, cancelable, + view, 0); +} - err = _dom_parse_modifier_list(modifier_list, &evt->modifier_state); - if (err != DOM_NO_ERR) - return err; +/** + * Initialise the keyboard event with namespace + * + * \param evt The Event object + * \param namespace The namespace of this event + * \param type The event's type + * \param bubble Whether this is a bubbling event + * \param cancelable Whether this is a cancelable event + * \param view The AbstractView associated with this event + * \param key The key identifier of pressed key + * \param code The code identifier of pressed key + * \param location The key location of the preesed key + * \param ctrl_key Whether the ctrl_key is pressed + * \param shift_key Whether the shift_key is pressed + * \param alt_key Whether the alt_key is pressed + * \param meta_key Whether the ctrl_key is pressed + * \param repeat Whether this is a repeat press from a held key + * \param is_composing Whether the input is being composed + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_keyboard_event_init_ns( + dom_keyboard_event *evt, + dom_string *namespace, + dom_string *type, + bool bubble, + bool cancelable, + struct dom_abstract_view *view, + dom_string *key, + dom_string *code, + dom_key_location location, + bool ctrl_key, + bool shift_key, + bool alt_key, + bool meta_key, + bool repeat, + bool is_composing) +{ + _dom_keyboard_event_init_helper(evt, key, code, location, + ctrl_key, shift_key, alt_key, meta_key, + repeat, is_composing); - return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble, + return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble, cancelable, view, 0); } diff --git a/src/events/keyboard_event.h b/src/events/keyboard_event.h index d640bbb..81b702f 100644 --- a/src/events/keyboard_event.h +++ b/src/events/keyboard_event.h @@ -18,21 +18,15 @@ struct dom_keyboard_event { struct dom_ui_event base; /**< The base class */ - dom_string *key_ident; /**< The identifier of the key in this - * event, please refer: - * http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set - * for detail - */ - - dom_key_location key_loc; /**< Indicate the location of the key on - * the keyboard - */ + dom_string *key; + dom_string *code; + dom_key_location location; uint32_t modifier_state; /**< The modifier keys state */ -}; -/* Constructor */ -dom_exception _dom_keyboard_event_create(struct dom_keyboard_event **evt); + bool repeat; + bool is_composing; +}; /* Destructor */ void _dom_keyboard_event_destroy(struct dom_keyboard_event *evt); diff --git a/src/events/mouse_event.c b/src/events/mouse_event.c index b3b2154..ac1d142 100644 --- a/src/events/mouse_event.c +++ b/src/events/mouse_event.c @@ -15,7 +15,7 @@ static void _virtual_dom_mouse_event_destroy(struct dom_event *evt); -static struct dom_event_private_vtable _event_vtable = { +static const struct dom_event_private_vtable _event_vtable = { _virtual_dom_mouse_event_destroy }; diff --git a/src/events/mouse_multi_wheel_event.c b/src/events/mouse_multi_wheel_event.c index bcbe8d5..a42085a 100644 --- a/src/events/mouse_multi_wheel_event.c +++ b/src/events/mouse_multi_wheel_event.c @@ -16,7 +16,7 @@ static void _virtual_dom_mouse_multi_wheel_event_destroy( struct dom_event *evt); -static struct dom_event_private_vtable _event_vtable = { +static const struct dom_event_private_vtable _event_vtable = { _virtual_dom_mouse_multi_wheel_event_destroy }; diff --git a/src/events/mouse_wheel_event.c b/src/events/mouse_wheel_event.c index d59eab1..5d6bdd6 100644 --- a/src/events/mouse_wheel_event.c +++ b/src/events/mouse_wheel_event.c @@ -15,7 +15,7 @@ static void _virtual_dom_mouse_wheel_event_destroy(struct dom_event *evt); -static struct dom_event_private_vtable _event_vtable = { +static const struct dom_event_private_vtable _event_vtable = { _virtual_dom_mouse_wheel_event_destroy }; diff --git a/src/events/mutation_event.c b/src/events/mutation_event.c index df92c5f..2c5ffdc 100644 --- a/src/events/mutation_event.c +++ b/src/events/mutation_event.c @@ -11,7 +11,7 @@ static void _virtual_dom_mutation_event_destroy(struct dom_event *evt); -static struct dom_event_private_vtable _event_vtable = { +static const struct dom_event_private_vtable _event_vtable = { _virtual_dom_mutation_event_destroy }; diff --git a/src/events/mutation_name_event.c b/src/events/mutation_name_event.c index e0ba82e..13a51b5 100644 --- a/src/events/mutation_name_event.c +++ b/src/events/mutation_name_event.c @@ -14,7 +14,7 @@ static void _virtual_dom_mutation_name_event_destroy(struct dom_event *evt); -static struct dom_event_private_vtable _event_vtable = { +static const struct dom_event_private_vtable _event_vtable = { _virtual_dom_mutation_name_event_destroy }; diff --git a/src/events/text_event.c b/src/events/text_event.c index 3437716..d0d2706 100644 --- a/src/events/text_event.c +++ b/src/events/text_event.c @@ -12,7 +12,7 @@ static void _virtual_dom_text_event_destroy(struct dom_event *evt); -static struct dom_event_private_vtable _event_vtable = { +static const struct dom_event_private_vtable _event_vtable = { _virtual_dom_text_event_destroy }; diff --git a/src/events/ui_event.c b/src/events/ui_event.c index 4fac3b6..672f999 100644 --- a/src/events/ui_event.c +++ b/src/events/ui_event.c @@ -11,14 +11,14 @@ static void _virtual_dom_ui_event_destroy(struct dom_event *evt); -static struct dom_event_private_vtable _event_vtable = { +static const struct dom_event_private_vtable _event_vtable = { _virtual_dom_ui_event_destroy }; /* Constructor */ dom_exception _dom_ui_event_create(struct dom_ui_event **evt) { - *evt = malloc(sizeof(dom_ui_event)); + *evt = calloc(1, sizeof(dom_ui_event)); if (*evt == NULL) return DOM_NO_MEM_ERR; @@ -38,7 +38,6 @@ void _dom_ui_event_destroy(struct dom_ui_event *evt) /* Initialise function */ dom_exception _dom_ui_event_initialise(struct dom_ui_event *evt) { - evt->view = NULL; return _dom_event_initialise(&evt->base); } diff --git a/src/html/Makefile b/src/html/Makefile index c98ce9a..db765ad 100644 --- a/src/html/Makefile +++ b/src/html/Makefile @@ -1,24 +1,62 @@ # Sources DIR_SOURCES := \ - html_document.c html_collection.c html_options_collection.c \ - html_element.c html_html_element.c html_head_element.c \ - html_link_element.c html_title_element.c html_meta_element.c \ - html_base_element.c html_style_element.c \ - html_body_element.c html_form_element.c html_select_element.c \ - html_button_element.c html_input_element.c html_text_area_element.c \ - html_opt_group_element.c html_option_element.c html_hr_element.c \ - html_dlist_element.c html_directory_element.c html_menu_element.c \ - html_fieldset_element.c html_legend_element.c html_div_element.c \ - html_paragraph_element.c html_heading_element.c html_quote_element.c \ - html_pre_element.c html_br_element.c html_label_element.c \ - html_ulist_element.c html_olist_element.c html_li_element.c \ - html_font_element.c html_mod_element.c html_anchor_element.c \ - html_basefont_element.c html_image_element.c html_object_element.c \ - html_param_element.c html_applet_element.c html_area_element.c \ - html_map_element.c html_script_element.c html_tablecaption_element.c \ - html_tablecell_element.c html_tablecol_element.c html_tablesection_element.c \ - html_table_element.c html_tablerow_element.c html_frameset_element.c \ - html_frame_element.c html_iframe_element.c html_isindex_element.c \ + html_applet_element.c \ + html_area_element.c \ + html_anchor_element.c \ + html_basefont_element.c \ + html_base_element.c \ + html_body_element.c \ + html_button_element.c \ + html_canvas_element.c \ + html_collection.c \ + html_document.c \ + html_element.c \ + html_dlist_element.c \ + html_directory_element.c \ + html_options_collection.c \ + html_html_element.c \ + html_head_element.c \ + html_link_element.c \ + html_title_element.c \ + html_meta_element.c \ + html_style_element.c \ + html_form_element.c \ + html_select_element.c \ + html_input_element.c \ + html_text_area_element.c \ + html_opt_group_element.c \ + html_option_element.c \ + html_hr_element.c \ + html_menu_element.c \ + html_fieldset_element.c \ + html_legend_element.c \ + html_div_element.c \ + html_paragraph_element.c \ + html_heading_element.c \ + html_quote_element.c \ + html_pre_element.c \ + html_br_element.c \ + html_label_element.c \ + html_ulist_element.c \ + html_olist_element.c \ + html_li_element.c \ + html_font_element.c \ + html_mod_element.c \ + html_image_element.c \ + html_object_element.c \ + html_param_element.c \ + html_map_element.c \ + html_script_element.c \ + html_tablecaption_element.c \ + html_tablecell_element.c \ + html_tablecol_element.c \ + html_tablesection_element.c \ + html_table_element.c \ + html_tablerow_element.c \ + html_frameset_element.c \ + html_frame_element.c \ + html_iframe_element.c \ + html_isindex_element.c \ UNINMPLEMENTED_SOURCES := \ diff --git a/src/html/html_anchor_element.c b/src/html/html_anchor_element.c index 8d64c2b..88fd2ac 100644 --- a/src/html/html_anchor_element.c +++ b/src/html/html_anchor_element.c @@ -18,7 +18,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_ANCHOR_ELEMENT }, diff --git a/src/html/html_applet_element.c b/src/html/html_applet_element.c index 93ea1b5..f7f1afc 100644 --- a/src/html/html_applet_element.c +++ b/src/html/html_applet_element.c @@ -18,7 +18,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_APPLET_ELEMENT }, diff --git a/src/html/html_area_element.c b/src/html/html_area_element.c index 828b073..3da59d7 100644 --- a/src/html/html_area_element.c +++ b/src/html/html_area_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_AREA_ELEMENT }, diff --git a/src/html/html_base_element.c b/src/html/html_base_element.c index 0034f7c..f322f5b 100644 --- a/src/html/html_base_element.c +++ b/src/html/html_base_element.c @@ -13,7 +13,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_BASE_ELEMENT }, diff --git a/src/html/html_basefont_element.c b/src/html/html_basefont_element.c index ac1183d..b68ae03 100644 --- a/src/html/html_basefont_element.c +++ b/src/html/html_basefont_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_BASE_FONT_ELEMENT }, diff --git a/src/html/html_body_element.c b/src/html/html_body_element.c index 0fc4b13..4f52152 100644 --- a/src/html/html_body_element.c +++ b/src/html/html_body_element.c @@ -15,7 +15,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_BODY_ELEMENT }, diff --git a/src/html/html_br_element.c b/src/html/html_br_element.c index 74e3ea8..71778f6 100644 --- a/src/html/html_br_element.c +++ b/src/html/html_br_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_BR_ELEMENT }, diff --git a/src/html/html_button_element.c b/src/html/html_button_element.c index 04a17dd..52a3607 100644 --- a/src/html/html_button_element.c +++ b/src/html/html_button_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_BUTTON_ELEMENT }, diff --git a/src/html/html_canvas_element.c b/src/html/html_canvas_element.c new file mode 100644 index 0000000..71d4a53 --- /dev/null +++ b/src/html/html_canvas_element.c @@ -0,0 +1,214 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org> + */ + +#include <assert.h> +#include <stdlib.h> + +#include <dom/html/html_canvas_element.h> + +#include "html/html_document.h" +#include "html/html_canvas_element.h" + +#include "core/node.h" +#include "core/attr.h" +#include "utils/utils.h" + +static const struct dom_element_protected_vtable _protect_vtable = { + { + DOM_NODE_PROTECT_VTABLE_HTML_CANVAS_ELEMENT + }, + DOM_HTML_CANVAS_ELEMENT_PROTECT_VTABLE +}; + +/** + * Create a dom_html_canvas_element object + * + * \param params The html element creation parameters + * \param ele The returned element object + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_html_canvas_element_create( + struct dom_html_element_create_params *params, + struct dom_html_canvas_element **ele) +{ + struct dom_node_internal *node; + + *ele = malloc(sizeof(dom_html_canvas_element)); + if (*ele == NULL) + return DOM_NO_MEM_ERR; + + /* Set up vtables */ + node = (struct dom_node_internal *) *ele; + node->base.vtable = &_dom_html_element_vtable; + node->vtable = &_protect_vtable; + + return _dom_html_canvas_element_initialise(params, *ele); +} + +/** + * Initialise a dom_html_canvas_element object + * + * \param params The html element creation parameters + * \param ele The dom_html_canvas_element object + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_html_canvas_element_initialise( + struct dom_html_element_create_params *params, + struct dom_html_canvas_element *ele) +{ + return _dom_html_element_initialise(params, &ele->base); +} + +/** + * Finalise a dom_html_canvas_element object + * + * \param ele The dom_html_canvas_element object + */ +void _dom_html_canvas_element_finalise(struct dom_html_canvas_element *ele) +{ + _dom_html_element_finalise(&ele->base); +} + +/** + * Destroy a dom_html_canvas_element object + * + * \param ele The dom_html_canvas_element object + */ +void _dom_html_canvas_element_destroy(struct dom_html_canvas_element *ele) +{ + _dom_html_canvas_element_finalise(ele); + free(ele); +} + +/*------------------------------------------------------------------------*/ +/* The protected virtual functions */ + +/* The virtual function used to parse attribute value, see src/core/element.c + * for detail */ +dom_exception _dom_html_canvas_element_parse_attribute(dom_element *ele, + dom_string *name, dom_string *value, + dom_string **parsed) +{ + UNUSED(ele); + UNUSED(name); + + dom_string_ref(value); + *parsed = value; + + return DOM_NO_ERR; +} + +/* The virtual destroy function, see src/core/node.c for detail */ +void _dom_virtual_html_canvas_element_destroy(dom_node_internal *node) +{ + _dom_html_canvas_element_destroy((struct dom_html_canvas_element *) node); +} + +/* The virtual copy function, see src/core/node.c for detail */ +dom_exception _dom_html_canvas_element_copy( + dom_node_internal *old, dom_node_internal **copy) +{ + dom_html_canvas_element *new_node; + dom_exception err; + + new_node = malloc(sizeof(dom_html_canvas_element)); + if (new_node == NULL) + return DOM_NO_MEM_ERR; + + err = dom_html_canvas_element_copy_internal(old, new_node); + if (err != DOM_NO_ERR) { + free(new_node); + return err; + } + + *copy = (dom_node_internal *) new_node; + + return DOM_NO_ERR; +} + +dom_exception _dom_html_canvas_element_copy_internal( + dom_html_canvas_element *old, + dom_html_canvas_element *new) +{ + dom_exception err; + + err = dom_html_element_copy_internal(old, new); + if (err != DOM_NO_ERR) { + return err; + } + + return DOM_NO_ERR; +} + +/*-----------------------------------------------------------------------*/ +/* API functions */ + + +dom_exception +dom_html_canvas_element_get_width(dom_html_canvas_element *canvas, + dom_ulong *width) +{ + dom_exception exc; + + exc = dom_html_element_get_dom_ulong_property(&canvas->base, + "width", + SLEN("width"), + width); + + if (exc != DOM_NO_ERR) + return exc; + + if (*width == (dom_ulong)-1) { + /* width not set on the canvas, default is 300px */ + *width = 300; + } + + return DOM_NO_ERR; +} + +dom_exception +dom_html_canvas_element_set_width(dom_html_canvas_element *canvas, + dom_ulong width) +{ + return dom_html_element_set_dom_ulong_property(&canvas->base, + "width", + SLEN("width"), + width); +} + +dom_exception +dom_html_canvas_element_get_height(dom_html_canvas_element *canvas, + dom_ulong *height) +{ + dom_exception exc; + + exc = dom_html_element_get_dom_ulong_property(&canvas->base, + "height", + SLEN("height"), + height); + + if (exc != DOM_NO_ERR) + return exc; + + if (*height == (dom_ulong)-1) { + /* height not set on the canvas, default is 150px */ + *height = 150; + } + + return DOM_NO_ERR; +} + +dom_exception +dom_html_canvas_element_set_height(dom_html_canvas_element *canvas, + dom_ulong height) +{ + return dom_html_element_set_dom_ulong_property(&canvas->base, + "height", + SLEN("height"), + height); +} + diff --git a/src/html/html_canvas_element.h b/src/html/html_canvas_element.h new file mode 100644 index 0000000..4cf3042 --- /dev/null +++ b/src/html/html_canvas_element.h @@ -0,0 +1,62 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org> + */ + +#ifndef dom_internal_html_canvas_element_h_ +#define dom_internal_html_canvas_element_h_ + +#include <dom/html/html_canvas_element.h> + +#include "html/html_element.h" + +struct dom_html_canvas_element { + struct dom_html_element base; + /**< The base class */ +}; + +/* Create a dom_html_canvas_element object */ +dom_exception _dom_html_canvas_element_create( + struct dom_html_element_create_params *params, + struct dom_html_canvas_element **ele); + +/* Initialise a dom_html_canvas_element object */ +dom_exception _dom_html_canvas_element_initialise( + struct dom_html_element_create_params *params, + struct dom_html_canvas_element *ele); + +/* Finalise a dom_html_canvas_element object */ +void _dom_html_canvas_element_finalise(struct dom_html_canvas_element *ele); + +/* Destroy a dom_html_canvas_element object */ +void _dom_html_canvas_element_destroy(struct dom_html_canvas_element *ele); + +/* The protected virtual functions */ +dom_exception _dom_html_canvas_element_parse_attribute(dom_element *ele, + dom_string *name, dom_string *value, + dom_string **parsed); + +void _dom_virtual_html_canvas_element_destroy(dom_node_internal *node); +dom_exception _dom_html_canvas_element_copy(dom_node_internal *old, + dom_node_internal **copy); + +#define DOM_HTML_CANVAS_ELEMENT_PROTECT_VTABLE \ + _dom_html_canvas_element_parse_attribute + +#define DOM_NODE_PROTECT_VTABLE_HTML_CANVAS_ELEMENT \ + _dom_virtual_html_canvas_element_destroy, \ + _dom_html_canvas_element_copy + +/* Helper functions*/ +dom_exception _dom_html_canvas_element_copy_internal( + dom_html_canvas_element *old, + dom_html_canvas_element *new); +#define dom_html_canvas_element_copy_internal(o, n) \ + _dom_html_canvas_element_copy_internal( \ + (dom_html_canvas_element *) (o), \ + (dom_html_canvas_element *) (n)) + + +#endif diff --git a/src/html/html_directory_element.c b/src/html/html_directory_element.c index 585af1c..19db7cd 100644 --- a/src/html/html_directory_element.c +++ b/src/html/html_directory_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_DIRECTORY_ELEMENT }, diff --git a/src/html/html_div_element.c b/src/html/html_div_element.c index b061246..c39af74 100644 --- a/src/html/html_div_element.c +++ b/src/html/html_div_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_DIV_ELEMENT }, diff --git a/src/html/html_dlist_element.c b/src/html/html_dlist_element.c index ab9d4c3..fb0ad56 100644 --- a/src/html/html_dlist_element.c +++ b/src/html/html_dlist_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_DL_ELEMENT }, diff --git a/src/html/html_document.c b/src/html/html_document.c index 50a15a7..cf3c25d 100644 --- a/src/html/html_document.c +++ b/src/html/html_document.c @@ -17,6 +17,7 @@ #include "html/html_head_element.h" #include "html/html_body_element.h" #include "html/html_base_element.h" +#include "html/html_canvas_element.h" #include "html/html_div_element.h" #include "html/html_link_element.h" #include "html/html_title_element.h" @@ -71,7 +72,7 @@ #include "utils/namespace.h" #include "utils/utils.h" -static struct dom_html_document_vtable html_document_vtable = { +static const struct dom_html_document_vtable html_document_vtable = { { { { @@ -84,7 +85,7 @@ static struct dom_html_document_vtable html_document_vtable = { DOM_HTML_DOCUMENT_VTABLE }; -static struct dom_node_protect_vtable html_document_protect_vtable = { +static const struct dom_node_protect_vtable html_document_protect_vtable = { DOM_HTML_DOCUMENT_PROTECT_VTABLE }; @@ -318,6 +319,8 @@ static inline dom_html_element_type _dom_html_document_get_element_type( RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_RP) else RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_RT) + else + RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_TT) break; case 3: RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_DIV) @@ -353,6 +356,8 @@ static inline dom_html_element_type _dom_html_document_get_element_type( RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_BDO) else RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_WBR) + else + RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_BIG) break; case 4: RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_META) @@ -394,6 +399,8 @@ static inline dom_html_element_type _dom_html_document_get_element_type( RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_BASE) else RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_TIME) + else + RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_NOBR) break; case 5: RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_INPUT) @@ -468,6 +475,10 @@ static inline dom_html_element_type _dom_html_document_get_element_type( RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_SOURCE) else RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_STRONG) + else + RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_SPACER) + else + RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_STRIKE) break; case 7: RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_CAPTION) @@ -485,6 +496,12 @@ static inline dom_html_element_type _dom_html_document_get_element_type( RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_SECTION) else RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_SUMMARY) + else + RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_ACRONYM) + else + RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_BGSOUND) + else + RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_MARQUEE) break; case 8: RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_TEXTAREA) @@ -508,6 +525,8 @@ static inline dom_html_element_type _dom_html_document_get_element_type( RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_PROGRESS) else RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_TEMPLATE) + else + RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_NOFRAMES) break; case 10: RETURN_IF_MATCH(upper, DOM_HTML_ELEMENT_TYPE_BLOCKQUOTE) @@ -535,6 +554,10 @@ _dom_html_document_create_element_internal( dom_exception exc; struct dom_html_element_create_params params; + /* If the input tag name is empty, this is an 'invalid character' error */ + if (dom_string_length(in_tag_name) == 0) + return DOM_INVALID_CHARACTER_ERR; + exc = dom_string_toupper(in_tag_name, true, ¶ms.name); if (exc != DOM_NO_ERR) return exc; @@ -771,6 +794,10 @@ _dom_html_document_create_element_internal( exc = _dom_html_isindex_element_create(¶ms, (dom_html_isindex_element **) result); break; + case DOM_HTML_ELEMENT_TYPE_CANVAS: + exc = _dom_html_canvas_element_create(¶ms, + (dom_html_canvas_element **) result); + break; case DOM_HTML_ELEMENT_TYPE_DATA: case DOM_HTML_ELEMENT_TYPE_SPAN: case DOM_HTML_ELEMENT_TYPE_TIME: @@ -779,7 +806,6 @@ _dom_html_document_create_element_internal( case DOM_HTML_ELEMENT_TYPE_METER: case DOM_HTML_ELEMENT_TYPE_TRACK: case DOM_HTML_ELEMENT_TYPE_VIDEO: - case DOM_HTML_ELEMENT_TYPE_CANVAS: case DOM_HTML_ELEMENT_TYPE_DIALOG: case DOM_HTML_ELEMENT_TYPE_KEYGEN: case DOM_HTML_ELEMENT_TYPE_OUTPUT: @@ -801,8 +827,10 @@ _dom_html_document_create_element_internal( case DOM_HTML_ELEMENT_TYPE_EM: case DOM_HTML_ELEMENT_TYPE_RP: case DOM_HTML_ELEMENT_TYPE_RT: + case DOM_HTML_ELEMENT_TYPE_TT: case DOM_HTML_ELEMENT_TYPE_BDI: case DOM_HTML_ELEMENT_TYPE_BDO: + case DOM_HTML_ELEMENT_TYPE_BIG: case DOM_HTML_ELEMENT_TYPE_DFN: case DOM_HTML_ELEMENT_TYPE_KBD: case DOM_HTML_ELEMENT_TYPE_NAV: @@ -815,6 +843,7 @@ _dom_html_document_create_element_internal( case DOM_HTML_ELEMENT_TYPE_CODE: case DOM_HTML_ELEMENT_TYPE_MAIN: case DOM_HTML_ELEMENT_TYPE_MARK: + case DOM_HTML_ELEMENT_TYPE_NOBR: case DOM_HTML_ELEMENT_TYPE_RUBY: case DOM_HTML_ELEMENT_TYPE_SAMP: case DOM_HTML_ELEMENT_TYPE_ASIDE: @@ -825,10 +854,16 @@ _dom_html_document_create_element_internal( case DOM_HTML_ELEMENT_TYPE_HEADER: case DOM_HTML_ELEMENT_TYPE_HGROUP: case DOM_HTML_ELEMENT_TYPE_STRONG: + case DOM_HTML_ELEMENT_TYPE_SPACER: + case DOM_HTML_ELEMENT_TYPE_STRIKE: + case DOM_HTML_ELEMENT_TYPE_ACRONYM: case DOM_HTML_ELEMENT_TYPE_ADDRESS: case DOM_HTML_ELEMENT_TYPE_ARTICLE: + case DOM_HTML_ELEMENT_TYPE_BGSOUND: + case DOM_HTML_ELEMENT_TYPE_MARQUEE: case DOM_HTML_ELEMENT_TYPE_SECTION: case DOM_HTML_ELEMENT_TYPE_SUMMARY: + case DOM_HTML_ELEMENT_TYPE_NOFRAMES: case DOM_HTML_ELEMENT_TYPE_NOSCRIPT: case DOM_HTML_ELEMENT_TYPE_FIGCAPTION: /* These have no specialisation: use HTMLElement */ diff --git a/src/html/html_element.c b/src/html/html_element.c index 65a75ca..c110455 100644 --- a/src/html/html_element.c +++ b/src/html/html_element.c @@ -18,7 +18,7 @@ #include "core/document.h" #include "utils/utils.h" -struct dom_html_element_vtable _dom_html_element_vtable = { +const struct dom_html_element_vtable _dom_html_element_vtable = { { { { @@ -31,7 +31,7 @@ struct dom_html_element_vtable _dom_html_element_vtable = { DOM_HTML_ELEMENT_VTABLE }; -static struct dom_element_protected_vtable _dom_html_element_protect_vtable = { +static const struct dom_element_protected_vtable _dom_html_element_protect_vtable = { { DOM_HTML_ELEMENT_PROTECT_VTABLE }, @@ -477,7 +477,7 @@ dom_exception dom_html_element_get_int32_t_property(dom_html_element *ele, char *s3 = _strndup(dom_string_data(s2), dom_string_byte_length(s2)); if (s3 != NULL) { - *value = strtoul(s3, NULL, 0); + *value = strtol(s3, NULL, 0); free(s3); } else { err = DOM_NO_MEM_ERR; @@ -518,7 +518,7 @@ dom_exception dom_html_element_set_int32_t_property(dom_html_element *ele, if (err != DOM_NO_ERR) goto fail; - if (snprintf(numbuffer, 32, "%u", value) == 32) + if (snprintf(numbuffer, 32, "%"PRIu32, value) == 32) numbuffer[31] = '\0'; err = dom_string_create((const uint8_t *) numbuffer, @@ -526,7 +526,7 @@ dom_exception dom_html_element_set_int32_t_property(dom_html_element *ele, if (err != DOM_NO_ERR) goto cleanup; - err = dom_element_set_attribute(ele, svalue, str); + err = dom_element_set_attribute(ele, str, svalue); dom_string_unref(svalue); cleanup: @@ -607,7 +607,7 @@ dom_exception dom_html_element_set_dom_ulong_property(dom_html_element *ele, if (err != DOM_NO_ERR) goto fail; - if (snprintf(numbuffer, 32, "%u", value) == 32) + if (snprintf(numbuffer, 32, "%"PRIu32, value) == 32) numbuffer[31] = '\0'; err = dom_string_create((const uint8_t *) numbuffer, @@ -615,7 +615,7 @@ dom_exception dom_html_element_set_dom_ulong_property(dom_html_element *ele, if (err != DOM_NO_ERR) goto cleanup; - err = dom_element_set_attribute(ele, svalue, str); + err = dom_element_set_attribute(ele, str, svalue); dom_string_unref(svalue); cleanup: diff --git a/src/html/html_element.h b/src/html/html_element.h index 0290569..87e1bbb 100644 --- a/src/html/html_element.h +++ b/src/html/html_element.h @@ -162,7 +162,7 @@ dom_exception _dom_html_element_copy_internal(dom_html_element *old, #define dom_html_element_copy_internal(o, n) _dom_html_element_copy_internal( \ (dom_html_element *) (o), (dom_html_element *) (n)) -extern struct dom_html_element_vtable _dom_html_element_vtable; +extern const struct dom_html_element_vtable _dom_html_element_vtable; #endif diff --git a/src/html/html_fieldset_element.c b/src/html/html_fieldset_element.c index fe44e74..2ab8dd0 100644 --- a/src/html/html_fieldset_element.c +++ b/src/html/html_fieldset_element.c @@ -17,7 +17,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_FIELDSET_ELEMENT }, diff --git a/src/html/html_font_element.c b/src/html/html_font_element.c index ecedfb0..38f8869 100644 --- a/src/html/html_font_element.c +++ b/src/html/html_font_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_FONT_ELEMENT }, diff --git a/src/html/html_form_element.c b/src/html/html_form_element.c index 1dd1992..5ba8365 100644 --- a/src/html/html_form_element.c +++ b/src/html/html_form_element.c @@ -22,7 +22,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_FORM_ELEMENT }, diff --git a/src/html/html_frame_element.c b/src/html/html_frame_element.c index fe6859c..321cff9 100644 --- a/src/html/html_frame_element.c +++ b/src/html/html_frame_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_FRAME_ELEMENT }, diff --git a/src/html/html_frameset_element.c b/src/html/html_frameset_element.c index be44d5d..84a52b0 100644 --- a/src/html/html_frameset_element.c +++ b/src/html/html_frameset_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_FRAME_SET_ELEMENT }, diff --git a/src/html/html_head_element.c b/src/html/html_head_element.c index ff02b1f..20f6aa8 100644 --- a/src/html/html_head_element.c +++ b/src/html/html_head_element.c @@ -13,7 +13,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_HEAD_ELEMENT }, diff --git a/src/html/html_heading_element.c b/src/html/html_heading_element.c index 8ab2c5a..21e36c6 100644 --- a/src/html/html_heading_element.c +++ b/src/html/html_heading_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_HEADING_ELEMENT }, diff --git a/src/html/html_hr_element.c b/src/html/html_hr_element.c index e6086f5..8ca9743 100644 --- a/src/html/html_hr_element.c +++ b/src/html/html_hr_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_HR_ELEMENT }, diff --git a/src/html/html_html_element.c b/src/html/html_html_element.c index 9cdcd5e..24f35e4 100644 --- a/src/html/html_html_element.c +++ b/src/html/html_html_element.c @@ -13,7 +13,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_HTML_ELEMENT }, diff --git a/src/html/html_iframe_element.c b/src/html/html_iframe_element.c index 4d7272b..96397d0 100644 --- a/src/html/html_iframe_element.c +++ b/src/html/html_iframe_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_IFRAME_ELEMENT }, diff --git a/src/html/html_image_element.c b/src/html/html_image_element.c index 3cdd15f..e5b9c7b 100644 --- a/src/html/html_image_element.c +++ b/src/html/html_image_element.c @@ -18,7 +18,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_IMAGE_ELEMENT }, diff --git a/src/html/html_input_element.c b/src/html/html_input_element.c index 079b55e..025ef5d 100644 --- a/src/html/html_input_element.c +++ b/src/html/html_input_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_INPUT_ELEMENT }, diff --git a/src/html/html_isindex_element.c b/src/html/html_isindex_element.c index 40cb99c..e793fae 100644 --- a/src/html/html_isindex_element.c +++ b/src/html/html_isindex_element.c @@ -16,7 +16,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_ISINDEX_ELEMENT }, diff --git a/src/html/html_label_element.c b/src/html/html_label_element.c index 777144a..c62adca 100644 --- a/src/html/html_label_element.c +++ b/src/html/html_label_element.c @@ -15,7 +15,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_LABEL_ELEMENT }, diff --git a/src/html/html_legend_element.c b/src/html/html_legend_element.c index efb712b..f4200c8 100644 --- a/src/html/html_legend_element.c +++ b/src/html/html_legend_element.c @@ -19,7 +19,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_LEGEND_ELEMENT }, diff --git a/src/html/html_li_element.c b/src/html/html_li_element.c index 84becf9..6856046 100644 --- a/src/html/html_li_element.c +++ b/src/html/html_li_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_LI_ELEMENT }, diff --git a/src/html/html_link_element.c b/src/html/html_link_element.c index 87fe980..4916883 100644 --- a/src/html/html_link_element.c +++ b/src/html/html_link_element.c @@ -15,7 +15,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_LINK_ELEMENT }, diff --git a/src/html/html_map_element.c b/src/html/html_map_element.c index 3b10222..865d9b6 100644 --- a/src/html/html_map_element.c +++ b/src/html/html_map_element.c @@ -19,7 +19,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_MAP_ELEMENT }, diff --git a/src/html/html_menu_element.c b/src/html/html_menu_element.c index 09eadb6..882f1f2 100644 --- a/src/html/html_menu_element.c +++ b/src/html/html_menu_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_MENU_ELEMENT }, diff --git a/src/html/html_meta_element.c b/src/html/html_meta_element.c index 4098daf..39fd9e1 100644 --- a/src/html/html_meta_element.c +++ b/src/html/html_meta_element.c @@ -13,7 +13,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_META_ELEMENT }, diff --git a/src/html/html_mod_element.c b/src/html/html_mod_element.c index 20cb042..4f3331c 100644 --- a/src/html/html_mod_element.c +++ b/src/html/html_mod_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_MOD_ELEMENT }, diff --git a/src/html/html_object_element.c b/src/html/html_object_element.c index b51e3a0..1359ede 100644 --- a/src/html/html_object_element.c +++ b/src/html/html_object_element.c @@ -20,7 +20,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_OBJECT_ELEMENT }, diff --git a/src/html/html_olist_element.c b/src/html/html_olist_element.c index c89d11f..415b656 100644 --- a/src/html/html_olist_element.c +++ b/src/html/html_olist_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_OLIST_ELEMENT }, diff --git a/src/html/html_opt_group_element.c b/src/html/html_opt_group_element.c index 6af0a29..a50e3de 100644 --- a/src/html/html_opt_group_element.c +++ b/src/html/html_opt_group_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_OPT_GROUP_ELEMENT }, diff --git a/src/html/html_paragraph_element.c b/src/html/html_paragraph_element.c index 2b2f420..3c8f384 100644 --- a/src/html/html_paragraph_element.c +++ b/src/html/html_paragraph_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_P_ELEMENT }, diff --git a/src/html/html_param_element.c b/src/html/html_param_element.c index c75e1ce..2c991ac 100644 --- a/src/html/html_param_element.c +++ b/src/html/html_param_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_PARAM_ELEMENT }, diff --git a/src/html/html_pre_element.c b/src/html/html_pre_element.c index 64c8c3d..7582fde 100644 --- a/src/html/html_pre_element.c +++ b/src/html/html_pre_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_PRE_ELEMENT }, diff --git a/src/html/html_quote_element.c b/src/html/html_quote_element.c index cf3e0c5..f1bc06f 100644 --- a/src/html/html_quote_element.c +++ b/src/html/html_quote_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_QUOTE_ELEMENT }, diff --git a/src/html/html_script_element.c b/src/html/html_script_element.c index e8dfb1d..9acbf29 100644 --- a/src/html/html_script_element.c +++ b/src/html/html_script_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_SCRIPT_ELEMENT }, diff --git a/src/html/html_select_element.c b/src/html/html_select_element.c index ff549b2..8ba78f1 100644 --- a/src/html/html_select_element.c +++ b/src/html/html_select_element.c @@ -17,7 +17,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_SELECT_ELEMENT }, @@ -213,6 +213,9 @@ dom_exception dom_html_select_element_get_selected_index( dom_html_options_collection *col; err = _dom_html_select_element_make_collection(ele, &col); + if (err != DOM_NO_ERR) { + return err; + } err = dom_html_options_collection_get_length(col, &len); if (err != DOM_NO_ERR) { @@ -266,6 +269,9 @@ dom_exception dom_html_select_element_set_selected_index( dom_html_options_collection *col; err = _dom_html_select_element_make_collection(ele, &col); + if (err != DOM_NO_ERR) { + return err; + } err = dom_html_options_collection_item(col, index, &option); diff --git a/src/html/html_style_element.c b/src/html/html_style_element.c index ae845be..4e4974f 100644 --- a/src/html/html_style_element.c +++ b/src/html/html_style_element.c @@ -13,7 +13,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_STYLE_ELEMENT }, diff --git a/src/html/html_table_element.c b/src/html/html_table_element.c index f197d07..010a6cd 100644 --- a/src/html/html_table_element.c +++ b/src/html/html_table_element.c @@ -21,7 +21,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_TABLE_ELEMENT }, diff --git a/src/html/html_tablecaption_element.c b/src/html/html_tablecaption_element.c index cae229c..0e55e3a 100644 --- a/src/html/html_tablecaption_element.c +++ b/src/html/html_tablecaption_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_TABLE_CAPTION_ELEMENT }, diff --git a/src/html/html_tablecell_element.c b/src/html/html_tablecell_element.c index 7a1f968..2fc31c8 100644 --- a/src/html/html_tablecell_element.c +++ b/src/html/html_tablecell_element.c @@ -18,7 +18,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_TABLE_CELL_ELEMENT }, diff --git a/src/html/html_tablecol_element.c b/src/html/html_tablecol_element.c index 74169be..56bcd64 100644 --- a/src/html/html_tablecol_element.c +++ b/src/html/html_tablecol_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_TABLE_COL_ELEMENT }, diff --git a/src/html/html_tablerow_element.c b/src/html/html_tablerow_element.c index fe7d929..1a6069b 100644 --- a/src/html/html_tablerow_element.c +++ b/src/html/html_tablerow_element.c @@ -20,7 +20,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_TABLE_ROW_ELEMENT }, @@ -244,16 +244,17 @@ dom_exception dom_html_table_row_element_get_row_index( return exp; } - exp = dom_html_table_section_element_get_rows(t_head, &rows); - dom_node_unref(t_head); - if (exp != DOM_NO_ERR) { - return exp; - } - - dom_html_collection_get_length(rows, &len); - dom_html_collection_unref(rows); + if (t_head != NULL) { + exp = dom_html_table_section_element_get_rows(t_head, &rows); + dom_node_unref(t_head); + if (exp != DOM_NO_ERR) { + return exp; + } - count += len; + dom_html_collection_get_length(rows, &len); + dom_html_collection_unref(rows); + count += len; + } for (n = n->first_child;n != parent && n != NULL; n = n->next) { diff --git a/src/html/html_tablesection_element.c b/src/html/html_tablesection_element.c index f839758..dee5ae5 100644 --- a/src/html/html_tablesection_element.c +++ b/src/html/html_tablesection_element.c @@ -21,7 +21,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_TABLE_SECTION_ELEMENT }, diff --git a/src/html/html_text_area_element.c b/src/html/html_text_area_element.c index 5c63c3c..db351bc 100644 --- a/src/html/html_text_area_element.c +++ b/src/html/html_text_area_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_TEXT_AREA_ELEMENT }, diff --git a/src/html/html_title_element.c b/src/html/html_title_element.c index 39e898a..f727dfa 100644 --- a/src/html/html_title_element.c +++ b/src/html/html_title_element.c @@ -17,7 +17,7 @@ #include "core/node.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_TITLE_ELEMENT }, @@ -157,15 +157,7 @@ dom_exception _dom_html_title_element_copy_internal( dom_exception dom_html_title_element_get_text(dom_html_title_element *ele, dom_string **text) { - dom_node_internal *node = (dom_node_internal *) ele; - dom_node_internal *n = node->first_child; - - /* There should be only one child of title element */ - assert(node->first_child == node->last_child); - /* And it should be a text node */ - assert(n->type == DOM_TEXT_NODE); - - return dom_characterdata_get_data(n, text); + return dom_node_get_text_content(ele, text); } /** @@ -178,14 +170,6 @@ dom_exception dom_html_title_element_get_text(dom_html_title_element *ele, dom_exception dom_html_title_element_set_text(dom_html_title_element *ele, dom_string *text) { - dom_node_internal *node = (dom_node_internal *) ele; - dom_node_internal *n = node->first_child; - - /* There should be only one child of title element */ - assert(node->first_child == node->last_child); - /* And it should be a text node */ - assert(n->type == DOM_TEXT_NODE); - - return dom_characterdata_set_data(n, text); + return dom_node_set_text_content(ele, text); } diff --git a/src/html/html_ulist_element.c b/src/html/html_ulist_element.c index f2b87fb..48cb0c2 100644 --- a/src/html/html_ulist_element.c +++ b/src/html/html_ulist_element.c @@ -17,7 +17,7 @@ #include "core/attr.h" #include "utils/utils.h" -static struct dom_element_protected_vtable _protect_vtable = { +static const struct dom_element_protected_vtable _protect_vtable = { { DOM_NODE_PROTECT_VTABLE_HTML_U_LIST_ELEMENT }, diff --git a/src/utils/Makefile b/src/utils/Makefile index 4bb586f..f891b6e 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -1,4 +1,4 @@ # Sources -DIR_SOURCES := namespace.c hashtable.c character_valid.c validate.c +DIR_SOURCES := namespace.c hashtable.c character_valid.c validate.c walk.c include $(NSBUILD)/Makefile.subdir diff --git a/src/utils/namespace.c b/src/utils/namespace.c index c18e24b..e2d249f 100644 --- a/src/utils/namespace.c +++ b/src/utils/namespace.c @@ -77,13 +77,12 @@ static dom_exception _dom_namespace_initialise(void) return DOM_NO_ERR; } -#ifdef FINALISE_NAMESPACE /** * Finalise the namespace component * * \return DOM_NO_ERR on success. */ -dom_exception _dom_namespace_finalise(void) +dom_exception dom_namespace_finalise(void) { int i; @@ -106,7 +105,6 @@ dom_exception _dom_namespace_finalise(void) return DOM_NO_ERR; } -#endif /** * Ensure a QName is valid diff --git a/src/utils/walk.c b/src/utils/walk.c new file mode 100644 index 0000000..f103908 --- /dev/null +++ b/src/utils/walk.c @@ -0,0 +1,130 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2021 Michael Drake <tlsa@netsurf-browser.org> + */ + +/** \file + * This is an API for walking a loaded DOM. + */ + +#include <dom/dom.h> +#include <dom/walk.h> + +/** + * Wrapper for calling client callback. + * + * \param[in] mask Mask of stages to enable callback for. + * \param[in] stage Whether the \ref node is being entered or left. + * \param[in] node The node being walked. + * \param[in] cb The client callback function. + * \param[in] pw The client's private data. + * \param[out] cmd_out Walk instruction from client. + * \return false for early termination of walk, true otherwise. + */ +static inline dom_exception dom_walk__cb( + enum dom_walk_enable mask, + enum dom_walk_stage stage, + dom_node *node, + dom_walk_cb cb, + void *pw, + enum dom_walk_cmd *cmd_out) +{ + if ((1 << stage) & mask) { + dom_node_type type; + dom_exception exc; + + exc = dom_node_get_node_type(node, &type); + if (exc != DOM_NO_ERR) { + return exc; + } + + *cmd_out = cb(stage, type, node, pw); + } + + return DOM_NO_ERR; +} + +/* exported interface documented in include/dom/walk.h */ +dom_exception libdom_treewalk( + enum dom_walk_enable mask, + dom_walk_cb cb, + dom_node *root, + void *pw) +{ + dom_node *node; + dom_exception exc; + enum dom_walk_cmd cmd = DOM_WALK_CMD_CONTINUE; + + node = dom_node_ref(root); + + while (cmd != DOM_WALK_CMD_ABORT) { + dom_node *next = NULL; + + if (cmd != DOM_WALK_CMD_SKIP) { + exc = dom_node_get_first_child(node, &next); + if (exc != DOM_NO_ERR) { + dom_node_unref(node); + break; + } + } + + if (next != NULL) { + dom_node_unref(node); + node = next; + } else { + /* No children; siblings & ancestor's siblings */ + while (node != root) { + exc = dom_walk__cb(mask, DOM_WALK_STAGE_LEAVE, + node, cb, pw, &cmd); + if (exc != DOM_NO_ERR || + cmd == DOM_WALK_CMD_ABORT) { + dom_node_unref(node); + return exc; + } + + exc = dom_node_get_next_sibling(node, &next); + if (exc != DOM_NO_ERR) { + dom_node_unref(node); + node = NULL; + break; + } + + if (next != NULL) { + /* Found next sibling. */ + break; + } + + exc = dom_node_get_parent_node(node, &next); + if (exc != DOM_NO_ERR) { + dom_node_unref(node); + return exc; + } + + dom_node_unref(node); + node = next; + } + + if (node == root) { + break; + } + + dom_node_unref(node); + node = next; + } + + assert(node != NULL); + assert(node != root); + + exc = dom_walk__cb(mask, DOM_WALK_STAGE_ENTER, node, + cb, pw, &cmd); + if (exc != DOM_NO_ERR) { + return exc; + } + } + + dom_node_unref(node); + + return DOM_NO_ERR; +} |