/* * This file is part of LibNSLayout * Licensed under the ISC License, http://opensource.org/licenses/ISC * Copyright 2015 Michael Drake */ /** \file src/dom/event.c * DOM mutation handling */ #include #include #include #include #include "layout.h" #include "dom/event.h" #include "util/dom-str.h" #include "util/util.h" static const char *nsl__dom_node_type_to_string(dom_node_type type) { const char *str[] = { "ELEMENT_NODE", "ATTRIBUTE_NODE", "TEXT_NODE", "CDATA_SECTION_NODE", "ENTITY_REFERENCE_NODE", "ENTITY_NODE", "PROCESSING_INSTRUCTION_NODE", "COMMENT_NODE", "DOCUMENT_NODE", "DOCUMENT_TYPE_NODE", "DOCUMENT_FRAGMENT_NODE", "NOTATION_NODE" }; assert(DOM_NODE_TYPE_COUNT == 12); return str[type - 1]; } static void nsl__dom_event_handler(struct dom_event *evt, void *pw) { dom_event_target *node = NULL; dom_node_type node_type; dom_string *name = NULL; dom_string *type = NULL; dom_exception exc; UNUSED(pw); printf(" DOM Event: "); /* Ugly test to see what events come out */ exc = dom_event_get_target(evt, &node); if ((exc != DOM_NO_ERR) || (node == NULL)) { printf("FAILED to get target node!\n"); goto fail; } exc = dom_node_get_node_type(node, &node_type); if (exc != DOM_NO_ERR) { printf("FAILED to get target node type!\n"); goto fail; } if (node_type == DOM_ELEMENT_NODE) { exc = dom_node_get_node_name(node, &name); if ((exc != DOM_NO_ERR) || (name == NULL)) { printf("FAILED to get target node name!\n"); goto fail; } } exc = dom_event_get_type(evt, &type); if ((exc != DOM_NO_ERR) || (type == NULL)) { printf("FAILED to get event type!\n"); goto fail; } if (node_type == DOM_ELEMENT_NODE) { printf("<%s> %s", dom_string_data(name), dom_string_data(type)); } else { printf("%s %s", nsl__dom_node_type_to_string(node_type), dom_string_data(type)); } fail: if (type != NULL) dom_string_unref(type); if (name != NULL) dom_string_unref(name); if (node != NULL) dom_node_unref(node); printf("\n"); } /* Exported function, documented in src/dom/event.h */ nslayout_error nsl_dom_event_layout_init(nslayout_layout *layout) { dom_exception exc; /* TODO: LibDOM even listeners are really slow. Need to find a better * way to get DOM change notifications. */ exc = dom_event_listener_create(layout->doc, nsl__dom_event_handler, layout, &layout->listener); if (exc != DOM_NO_ERR) { /* TODO: free stuff, return value */ printf("Failed to register event handler!\n"); return NSLAYOUT_NO_MEM; } exc = dom_event_target_add_event_listener( layout->doc, nsl_dom_str_node_inserted, layout->listener, false); if (exc != DOM_NO_ERR) { /* TODO: free stuff, return value */ printf("Failed to register event handler!\n"); return NSLAYOUT_NO_MEM; } exc = dom_event_target_add_event_listener( layout->doc, nsl_dom_str_subtree_modified, layout->listener, false); if (exc != DOM_NO_ERR) { /* TODO: free stuff, return value */ printf("Failed to register event handler!\n"); return NSLAYOUT_NO_MEM; } return NSLAYOUT_OK; } /* Exported function, documented in src/dom/event.h */ nslayout_error nsl_dom_event_layout_fini(nslayout_layout *layout) { dom_exception exc; exc = dom_event_target_remove_event_listener( layout->doc, nsl_dom_str_node_inserted, layout->listener, false); if (exc != DOM_NO_ERR) { /* TODO: free stuff, return value */ printf("Failed to remove event handler!\n"); return NSLAYOUT_NO_MEM; } exc = dom_event_target_remove_event_listener( layout->doc, nsl_dom_str_subtree_modified, layout->listener, false); if (exc != DOM_NO_ERR) { /* TODO: free stuff, return value */ printf("Failed to remove event handler!\n"); return NSLAYOUT_NO_MEM; } dom_event_listener_unref(layout->listener); return NSLAYOUT_OK; }