summaryrefslogtreecommitdiff
path: root/src/events
diff options
context:
space:
mode:
authorBo Yang <struggleyb.nku@gmail.com>2009-08-13 09:33:24 +0000
committerBo Yang <struggleyb.nku@gmail.com>2009-08-13 09:33:24 +0000
commit13fadb12fb400818e0ccb4c38b3bfce70ccfdad2 (patch)
tree19c55b39d97567a37b88b49aaaac13b21b9f24ee /src/events
parentbf6bc398bd40e39a016725550f5b8446a01ee2d1 (diff)
downloadlibdom-13fadb12fb400818e0ccb4c38b3bfce70ccfdad2.tar.gz
libdom-13fadb12fb400818e0ccb4c38b3bfce70ccfdad2.tar.bz2
Merge the Events module (branches/struggleyb/libdom-events) back to trunk. :)
svn path=/trunk/dom/; revision=9236
Diffstat (limited to 'src/events')
-rw-r--r--src/events/Makefile7
-rw-r--r--src/events/custom_event.c99
-rw-r--r--src/events/custom_event.h36
-rw-r--r--src/events/document_event.c188
-rw-r--r--src/events/document_event.h62
-rw-r--r--src/events/event.c354
-rw-r--r--src/events/event.h81
-rw-r--r--src/events/event_listener.c62
-rw-r--r--src/events/event_listener.h28
-rw-r--r--src/events/event_target.c812
-rw-r--r--src/events/event_target.h88
-rw-r--r--src/events/keyboard_event.c354
-rw-r--r--src/events/keyboard_event.h55
-rw-r--r--src/events/mouse_event.c366
-rw-r--r--src/events/mouse_event.h49
-rw-r--r--src/events/mouse_multi_wheel_event.c152
-rw-r--r--src/events/mouse_multi_wheel_event.h44
-rw-r--r--src/events/mouse_wheel_event.c115
-rw-r--r--src/events/mouse_wheel_event.h40
-rw-r--r--src/events/mutation_event.c226
-rw-r--r--src/events/mutation_event.h45
-rw-r--r--src/events/mutation_name_event.c159
-rw-r--r--src/events/mutation_name_event.h42
-rw-r--r--src/events/text_event.c125
-rw-r--r--src/events/text_event.h40
-rw-r--r--src/events/ui_event.c138
-rw-r--r--src/events/ui_event.h54
27 files changed, 3821 insertions, 0 deletions
diff --git a/src/events/Makefile b/src/events/Makefile
new file mode 100644
index 0000000..5b881b7
--- /dev/null
+++ b/src/events/Makefile
@@ -0,0 +1,7 @@
+# Sources
+DIR_SOURCES := event.c event_target.c document_event.c \
+ custom_event.c keyboard_event.c mouse_wheel_event.c \
+ text_event.c event_listener.c mouse_event.c mutation_event.c \
+ ui_event.c mouse_multi_wheel_event.c mutation_name_event.c
+
+include build/makefiles/Makefile.subdir
diff --git a/src/events/custom_event.c b/src/events/custom_event.c
new file mode 100644
index 0000000..920c23e
--- /dev/null
+++ b/src/events/custom_event.c
@@ -0,0 +1,99 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include "events/custom_event.h"
+
+#include "core/document.h"
+
+static void _virtual_dom_custom_event_destroy(struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_custom_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_custom_event_create(struct dom_document *doc,
+ struct dom_custom_event **evt)
+{
+ *evt = _dom_document_alloc(doc, NULL, sizeof(dom_custom_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ((struct dom_event *) *evt)->vtable = &_event_vtable;
+
+ return _dom_custom_event_initialise(doc, *evt);
+}
+
+/* Destructor */
+void _dom_custom_event_destroy(struct dom_document *doc,
+ struct dom_custom_event *evt)
+{
+ _dom_custom_event_finalise(doc, evt);
+
+ _dom_document_alloc(doc, evt, 0);
+}
+
+/* Initialise function */
+dom_exception _dom_custom_event_initialise(struct dom_document *doc,
+ struct dom_custom_event *evt)
+{
+ evt->detail = NULL;
+ return _dom_event_initialise(doc, &evt->base);
+}
+
+/* Finalise function */
+void _dom_custom_event_finalise(struct dom_document *doc,
+ struct dom_custom_event *evt)
+{
+ evt->detail = NULL;
+ _dom_event_finalise(doc, &evt->base);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_custom_event_destroy(struct dom_event *evt)
+{
+ _dom_custom_event_destroy(evt->doc, (dom_custom_event *) evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Get the detail object of this custom event
+ *
+ * \param evt The Event object
+ * \param detail The returned detail object
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_custom_event_get_detail(dom_custom_event *evt,
+ void **detail)
+{
+ *detail = evt->detail;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Initialise this custom event
+ *
+ * \param evt The Event object
+ * \param namespace The namespace of this new Event
+ * \param type The Event type
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \param detail The detail object of this custom event
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_custom_event_init_ns(dom_custom_event *evt,
+ struct dom_string *namespace, struct dom_string *type,
+ bool bubble, bool cancelable, void *detail)
+{
+ evt->detail = detail;
+ return _dom_event_init_ns(&evt->base, namespace, type, bubble,
+ cancelable);
+}
+
diff --git a/src/events/custom_event.h b/src/events/custom_event.h
new file mode 100644
index 0000000..a50bc23
--- /dev/null
+++ b/src/events/custom_event.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_interntal_events_custom_event_h_
+#define dom_interntal_events_custom_event_h_
+
+#include <dom/events/custom_event.h>
+
+#include "events/event.h"
+
+struct dom_custom_event {
+ struct dom_event base;
+ void *detail;
+};
+
+/* Constructor */
+dom_exception _dom_custom_event_create(struct dom_document *doc,
+ struct dom_custom_event **evt);
+
+/* Destructor */
+void _dom_custom_event_destroy(struct dom_document *doc,
+ struct dom_custom_event *evt);
+
+/* Initialise function */
+dom_exception _dom_custom_event_initialise(struct dom_document *doc,
+ struct dom_custom_event *evt);
+
+/* Finalise function */
+void _dom_custom_event_finalise(struct dom_document *doc,
+ struct dom_custom_event *evt);
+
+#endif
diff --git a/src/events/document_event.c b/src/events/document_event.c
new file mode 100644
index 0000000..47afed6
--- /dev/null
+++ b/src/events/document_event.c
@@ -0,0 +1,188 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include <assert.h>
+
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "core/string.h"
+#include "core/node.h"
+#include "core/document.h"
+#include "events/document_event.h"
+#include "events/event.h"
+#include "events/ui_event.h"
+#include "events/custom_event.h"
+#include "events/text_event.h"
+#include "events/keyboard_event.h"
+#include "events/mouse_event.h"
+#include "events/mouse_multi_wheel_event.h"
+#include "events/mouse_wheel_event.h"
+#include "events/mutation_event.h"
+#include "events/mutation_name_event.h"
+
+#include "utils/utils.h"
+
+static const char *__event_types[] = {
+ "Event",
+ "CustomEvent",
+ "UIEvent",
+ "TextEvent",
+ "KeyboardEvent",
+ "MouseEvent",
+ "MouseMultiWheelEvent",
+ "MouseWheelEvent",
+ "MutationEvent",
+ "MutationNameEvent"
+};
+
+/**
+ * Initialise this DocumentEvent
+ *
+ * \param doc The document object
+ * \param dei The DocumentEvent internal object
+ * \param actions The default action fetcher, the browser should provide such
+ * a function to Event module.
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_document_event_internal_initialise(struct dom_document *doc,
+ dom_document_event_internal *dei,
+ dom_events_default_action_fetcher actions)
+{
+ lwc_error err;
+ lwc_context *ctx = _dom_document_get_intern_context(doc);
+ int i = 0;
+
+ for (; i < DOM_EVENT_COUNT; i++) {
+ err = lwc_context_intern(ctx, __event_types[i],
+ SLEN(__event_types[i]), &dei->event_types[i]);
+ if (err != lwc_error_ok)
+ return _dom_exception_from_lwc_error(err);
+ }
+
+ dei->actions = actions;
+
+ return DOM_NO_ERR;
+}
+
+/* Finalise this DocumentEvent */
+void _dom_document_event_internal_finalise(struct dom_document *doc,
+ dom_document_event_internal *dei)
+{
+ /* Nothing to do here */
+ UNUSED(doc);
+ UNUSED(dei);
+ return;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Public API */
+
+/**
+ * Create an Event object
+ *
+ * \param de The DocumentEvent object
+ * \param type The Event type
+ * \param evt The returned Event object
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_document_event_create_event(dom_document_event *de,
+ struct dom_string *type, struct dom_event **evt)
+{
+ lwc_context *ctx = NULL;
+ lwc_string *t = NULL;
+ dom_exception err;
+ struct dom_document *doc = de;
+
+ dom_string_get_intern(type, &ctx, &t);
+ if (t == NULL) {
+ ctx = _dom_document_get_intern_context(doc);
+ err = _dom_string_intern(type, ctx, &t);
+ if (err != DOM_NO_ERR)
+ return err;
+ }
+
+ assert(t != NULL);
+
+ int i, et = 0;
+ dom_document_event_internal *dei = &de->dei;
+ for (i = 0; i < DOM_EVENT_COUNT; i++) {
+ if (dei->event_types[i] == t) {
+ et = i;
+ break;
+ }
+ }
+ lwc_context_string_unref(ctx, t);
+
+ switch (et) {
+ case DOM_EVENT:
+ err = _dom_event_create(doc, evt);
+ break;
+ case DOM_CUSTOM_EVENT:
+ err = _dom_custom_event_create(doc,
+ (dom_custom_event **) evt);
+ break;
+ case DOM_UI_EVENT:
+ err = _dom_ui_event_create(doc, (dom_ui_event **) evt);
+ break;
+ case DOM_TEXT_EVENT:
+ err = _dom_text_event_create(doc,
+ (dom_text_event **) evt);
+ break;
+ case DOM_KEYBOARD_EVENT:
+ err = _dom_keyboard_event_create(doc,
+ (dom_keyboard_event **) evt);
+ break;
+ case DOM_MOUSE_EVENT:
+ err = _dom_mouse_event_create(doc,
+ (dom_mouse_event **) evt);
+ break;
+ case DOM_MOUSE_MULTI_WHEEL_EVENT:
+ err = _dom_mouse_multi_wheel_event_create(doc,
+ (dom_mouse_multi_wheel_event **) evt);
+ break;
+ case DOM_MOUSE_WHEEL_EVENT:
+ err = _dom_mouse_wheel_event_create(doc,
+ (dom_mouse_wheel_event **) evt);
+ break;
+ case DOM_MUTATION_EVENT:
+ err = _dom_mutation_event_create(doc,
+ (dom_mutation_event **) evt);
+ break;
+ case DOM_MUTATION_NAME_EVENT:
+ err = _dom_mutation_name_event_create(doc,
+ (dom_mutation_name_event **) evt);
+ break;
+ default:
+ assert("Should never be here" == NULL);
+ }
+
+ return err;
+}
+
+/**
+ * Tests if the implementation can generate events of a specified type
+ *
+ * \param de The DocumentEvent
+ * \param namespace The namespace of the event
+ * \param type The type of the event
+ * \param can True if we can generate such an event, false otherwise
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ *
+ * We don't support this API now, so the return value should always
+ * DOM_NO_SUPPORTED_ERR.
+ */
+dom_exception _dom_document_event_can_dispatch(dom_document_event *de,
+ struct dom_string *namespace, struct dom_string *type,
+ bool *can)
+{
+ UNUSED(de);
+ UNUSED(namespace);
+ UNUSED(type);
+ UNUSED(can);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
diff --git a/src/events/document_event.h b/src/events/document_event.h
new file mode 100644
index 0000000..2458508
--- /dev/null
+++ b/src/events/document_event.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 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_internal_events_document_event_h_
+#define dom_internal_events_document_event_h_
+
+#include <dom/events/document_event.h>
+
+struct dom_event_listener;
+struct lwc_string_s;
+struct dom_document;
+
+/**
+ * Type of Events
+ */
+typedef enum {
+ DOM_EVENT = 0,
+ DOM_CUSTOM_EVENT,
+ DOM_UI_EVENT,
+ DOM_TEXT_EVENT,
+ DOM_KEYBOARD_EVENT,
+ DOM_MOUSE_EVENT,
+ DOM_MOUSE_MULTI_WHEEL_EVENT,
+ DOM_MOUSE_WHEEL_EVENT,
+ DOM_MUTATION_EVENT,
+ DOM_MUTATION_NAME_EVENT,
+
+ DOM_EVENT_COUNT
+} dom_event_type;
+
+/**
+ * The DocumentEvent internal class
+ */
+struct dom_document_event_internal {
+ dom_events_default_action_fetcher actions;
+ /**< The default action fetecher */
+ struct lwc_string_s *event_types[DOM_EVENT_COUNT];
+ /**< Events type names */
+};
+
+typedef struct dom_document_event_internal dom_document_event_internal;
+
+/**
+ * Constructor and destructor: Since this object is not intended to be
+ * allocated alone, it should be embedded into the Document object, there
+ * is no constructor and destructor for it.
+ */
+
+/* Initialise this DocumentEvent */
+dom_exception _dom_document_event_internal_initialise(struct dom_document *doc,
+ dom_document_event_internal *dei,
+ dom_events_default_action_fetcher actions);
+
+/* Finalise this DocumentEvent */
+void _dom_document_event_internal_finalise(struct dom_document *doc,
+ dom_document_event_internal *dei);
+
+#endif
diff --git a/src/events/event.c b/src/events/event.c
new file mode 100644
index 0000000..f9caa0b
--- /dev/null
+++ b/src/events/event.c
@@ -0,0 +1,354 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include <assert.h>
+#include <time.h>
+
+#include "events/event.h"
+
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "core/string.h"
+#include "core/node.h"
+#include "core/document.h"
+
+static void _virtual_dom_event_destroy(struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_event_create(struct dom_document *doc,
+ struct dom_event **evt)
+{
+ *evt = (dom_event *) _dom_document_alloc(doc, NULL, sizeof(dom_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ (*evt)->vtable = &_event_vtable;
+
+ return _dom_event_initialise(doc, *evt);
+}
+
+/* Destructor */
+void _dom_event_destroy(struct dom_document *doc, struct dom_event *evt)
+{
+ _dom_event_finalise(doc, evt);
+
+ _dom_document_alloc(doc, evt, sizeof(dom_event));
+}
+
+/* Initialise function */
+dom_exception _dom_event_initialise(struct dom_document *doc,
+ struct dom_event *evt)
+{
+ assert(doc != NULL);
+
+ evt->doc = doc;
+ evt->stop = false;
+ evt->stop_now = false;
+ evt->prevent_default = false;
+ evt->custom = false;
+
+ evt->type = NULL;
+
+ evt->namespace = NULL;
+
+ evt->timestamp = time(NULL);
+
+ evt->refcnt = 1;
+ evt->in_dispatch = false;
+
+ return DOM_NO_ERR;
+}
+
+/* Finalise function */
+void _dom_event_finalise(struct dom_document *doc, struct dom_event *evt)
+{
+ assert(doc != NULL);
+ lwc_context *ctx = _dom_document_get_intern_context(doc);
+ assert(ctx != NULL);
+
+ if (evt->type != NULL)
+ lwc_context_string_unref(ctx, evt->type);
+ if (evt->namespace != NULL)
+ lwc_context_string_unref(ctx, evt->namespace);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_event_destroy(struct dom_event *evt)
+{
+ _dom_event_destroy(evt->doc, evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Claim a reference on this event object
+ *
+ * \param evt The Event object
+ */
+void _dom_event_ref(dom_event *evt)
+{
+ evt->refcnt++;
+}
+
+/**
+ * Release a reference on this event object
+ *
+ * \param evt The Event object
+ */
+void _dom_event_unref(dom_event *evt)
+{
+ if (evt->refcnt > 0)
+ evt->refcnt--;
+
+ if (evt->refcnt == 0)
+ dom_event_destroy(evt);
+}
+
+
+/**
+ * Get the event type
+ *
+ * \param evt The event object
+ * \parnm type The returned event type
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_event_get_type(dom_event *evt, struct dom_string **type)
+{
+ struct dom_document *doc = evt->doc;
+ dom_exception err;
+
+ err = _dom_document_create_string_from_lwcstring(doc, evt->type, type);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the target node of this event
+ *
+ * \param evt The event object
+ * \param target The target node
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_event_get_target(dom_event *evt, dom_event_target **target)
+{
+ *target = evt->target;
+ dom_node_ref(*target);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the current target of this event
+ *
+ * \param evt The event object
+ * \param current The current event target node
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_event_get_current_target(dom_event *evt,
+ dom_event_target **current)
+{
+ *current = evt->current;
+ dom_node_ref(*current);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get whether this event can bubble
+ *
+ * \param evt The Event object
+ * \param bubbles The returned value
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_event_get_bubbles(dom_event *evt, bool *bubbles)
+{
+ *bubbles = evt->bubble;
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get whether this event can be cancelable
+ *
+ * \param evt The Event object
+ * \param cancelable The returned value
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_event_get_cancelable(dom_event *evt, bool *cancelable)
+{
+ *cancelable = evt->cancelable;
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the event's generation timestamp
+ *
+ * \param evt The Event object
+ * \param timestamp The returned value
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_event_get_timestamp(dom_event *evt, unsigned int *timestamp)
+{
+ *timestamp = evt->timestamp;
+ return DOM_NO_ERR;
+}
+
+/**
+ * Stop propagation of the event
+ *
+ * \param evt The Event object
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_event_stop_propagation(dom_event *evt)
+{
+ evt->stop = true;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Prevent the default action of this event
+ *
+ * \param evt The Event object
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_event_prevent_default(dom_event *evt)
+{
+ evt->prevent_default = true;
+ return DOM_NO_ERR;
+}
+
+/**
+ * Initialise the event object
+ *
+ * \param evt The event object
+ * \param type The type of this event
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_event_init(dom_event *evt, struct dom_string *type,
+ bool bubble, bool cancelable)
+{
+ assert(evt->doc != NULL);
+ lwc_context *ctx = _dom_document_get_intern_context(evt->doc);
+ lwc_string *str = NULL;
+ dom_exception err;
+
+ err = _dom_string_intern(type, ctx, &str);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ evt->type = str;
+ evt->bubble = bubble;
+ evt->cancelable = cancelable;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the namespace of this event
+ *
+ * \param evt The event object
+ * \param namespace The returned namespace of this event
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_event_get_namespace(dom_event *evt,
+ struct dom_string **namespace)
+{
+ struct dom_document *doc = evt->doc;
+ dom_exception err;
+
+ err = _dom_document_create_string_from_lwcstring(doc, evt->namespace,
+ namespace);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Whether this is a custom event
+ *
+ * \param evt The event object
+ * \param custom The returned value
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_event_is_custom(dom_event *evt, bool *custom)
+{
+ *custom = evt->custom;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Stop the event propagation immediately
+ *
+ * \param evt The event object
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_event_stop_immediate_propagation(dom_event *evt)
+{
+ evt->stop_now = true;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Whether the default action is prevented
+ *
+ * \param evt The event object
+ * \param prevented The returned value
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_event_is_default_prevented(dom_event *evt, bool *prevented)
+{
+ *prevented = evt->prevent_default;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Initialise the event with namespace
+ *
+ * \param evt The event object
+ * \param namespace The namespace of this event
+ * \param type The event type
+ * \param bubble Whether this event has a bubble phase
+ * \param cancelable Whether this event is cancelable
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_event_init_ns(dom_event *evt, struct dom_string *namespace,
+ struct dom_string *type, bool bubble, bool cancelable)
+{
+ assert(evt->doc != NULL);
+ lwc_context *ctx = _dom_document_get_intern_context(evt->doc);
+ lwc_string *str = NULL;
+ dom_exception err;
+
+ err = _dom_string_intern(type, ctx, &str);
+ if (err != DOM_NO_ERR)
+ return err;
+ evt->type = str;
+
+ err = _dom_string_intern(namespace, ctx, &str);
+ if (err != DOM_NO_ERR)
+ return err;
+ evt->namespace = str;
+
+ evt->bubble = bubble;
+ evt->cancelable = cancelable;
+
+ return DOM_NO_ERR;
+}
+
diff --git a/src/events/event.h b/src/events/event.h
new file mode 100644
index 0000000..4d094e9
--- /dev/null
+++ b/src/events/event.h
@@ -0,0 +1,81 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_internal_events_event_h_
+#define dom_internal_events_event_h_
+
+#include <inttypes.h>
+
+#include <dom/events/event_target.h>
+#include <dom/events/event.h>
+
+#include "utils/list.h"
+
+struct lwc_string_s;
+struct dom_document;
+
+/* The private virtual table */
+struct dom_event_private_vtable {
+ void (*destroy)(dom_event *evt);
+};
+
+/**
+ * The Event Ojbect
+ */
+struct dom_event {
+ struct lwc_string_s *type; /**< The type of the event */
+ dom_event_target *target; /**< The event target */
+ dom_event_target *current; /**< The current event target */
+ dom_event_flow_phase phase; /**< The event phase */
+ bool bubble; /**< Whether this event is a bubbling event */
+ bool cancelable; /**< Whether this event is cancelable */
+ unsigned int timestamp;
+ /**< The timestamp this event is created */
+
+ struct lwc_string_s *namespace;
+ /**< The namespace of this event */
+
+ struct dom_document *doc;
+ /**< The document which create this event */
+
+ bool stop; /**< Whether stopPropagation is called */
+ bool stop_now; /**< Whether stopImmediatePropagation is called */
+ bool prevent_default;
+ /**< Whether the default action is prevented */
+
+ bool custom; /**< Whether this is a custom event */
+
+ uint32_t refcnt; /**< The reference count of this object */
+
+ struct dom_event_private_vtable *vtable;
+ /**< The private virtual function table of Event */
+ bool in_dispatch; /**< Whether this event is in dispatch */
+};
+
+/* Constructor */
+dom_exception _dom_event_create(struct dom_document *doc,
+ struct dom_event **evt);
+
+/* Destructor */
+void _dom_event_destroy(struct dom_document *doc, struct dom_event *evt);
+
+/* Initialise function */
+dom_exception _dom_event_initialise(struct dom_document *doc,
+ struct dom_event *evt);
+
+/* Finalise function */
+void _dom_event_finalise(struct dom_document *doc, struct dom_event *evt);
+
+
+static inline void dom_event_destroy(struct dom_event *evt)
+{
+ evt->vtable->destroy(evt);
+}
+#define dom_event_destroy(e) dom_event_destroy((struct dom_event *) (e))
+
+#endif
+
diff --git a/src/events/event_listener.c b/src/events/event_listener.c
new file mode 100644
index 0000000..3c3c14c
--- /dev/null
+++ b/src/events/event_listener.c
@@ -0,0 +1,62 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include "events/event_listener.h"
+#include "core/document.h"
+
+/**
+ * Create an EventListener
+ *
+ * \param doc The document object
+ * \param handler The event function
+ * \param pw The private data
+ * \param listener The returned EventListener
+ * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion.
+ */
+dom_exception dom_event_listener_create(struct dom_document *doc,
+ handle_event handler, void *pw, dom_event_listener **listener)
+{
+ dom_event_listener *ret = (dom_event_listener *) _dom_document_alloc(
+ doc, NULL, sizeof(dom_event_listener));
+ if (ret == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ret->handler = handler;
+ ret->pw = pw;
+ ret->refcnt = 1;
+ ret->doc = doc;
+
+ *listener = ret;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Claim a new reference on the listener object
+ *
+ * \param listener The EventListener object
+ */
+void dom_event_listener_ref(dom_event_listener *listener)
+{
+ listener->refcnt++;
+}
+
+/**
+ * Release a reference on the listener object
+ *
+ * \param listener The EventListener object
+ */
+void dom_event_listener_unref(dom_event_listener *listener)
+{
+ if (listener->refcnt > 0)
+ listener->refcnt--;
+
+ if (listener->refcnt == 0)
+ _dom_document_alloc(listener->doc, listener,
+ sizeof(dom_event_listener));
+}
+
diff --git a/src/events/event_listener.h b/src/events/event_listener.h
new file mode 100644
index 0000000..c85be85
--- /dev/null
+++ b/src/events/event_listener.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_internal_events_event_listener_h_
+#define dom_internal_events_event_listener_h_
+
+#include <dom/events/event_listener.h>
+
+#include "utils/list.h"
+
+/**
+ * The EventListener class
+ */
+struct dom_event_listener {
+ handle_event handler; /**< The event handler function */
+ void *pw; /**< The private data of this listener */
+
+ unsigned int refcnt; /**< The reference count of this listener */
+ struct dom_document *doc;
+ /**< The document which create this listener */
+};
+
+#endif
+
diff --git a/src/events/event_target.c b/src/events/event_target.c
new file mode 100644
index 0000000..e17aa9c
--- /dev/null
+++ b/src/events/event_target.c
@@ -0,0 +1,812 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include <assert.h>
+
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "events/event.h"
+#include "events/event_listener.h"
+#include "events/event_target.h"
+
+#include "core/document.h"
+#include "core/node.h"
+#include "core/string.h"
+
+#include "utils/utils.h"
+#include "utils/validate.h"
+
+/* The number of chains in the hash table used for hash event types */
+#define CHAINS 11
+
+/* Entry for a EventTarget, used to record the bubbling list */
+typedef struct dom_event_target_entry {
+ struct list_entry entry; /**< The list entry */
+ dom_event_target *et; /**< The node */
+} dom_event_target_entry;
+
+/* Hash key/value functions */
+static void *_key(void *key, void *key_pw, dom_alloc alloc, void *pw,
+ bool clone);
+static void *_value(void *value, void *value_pw, dom_alloc alloc,
+ void *pw, bool clone);
+
+
+/* Initialise this EventTarget */
+dom_exception _dom_event_target_internal_initialise(struct dom_document *doc,
+ dom_event_target_internal *eti)
+{
+ UNUSED(doc);
+ eti->listeners = NULL;
+ eti->ns_listeners = NULL;
+
+ return DOM_NO_ERR;
+}
+
+/* Finalise this EventTarget */
+void _dom_event_target_internal_finalise(struct dom_document *doc,
+ dom_event_target_internal *eti)
+{
+ lwc_context *ctx = _dom_document_get_intern_context(doc);
+
+ if (eti->listeners != NULL)
+ _dom_hash_destroy(eti->listeners, _key, ctx, _value, doc);
+ /* TODO: Now, we did not support the EventListener with namespace,
+ * when we support it, we should deal with the ns_listeners hash
+ * table, too.
+ */
+}
+
+/*-------------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Add an EventListener to the EventTarget
+ *
+ * \param et The EventTarget object
+ * \param type The event type which this event listener listens for
+ * \param listener The event listener object
+ * \param capture Whether add this listener in the capturing phase
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_event_target_add_event_listener(dom_event_target *et,
+ struct dom_string *type, struct dom_event_listener *listener,
+ bool capture)
+{
+ struct listener_entry *le = NULL;
+ struct dom_document *doc = dom_node_get_owner(et);
+ assert(doc != NULL);
+
+ struct dom_event_target_internal *eti = &et->eti;
+ lwc_string *t = NULL;
+ lwc_context *ctx = NULL;
+ dom_exception err;
+
+ /* If there is no hash table, we should create one firstly */
+ if (eti->listeners == NULL) {
+ err = _dom_document_create_hashtable(doc, CHAINS,
+ _dom_hash_hash_lwcstring, &eti->listeners);
+ if (err != DOM_NO_ERR)
+ return err;
+ }
+
+ err = dom_string_get_intern(type, &ctx, &t);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ ctx = _dom_document_get_intern_context(doc);
+ if (t == NULL) {
+ err = _dom_string_intern(type, ctx, &t);
+ if (err != DOM_NO_ERR)
+ return err;
+ } else {
+ lwc_context_string_ref(ctx, t);
+ }
+
+ assert(t != NULL);
+
+ le = (struct listener_entry *) _dom_document_alloc(doc, NULL,
+ sizeof(struct listener_entry));
+ if (le == NULL)
+ return DOM_NO_MEM_ERR;
+
+ /* Initialise the listener_entry */
+ list_init(&le->list);
+ le->listener = listener;
+ dom_event_listener_ref(listener);
+ le->capture = capture;
+
+ /* Find the type of this event */
+ struct list_entry *item = (struct list_entry *) _dom_hash_get(
+ eti->listeners, t);
+ if (item == NULL) {
+ /* If there is no item in the hash table, we should add the
+ * first */
+ _dom_hash_add(eti->listeners, t, &le->list, false);
+ } else {
+ /* Append this listener to the end of the list */
+ list_append(item, &le->list);
+ }
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Remove an EventListener from the EventTarget
+ *
+ * \param et The EventTarget object
+ * \param type The event type this listener is registered for
+ * \param listener The listener object
+ * \param capture Whether the listener is registered at the capturing phase
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_event_target_remove_event_listener(dom_event_target *et,
+ struct dom_string *type, struct dom_event_listener *listener,
+ bool capture)
+{
+ struct listener_entry *le = NULL;
+ struct dom_document *doc = dom_node_get_owner(et);
+ if (doc == NULL) {
+ /* TODO: In the progress of parsing, many Nodes in the DTD
+ * has no document at all, do nothing for this kind of node */
+ return DOM_NO_ERR;
+ }
+
+ struct dom_event_target_internal *eti = &et->eti;
+ lwc_string *t = NULL;
+ lwc_context *ctx = NULL;
+ dom_exception err;
+
+ err = dom_string_get_intern(type, &ctx, &t);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ ctx = _dom_document_get_intern_context(doc);
+ if (t == NULL) {
+ err = _dom_string_intern(type, ctx, &t);
+ if (err != DOM_NO_ERR)
+ return err;
+ } else {
+ lwc_context_string_ref(ctx, t);
+ }
+
+ assert(t != NULL);
+
+ /* Find the type of this event */
+ struct list_entry *item = (struct list_entry *) _dom_hash_get(
+ eti->listeners, t);
+ if (item == NULL) {
+ /* There is no such event listener */
+ lwc_context_string_unref(ctx, t);
+ return DOM_NO_ERR;
+ } else {
+ struct list_entry *i = item;
+ do {
+ le = (struct listener_entry *) i;
+ if (le->listener == listener &&
+ le->capture == capture) {
+ /* We found the listener */
+ list_del(i);
+ dom_event_listener_unref(le->listener);
+ _dom_document_alloc(doc, le,
+ sizeof(struct listener_entry));
+ break;
+ }
+ i = i->next;
+ } while(i != item);
+ }
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Dispatch an event into the implementation's event model
+ *
+ * \param et The EventTarget object
+ * \param evt The event object
+ * \param success Indicates whether any of the listeners which handled the
+ * event called Event.preventDefault(). If
+ * Event.preventDefault() was called the returned value is
+ * false, else it is true.
+ * \return DOM_NO_ERR on success
+ * DOM_DISPATCH_REQUEST_ERR If the event is already in dispatch
+ * DOM_UNSPECIFIED_EVENT_TYPE_ERR If the type of the event is Null or
+ * empty string.
+ * DOM_NOT_SUPPORTED_ERR If the event is not created by
+ * Document.createEvent
+ * DOM_INVALID_CHARACTER_ERR If the type of this event is not a
+ * valid NCName.
+ */
+dom_exception _dom_event_target_dispatch_event(dom_event_target *et,
+ struct dom_event *evt, bool *success)
+{
+ assert(et != NULL);
+
+ dom_exception err, ret = DOM_NO_ERR;
+
+ /* To test whether this event is in dispatch */
+ if (evt->in_dispatch == true) {
+ return DOM_DISPATCH_REQUEST_ERR;
+ } else {
+ evt->in_dispatch = true;
+ }
+
+ if (evt->type == NULL || lwc_string_length(evt->type) == 0) {
+ return DOM_UNSPECIFIED_EVENT_TYPE_ERR;
+ }
+
+ if (evt->doc == NULL)
+ return DOM_NOT_SUPPORTED_ERR;
+
+ struct dom_document *doc = dom_node_get_owner(et);
+ if (doc == NULL) {
+ /* TODO: In the progress of parsing, many Nodes in the DTD has
+ * no document at all, do nothing for this kind of node */
+ return DOM_NO_ERR;
+ }
+
+ struct dom_string *type = NULL;
+ err = _dom_document_create_string_from_lwcstring(doc, evt->type, &type);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ if (_dom_validate_ncname(type) == false) {
+ dom_string_unref(type);
+ return DOM_INVALID_CHARACTER_ERR;
+ }
+ dom_string_unref(type);
+
+ lwc_string *t = evt->type;
+ lwc_context *ctx = NULL;
+ dom_event_target_entry list;
+ dom_event_target *target = et;
+
+ ctx = _dom_document_get_intern_context(doc);
+ assert(t != NULL);
+
+ *success = true;
+
+ /* Compose the event target list */
+ list_init(&list.entry);
+ list.et = et;
+ dom_node_ref(et);
+ target = target->parent;
+
+ while (target != NULL) {
+ dom_event_target_entry *l = (dom_event_target_entry *)
+ _dom_document_alloc(doc, NULL,
+ sizeof(dom_event_target_entry));
+ if (l == NULL) {
+ ret = DOM_NO_MEM_ERR;
+ goto cleanup;
+ }
+ list_append(&list.entry, &l->entry);
+ l->et = target;
+ dom_node_ref(target);
+ target = target->parent;
+ }
+
+ /* Fill the target of the event */
+ evt->target = et;
+ evt->phase = DOM_CAPTURING_PHASE;
+
+ /* The capture phase */
+ struct list_entry *e = list.entry.prev;
+ for (; e != &list.entry; e = e->prev) {
+ dom_event_target_entry *l = (dom_event_target_entry *) e;
+ err = _dom_event_target_dispatch(l->et, evt,
+ DOM_CAPTURING_PHASE, success);
+ if (err != DOM_NO_ERR) {
+ ret = err;
+ goto cleanup;
+ }
+ /* If the stopImmediatePropagation or stopPropagation is
+ * called, we should break */
+ if (evt->stop_now == true || evt->stop == true)
+ goto cleanup;
+ }
+
+ /* Target phase */
+ evt->phase = DOM_AT_TARGET;
+ evt->current = et;
+ err = _dom_event_target_dispatch(et, evt, DOM_AT_TARGET,
+ success);
+ if (evt->stop_now == true || evt->stop == true)
+ goto cleanup;
+
+ /* Bubbling phase */
+ evt->phase = DOM_BUBBLING_PHASE;
+
+ e = list.entry.next;
+ for (; e != &list.entry; e = e->next) {
+ dom_event_target_entry *l = (dom_event_target_entry *) e;
+ err = _dom_event_target_dispatch(l->et, evt,
+ DOM_BUBBLING_PHASE, success);
+ if (err != DOM_NO_ERR) {
+ ret = err;
+ goto cleanup;
+ }
+ /* If the stopImmediatePropagation or stopPropagation is
+ * called, we should break */
+ if (evt->stop_now == true || evt->stop == true)
+ goto cleanup;
+ }
+
+ struct dom_document_event_internal *dei = &doc->dei;
+ if (dei->actions == NULL || evt->prevent_default == true)
+ goto cleanup;
+
+ /* The default action */
+ struct dom_string *nodename;
+ err = dom_node_get_node_name(et, &nodename);
+ if (err != DOM_NO_ERR) {
+ ret = err;
+ goto cleanup;
+ }
+ lwc_string *lnodename = NULL;
+ lwc_context *lctx = NULL;
+ err = dom_string_get_intern(nodename, &lctx, &lnodename);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(nodename);
+ ret = err;
+ goto cleanup;
+ }
+
+ dom_event_listener *da = dei->actions(lnodename, t);
+ if (da != NULL) {
+ da->handler(evt, da->pw);
+ }
+
+ dom_string_unref(nodename);
+ lwc_context_string_unref(lctx, lnodename);
+ lwc_context_unref(lctx);
+
+cleanup:
+ if (evt->prevent_default == true) {
+ *success = false;
+ }
+
+ while (list.entry.next != &list.entry) {
+ dom_event_target_entry *e = (dom_event_target_entry *)
+ list.entry.next;
+ dom_node_unref(e->et);
+ list_del(list.entry.next);
+ _dom_document_alloc(doc, e, 0);
+ }
+
+ dom_node_unref(et);
+
+ return ret;
+}
+
+/**
+ * Add an EventListener
+ *
+ * \param et The EventTarget object
+ * \param namespace The namespace of this listener
+ * \param type The event type which this event listener listens for
+ * \param listener The event listener object
+ * \param capture Whether add this listener in the capturing phase
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ *
+ * We don't support this API now, so it always return DOM_NOT_SUPPORTED_ERR.
+ */
+dom_exception _dom_event_target_add_event_listener_ns(dom_event_target *et,
+ struct dom_string *namespace, struct dom_string *type,
+ struct dom_event_listener *listener, bool capture)
+{
+ UNUSED(et);
+ UNUSED(namespace);
+ UNUSED(type);
+ UNUSED(listener);
+ UNUSED(capture);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
+
+/**
+ * Remove an EventListener
+ *
+ * \param et The EventTarget object
+ * \param namespace The namespace of this listener
+ * \param type The event type which this event listener listens for
+ * \param listener The event listener object
+ * \param capture Whether add this listener in the capturing phase
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ *
+ * We don't support this API now, so it always return DOM_NOT_SUPPORTED_ERR.
+ */
+dom_exception _dom_event_target_remove_event_listener_ns(dom_event_target *et,
+ struct dom_string *namespace, struct dom_string *type,
+ struct dom_event_listener *listener, bool capture)
+{
+ UNUSED(et);
+ UNUSED(namespace);
+ UNUSED(type);
+ UNUSED(listener);
+ UNUSED(capture);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* The key process function of the hash table, see utils/hash_table.h for
+ * detail */
+static void *_key(void *key, void *key_pw, dom_alloc alloc, void *pw,
+ bool clone)
+{
+ UNUSED(alloc);
+ UNUSED(pw);
+ /* There should never be the requirement of clone the event listener
+ * list */
+ assert(clone == false);
+ UNUSED(clone);
+
+ lwc_context *ctx = (lwc_context *) key_pw;
+ lwc_context_string_unref(ctx, (lwc_string *) key);
+
+ return NULL;
+}
+
+/* The value process function of the hash table, see utils/hash_table.h for
+ * detail */
+static void *_value(void *value, void *value_pw, dom_alloc alloc,
+ void *pw, bool clone)
+{
+ UNUSED(alloc);
+ UNUSED(pw);
+ /* There should never be the requirement of clone the event listener
+ * list */
+ assert(clone == false);
+ UNUSED(clone);
+
+ struct listener_entry *le = NULL;
+ struct dom_document *doc = (struct dom_document *) value_pw;
+ struct list_entry *i = (struct list_entry *) value;
+
+ while(i != i->next) {
+ le = (struct listener_entry *) i->next;
+ list_del(i->next);
+ dom_event_listener_unref(le->listener);
+ _dom_document_alloc(doc, le, sizeof(struct listener_entry));
+ }
+
+ le = (struct listener_entry *) i;
+ list_del(i);
+ dom_event_listener_unref(le->listener);
+ _dom_document_alloc(doc, le, sizeof(struct listener_entry));
+
+ return NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * Dispatch an event on certain EventTarget
+ *
+ * \param et The EventTarget object
+ * \param evt The event object
+ * \param success Indicates whether any of the listeners which handled the
+ * event called Event.preventDefault(). If
+ * Event.preventDefault() was called the returned value is
+ * false, else it is true.
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_event_target_dispatch(dom_event_target *et,
+ struct dom_event *evt, dom_event_flow_phase phase,
+ bool *success)
+{
+ struct dom_event_target_internal *eti = &et->eti;
+ lwc_string *t = evt->type;
+
+ struct list_entry *item = (struct list_entry *) _dom_hash_get(
+ eti->listeners, t);
+ if (item == NULL) {
+ /* There is no such event listener */
+ return DOM_NO_ERR;
+ } else {
+ /* Call the handler for each listener */
+ struct list_entry *i = item;
+ /* Fill the Event fields */
+ evt->current = et;
+ do {
+ struct listener_entry *le =
+ (struct listener_entry *) i;
+ assert(le->listener->handler != NULL);
+ if ((le->capture == true &&
+ phase == DOM_CAPTURING_PHASE) ||
+ (le->capture == false &&
+ phase == DOM_BUBBLING_PHASE) ||
+ (evt->target == evt->current &&
+ phase == DOM_AT_TARGET)) {
+ /* We found the listener */
+ le->listener->handler(evt, le->listener->pw);
+ /* If the handler call
+ * stopImmediatedPropagation, we should
+ * break */
+ if (evt->stop_now == true)
+ break;
+ }
+ i = i->next;
+ } while(i != item);
+ }
+
+ if (evt->prevent_default == true)
+ *success = false;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Dispatch a DOMNodeInserted/DOMNodeRemoved event
+ *
+ * \param doc The document object
+ * \param et The EventTarget object
+ * \param type "DOMNodeInserted" or "DOMNodeRemoved"
+ * \param related The parent of the removed/inserted node
+ * \param success Whether this event's default action get called
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_dispatch_node_change_event(struct dom_document *doc,
+ dom_event_target *et, dom_event_target *related,
+ dom_mutation_type change, bool *success)
+{
+ struct dom_mutation_event *evt;
+ dom_exception err;
+
+ err = _dom_mutation_event_create(doc, &evt);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ lwc_string *type = NULL;
+ if (change == DOM_MUTATION_ADDITION) {
+ err = _dom_document_create_lwcstring(doc,
+ (const uint8_t *) "DOMNodeInserted",
+ SLEN("DOMNodeInserted"), &type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+ } else if (change == DOM_MUTATION_REMOVAL) {
+ err = _dom_document_create_lwcstring(doc,
+ (const uint8_t *) "DOMNodeRemoval",
+ SLEN("DOMNodeRemoved"), &type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+ } else {
+ assert("Should never be here" == NULL);
+ }
+
+ dom_string *t = NULL;
+ err = _dom_document_create_string_from_lwcstring(doc, type, &t);
+ _dom_document_unref_lwcstring(doc, type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ /* Initiliase the event with corresponding parameters */
+ err = dom_mutation_event_init(evt, t, true, false, related, NULL, NULL,
+ NULL, change);
+ dom_string_unref(t);
+ if (err != DOM_NO_ERR) {
+ goto cleanup;
+ }
+
+ err = dom_event_target_dispatch_event(et, evt, success);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ /* Finalise the evt, and reuse it */
+ _dom_mutation_event_finalise(doc, evt);
+ /* Dispatch the DOMNodeInsertedIntoDocument/DOMNodeRemovedFromDocument
+ * event */
+ if (change == DOM_MUTATION_ADDITION) {
+ err = _dom_document_create_lwcstring(doc,
+ (const uint8_t *)
+ "DOMNodeInsertedIntoDocument",
+ SLEN("DOMNodeInsertedIntoDocument"), &type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+ } else if (change == DOM_MUTATION_REMOVAL) {
+ err = _dom_document_create_lwcstring(doc,
+ (const uint8_t *) "DOMNodeRemovedFromDocument",
+ SLEN("DOMNodeRemovedFromDocument"), &type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+ } else {
+ assert("Should never be here" == NULL);
+ }
+
+ err = _dom_document_create_string_from_lwcstring(doc, type, &t);
+ _dom_document_unref_lwcstring(doc, type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ dom_event_target *target = et;
+ while (target != NULL) {
+ err = dom_mutation_event_init(evt, t, true, false, NULL,
+ NULL, NULL, NULL, change);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ err = dom_event_target_dispatch_event(target, evt, success);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ dom_event_target *p = dom_node_get_parent(target);
+ if (target->first_child != NULL) {
+ target = target->first_child;
+ } else if (target->next != NULL) {
+ target = target->next;
+ } else {
+ while (p != et && target == p->first_child) {
+ target = p;
+ p = dom_node_get_parent(p);
+ }
+
+ target = target->next;
+ }
+ /* Finalise the event for reuse in next iteration */
+ _dom_mutation_event_finalise(doc, evt);
+ }
+
+cleanup:
+ _dom_mutation_event_destroy(doc, evt);
+
+ return err;
+}
+
+/**
+ * Dispatch a DOMAttrModified event
+ *
+ * \param doc The Document object
+ * \param et The EventTarget
+ * \param prev The previous value before change
+ * \param new The new value after change
+ * \param related The related EventTarget
+ * \param attr_name The Attribute name
+ * \param change How this attribute change
+ * \param success Whether this event's default handler get called
+ * \return DOM_NO_ERR on success, appropirate dom_exception on failure.
+ */
+dom_exception _dom_dispatch_attr_modified_event(struct dom_document *doc,
+ dom_event_target *et, dom_string *prev, dom_string *new,
+ dom_event_target *related, dom_string *attr_name,
+ dom_mutation_type change, bool *success)
+{
+ struct dom_mutation_event *evt;
+ dom_exception err;
+
+ err = _dom_mutation_event_create(doc, &evt);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ lwc_string *type = NULL;
+ err = _dom_document_create_lwcstring(doc,
+ (const uint8_t *) "DOMAttrModified",
+ SLEN("DOMAttrModified"), &type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ dom_string *t = NULL;
+ err = _dom_document_create_string_from_lwcstring(doc, type, &t);
+ _dom_document_unref_lwcstring(doc, type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ /* Initiliase the event with corresponding parameters */
+ err = dom_mutation_event_init(evt, t, true, false, related, prev, new,
+ attr_name, change);
+ dom_string_unref(t);
+ if (err != DOM_NO_ERR) {
+ goto cleanup;
+ }
+
+ err = dom_event_target_dispatch_event(et, evt, success);
+
+cleanup:
+ _dom_mutation_event_destroy(doc, evt);
+
+ return err;
+}
+
+/**
+ * Dispatch a DOMCharacterDataModified event
+ *
+ * \param et The EventTarget object
+ * \param prev The preValue of the DOMCharacterData
+ * \param new The newValue of the DOMCharacterData
+ * \return DOM_NO_ERR on success, appropirate dom_exception on failure.
+ *
+ * TODO:
+ * The character_data object may be a part of a Attr node, if so, another
+ * DOMAttrModified event should be dispatched, too. But for now, we did not
+ * support any XML feature, so just leave it as this.
+ */
+dom_exception _dom_dispatch_characterdata_modified_event(
+ struct dom_document *doc, dom_event_target *et,
+ dom_string *prev, dom_string *new, bool *success)
+{
+ struct dom_mutation_event *evt;
+ dom_exception err;
+
+ err = _dom_mutation_event_create(doc, &evt);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ lwc_string *type = NULL;
+ err = _dom_document_create_lwcstring(doc,
+ (const uint8_t *) "DOMCharacterDataModified",
+ SLEN("DOMCharacterDataModified"), &type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ dom_string *t = NULL;
+ err = _dom_document_create_string_from_lwcstring(doc, type, &t);
+ _dom_document_unref_lwcstring(doc, type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ err = dom_mutation_event_init(evt, t, true, false, et, prev, new, NULL,
+ DOM_MUTATION_MODIFICATION);
+ dom_string_unref(t);
+ if (err != DOM_NO_ERR) {
+ goto cleanup;
+ }
+
+ err = dom_event_target_dispatch_event(et, evt, success);
+
+cleanup:
+ _dom_mutation_event_destroy(doc, evt);
+
+ return err;
+}
+
+/**
+ * Dispatch a DOMSubtreeModified event
+ *
+ * \param doc The Document
+ * \param et The EventTarget object
+ * \param success The newValue of the DOMCharacterData
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_dispatch_subtree_modified_event(struct dom_document *doc,
+ dom_event_target *et, bool *success)
+{
+ struct dom_mutation_event *evt;
+ dom_exception err;
+
+ err = _dom_mutation_event_create(doc, &evt);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ lwc_string *type = NULL;
+ err = _dom_document_create_lwcstring(doc,
+ (const uint8_t *) "DOMSubtreeModified",
+ SLEN("DOMSubtreeModified"), &type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ dom_string *t = NULL;
+ err = _dom_document_create_string_from_lwcstring(doc, type, &t);
+ _dom_document_unref_lwcstring(doc, type);
+ if (err != DOM_NO_ERR)
+ goto cleanup;
+
+ err = dom_mutation_event_init(evt, t, true, false, et, NULL, NULL, NULL,
+ DOM_MUTATION_MODIFICATION);
+ dom_string_unref(t);
+ if (err != DOM_NO_ERR) {
+ goto cleanup;
+ }
+
+ err = dom_event_target_dispatch_event(et, evt, success);
+
+cleanup:
+ _dom_mutation_event_destroy(doc, evt);
+
+ return err;
+}
+
diff --git a/src/events/event_target.h b/src/events/event_target.h
new file mode 100644
index 0000000..a92963e
--- /dev/null
+++ b/src/events/event_target.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_internal_events_event_target_h_
+#define dom_internal_events_event_target_h_
+
+#include <dom/events/event.h>
+#include <dom/events/mutation_event.h>
+#include <dom/events/event_target.h>
+#include <dom/events/event_listener.h>
+
+#include "utils/list.h"
+#include "utils/hashtable.h"
+
+struct dom_document;
+struct dom_string;
+
+/**
+ * Listener Entry
+ */
+struct listener_entry {
+ struct list_entry list;
+ /**< The listener list registered at the same
+ * EventTarget */
+ dom_event_listener *listener; /**< The EventListener */
+ bool capture; /**< Whether this listener is in capture phase */
+};
+
+/**
+ * EventTarget internal class
+ */
+struct dom_event_target_internal {
+ struct dom_hash_table *listeners;
+ /**< The listeners of this EventTarget.
+ * The listeners are organized by the
+ * type of events they listen for
+ */
+ struct dom_hash_table *ns_listeners;
+ /**< The listeners with namespace of thie EventTarget */
+};
+
+typedef struct dom_event_target_internal dom_event_target_internal;
+
+/**
+ * Constructor and destructor: Since this object is not intended to be
+ * allocated alone, it should be embedded into the Node object, there is
+ * no constructor and destructor for it.
+ */
+
+/* Initialise this EventTarget */
+dom_exception _dom_event_target_internal_initialise(struct dom_document *doc,
+ dom_event_target_internal *eti);
+
+/* Finalise this EventTarget */
+void _dom_event_target_internal_finalise(struct dom_document *doc,
+ dom_event_target_internal *eti);
+
+/* Dispatch the event on this node */
+dom_exception _dom_event_target_dispatch(dom_event_target *et,
+ struct dom_event *evt, dom_event_flow_phase phase,
+ bool *success);
+
+/* Dispatch a DOMNodeInserted/DOMNodeRemoved event */
+dom_exception _dom_dispatch_node_change_event(struct dom_document *doc,
+ dom_event_target *et, dom_event_target *related,
+ dom_mutation_type change, bool *success);
+
+/* Dispatch a DOMCharacterDataModified event */
+dom_exception _dom_dispatch_characterdata_modified_event(
+ struct dom_document *doc, dom_event_target *et,
+ struct dom_string *prev, struct dom_string *new, bool *success);
+
+/* Dispatch a DOMAttrModified event */
+dom_exception _dom_dispatch_attr_modified_event(struct dom_document *doc,
+ dom_event_target *et, struct dom_string *prev,
+ struct dom_string *new, dom_event_target *related,
+ struct dom_string *attr_name, dom_mutation_type change,
+ bool *success);
+
+/* Dispatch a DOMSubtreeModified event */
+dom_exception _dom_dispatch_subtree_modified_event(struct dom_document *doc,
+ dom_event_target *et, bool *success);
+
+#endif
diff --git a/src/events/keyboard_event.c b/src/events/keyboard_event.c
new file mode 100644
index 0000000..b8fc3ba
--- /dev/null
+++ b/src/events/keyboard_event.c
@@ -0,0 +1,354 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include <string.h>
+
+#include "events/keyboard_event.h"
+#include "core/document.h"
+
+#include "utils/utils.h"
+
+static void _virtual_dom_keyboard_event_destroy(struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_keyboard_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_keyboard_event_create(struct dom_document *doc,
+ struct dom_keyboard_event **evt)
+{
+ *evt = _dom_document_alloc(doc, NULL, sizeof(dom_keyboard_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ((struct dom_event *) *evt)->vtable = &_event_vtable;
+
+ return _dom_keyboard_event_initialise(doc, *evt);
+}
+
+/* Destructor */
+void _dom_keyboard_event_destroy(struct dom_document *doc,
+ struct dom_keyboard_event *evt)
+{
+ _dom_keyboard_event_finalise(doc, evt);
+
+ _dom_document_alloc(doc, evt, 0);
+}
+
+/* Initialise function */
+dom_exception _dom_keyboard_event_initialise(struct dom_document *doc,
+ struct dom_keyboard_event *evt)
+{
+ evt->key_ident = NULL;
+ evt->modifier_state = 0;
+
+ return _dom_ui_event_initialise(doc, &evt->base);
+}
+
+/* Finalise function */
+void _dom_keyboard_event_finalise(struct dom_document *doc,
+ struct dom_keyboard_event *evt)
+{
+ _dom_ui_event_finalise(doc, &evt->base);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_keyboard_event_destroy(struct dom_event *evt)
+{
+ _dom_keyboard_event_destroy(evt->doc, (dom_keyboard_event *) evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Get the key identifier
+ *
+ * \param evt The Event object
+ * \param ident The returned key identifier
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_keyboard_event_get_key_identifier(dom_keyboard_event *evt,
+ struct dom_string **ident)
+{
+ *ident = evt->key_ident;
+ dom_string_ref(*ident);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the key location
+ *
+ * \param evt The Event object
+ * \param loc The returned key location
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_keyboard_event_get_key_location(dom_keyboard_event *evt,
+ dom_key_location *loc)
+{
+ *loc = evt->key_loc;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the ctrl key state
+ *
+ * \param evt The Event object
+ * \param key Whether the Control key is pressed down
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_keyboard_event_get_ctrl_key(dom_keyboard_event *evt,
+ bool *key)
+{
+ *key = ((evt->modifier_state & DOM_MOD_CTRL) != 0);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the shift key state
+ *
+ * \param evt The Event object
+ * \param key Whether the Shift key is pressed down
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_keyboard_event_get_shift_key(dom_keyboard_event *evt,
+ bool *key)
+{
+ *key = ((evt->modifier_state & DOM_MOD_SHIFT) != 0);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the alt key state
+ *
+ * \param evt The Event object
+ * \param key Whether the Alt key is pressed down
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_keyboard_event_get_alt_key(dom_keyboard_event *evt,
+ bool *key)
+{
+ *key = ((evt->modifier_state & DOM_MOD_ALT) != 0);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the meta key state
+ *
+ * \param evt The Event object
+ * \param key Whether the Meta key is pressed down
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_keyboard_event_get_meta_key(dom_keyboard_event *evt,
+ bool *key)
+{
+ *key = ((evt->modifier_state & DOM_MOD_META) != 0);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Query the state of a modifier using a key identifier
+ *
+ * \param evt The event object
+ * \param ml The modifier identifier, such as "Alt", "Control", "Meta",
+ * "AltGraph", "CapsLock", "NumLock", "Scroll", "Shift".
+ * \param state Whether the modifier key is pressed
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ *
+ * @note: If an application wishes to distinguish between right and left
+ * modifiers, this information could be deduced using keyboard events and
+ * KeyboardEvent.keyLocation.
+ */
+dom_exception _dom_keyboard_event_get_modifier_state(dom_keyboard_event *evt,
+ struct dom_string *m, bool *state)
+{
+ if (m == NULL) {
+ *state = false;
+ return DOM_NO_ERR;
+ }
+
+ const char *data = _dom_string_data(m);
+ size_t len = _dom_string_length(m);
+
+ if (len == SLEN("AltGraph") && strncmp(data, "AltGraph", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_ALT_GRAPH) != 0);
+ } else if (len == SLEN("Alt") && strncmp(data, "Alt", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_ALT) != 0);
+ } else if (len == SLEN("CapsLock") &&
+ strncmp(data, "CapsLock", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_CAPS_LOCK) != 0);
+ } else if (len == SLEN("Control") &&
+ strncmp(data, "Control", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_CTRL) != 0);
+ } else if (len == SLEN("Meta") && strncmp(data, "Meta", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_META) != 0);
+ } else if (len == SLEN("NumLock") &&
+ strncmp(data, "NumLock", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_NUM_LOCK) != 0);
+ } else if (len == SLEN("Scroll") &&
+ strncmp(data, "Scroll", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_SCROLL) != 0);
+ } else if (len == SLEN("Shift") && strncmp(data, "Shift", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_SHIFT) != 0);
+ }
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * 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.
+ */
+dom_exception _dom_keyboard_event_init(dom_keyboard_event *evt,
+ struct dom_string *type, bool bubble, bool cancelable,
+ struct dom_abstract_view *view, struct dom_string *key_ident,
+ dom_key_location key_loc, struct dom_string *modifier_list)
+{
+ dom_exception err;
+
+ evt->key_ident = key_ident;
+ dom_string_ref(evt->key_ident);
+ evt->key_loc = key_loc;
+
+ err = _dom_parse_modifier_list(modifier_list, &evt->modifier_state);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ return _dom_ui_event_init(&evt->base, type, bubble, cancelable,
+ view, 0);
+}
+
+/**
+ * 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
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_keyboard_event_init_ns(dom_keyboard_event *evt,
+ struct dom_string *namespace, struct dom_string *type,
+ bool bubble, bool cancelable, struct dom_abstract_view *view,
+ struct dom_string *key_ident, dom_key_location key_loc,
+ struct dom_string *modifier_list)
+{
+ dom_exception err;
+
+ evt->key_ident = key_ident;
+ dom_string_ref(evt->key_ident);
+ evt->key_loc = key_loc;
+
+ err = _dom_parse_modifier_list(modifier_list, &evt->modifier_state);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble,
+ cancelable, view, 0);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * Parse the modifier list string to corresponding bool variable state
+ *
+ * \param modifier_list The modifier list string
+ * \param modifier_state The returned state
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_parse_modifier_list(struct dom_string *modifier_list,
+ uint32_t *modifier_state)
+{
+ *modifier_state = 0;
+
+ if (modifier_list == NULL)
+ return DOM_NO_ERR;
+
+ char *data = _dom_string_data(modifier_list);
+ char *m = data;
+ size_t len = 0;
+
+ while (true) {
+ /* If we reach a space or end of the string, we should parse
+ * the new token. */
+ if (*data == ' ' || *data == '\0') {
+ if (len == SLEN("AltGraph") &&
+ strncmp(data, "AltGraph", len) == 0) {
+ *modifier_state = *modifier_state |
+ DOM_MOD_ALT_GRAPH;
+ } else if (len == SLEN("Alt") &&
+ strncmp(data, "Alt", len) == 0) {
+ *modifier_state = *modifier_state |
+ DOM_MOD_ALT;
+ } else if (len == SLEN("CapsLock") &&
+ strncmp(data, "CapsLock", len) == 0) {
+ *modifier_state = *modifier_state |
+ DOM_MOD_CAPS_LOCK;
+ } else if (len == SLEN("Control") &&
+ strncmp(data, "Control", len) == 0) {
+ *modifier_state = *modifier_state |
+ DOM_MOD_CTRL;
+ } else if (len == SLEN("Meta") &&
+ strncmp(data, "Meta", len) == 0) {
+ *modifier_state = *modifier_state |
+ DOM_MOD_META;
+ } else if (len == SLEN("NumLock") &&
+ strncmp(data, "NumLock", len) == 0) {
+ *modifier_state = *modifier_state |
+ DOM_MOD_NUM_LOCK;
+ } else if (len == SLEN("Scroll") &&
+ strncmp(data, "Scroll", len) == 0) {
+ *modifier_state = *modifier_state |
+ DOM_MOD_SCROLL;
+ } else if (len == SLEN("Shift") &&
+ strncmp(data, "Shift", len) == 0) {
+ *modifier_state = *modifier_state |
+ DOM_MOD_SHIFT;
+ }
+
+ while (*data == ' ') {
+ data++;
+ }
+ /* Finished parsing and break */
+ if (*data == '\0')
+ break;
+
+ m = data;
+ len = 0;
+ }
+
+ data++;
+ len++;
+ }
+
+ return DOM_NO_ERR;
+}
+
diff --git a/src/events/keyboard_event.h b/src/events/keyboard_event.h
new file mode 100644
index 0000000..4d2777c
--- /dev/null
+++ b/src/events/keyboard_event.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_interntal_events_keyboard_event_h_
+#define dom_interntal_events_keyboard_event_h_
+
+#include <dom/events/keyboard_event.h>
+
+#include "events/ui_event.h"
+
+/**
+ * The keyboard event
+ */
+struct dom_keyboard_event {
+ struct dom_ui_event base; /**< The base class */
+
+ struct 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
+ */
+
+ uint32_t modifier_state; /**< The modifier keys state */
+};
+
+/* Constructor */
+dom_exception _dom_keyboard_event_create(struct dom_document *doc,
+ struct dom_keyboard_event **evt);
+
+/* Destructor */
+void _dom_keyboard_event_destroy(struct dom_document *doc,
+ struct dom_keyboard_event *evt);
+
+/* Initialise function */
+dom_exception _dom_keyboard_event_initialise(struct dom_document *doc,
+ struct dom_keyboard_event *evt);
+
+/* Finalise function */
+void _dom_keyboard_event_finalise(struct dom_document *doc,
+ struct dom_keyboard_event *evt);
+
+
+/* Parse the modifier list string to corresponding bool variable state */
+dom_exception _dom_parse_modifier_list(struct dom_string *modifier_list,
+ uint32_t *modifier_state);
+
+#endif
diff --git a/src/events/mouse_event.c b/src/events/mouse_event.c
new file mode 100644
index 0000000..1b31012
--- /dev/null
+++ b/src/events/mouse_event.c
@@ -0,0 +1,366 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include <string.h>
+
+#include "events/mouse_event.h"
+#include "core/document.h"
+
+#include "utils/utils.h"
+
+static void _virtual_dom_mouse_event_destroy(struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_mouse_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_mouse_event_create(struct dom_document *doc,
+ struct dom_mouse_event **evt)
+{
+ *evt = _dom_document_alloc(doc, NULL, sizeof(dom_mouse_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ((struct dom_event *) *evt)->vtable = &_event_vtable;
+
+ return _dom_mouse_event_initialise(doc, *evt);
+}
+
+/* Destructor */
+void _dom_mouse_event_destroy(struct dom_document *doc,
+ struct dom_mouse_event *evt)
+{
+ _dom_mouse_event_finalise(doc, (dom_ui_event *) evt);
+
+ _dom_document_alloc(doc, evt, 0);
+}
+
+/* Initialise function */
+dom_exception _dom_mouse_event_initialise(struct dom_document *doc,
+ struct dom_mouse_event *evt)
+{
+ evt->modifier_state = 0;
+
+ return _dom_ui_event_initialise(doc, (dom_ui_event *) evt);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_mouse_event_destroy(struct dom_event *evt)
+{
+ _dom_mouse_event_destroy(evt->doc, (dom_mouse_event *) evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Get screenX
+ *
+ * \param evt The Event object
+ * \param x The returned screenX
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_screen_x(dom_mouse_event *evt,
+ long *x)
+{
+ *x = evt->sx;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get screenY
+ *
+ * \param evt The Event object
+ * \param y The returned screenY
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_screen_y(dom_mouse_event *evt,
+ long *y)
+{
+ *y = evt->sy;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get clientX
+ *
+ * \param evt The Event object
+ * \param x The returned clientX
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_client_x(dom_mouse_event *evt,
+ long *x)
+{
+ *x = evt->cx;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get clientY
+ *
+ * \param evt The Event object
+ * \param y The returned clientY
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_client_y(dom_mouse_event *evt,
+ long *y)
+{
+ *y = evt->cy;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the ctrl key state
+ *
+ * \param evt The Event object
+ * \param key Whether the Control key is pressed down
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_ctrl_key(dom_mouse_event *evt,
+ bool *key)
+{
+ *key = ((evt->modifier_state & DOM_MOD_CTRL) != 0);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the shift key state
+ *
+ * \param evt The Event object
+ * \param key Whether the Shift key is pressed down
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_shift_key(dom_mouse_event *evt,
+ bool *key)
+{
+ *key = ((evt->modifier_state & DOM_MOD_SHIFT) != 0);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the alt key state
+ *
+ * \param evt The Event object
+ * \param key Whether the Alt key is pressed down
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_alt_key(dom_mouse_event *evt,
+ bool *key)
+{
+ *key = ((evt->modifier_state & DOM_MOD_ALT) != 0);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the meta key state
+ *
+ * \param evt The Event object
+ * \param key Whether the Meta key is pressed down
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_meta_key(dom_mouse_event *evt,
+ bool *key)
+{
+ *key = ((evt->modifier_state & DOM_MOD_META) != 0);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the button which get pressed
+ *
+ * \param evt The Event object
+ * \param button The pressed mouse button
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_button(dom_mouse_event *evt,
+ unsigned short *button)
+{
+ *button = evt->button;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the related target
+ *
+ * \param evt The Event object
+ * \param et The related EventTarget
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_event_get_related_target(dom_mouse_event *evt,
+ dom_event_target **et)
+{
+ *et = evt->related_target;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Query the state of a modifier using a key identifier
+ *
+ * \param evt The event object
+ * \param ml The modifier identifier, such as "Alt", "Control", "Meta",
+ * "AltGraph", "CapsLock", "NumLock", "Scroll", "Shift".
+ * \param state Whether the modifier key is pressed
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ *
+ * @note: If an application wishes to distinguish between right and left
+ * modifiers, this information could be deduced using keyboard events and
+ * KeyboardEvent.keyLocation.
+ */
+dom_exception _dom_mouse_event_get_modifier_state(dom_mouse_event *evt,
+ struct dom_string *m, bool *state)
+{
+ if (m == NULL) {
+ *state = false;
+ return DOM_NO_ERR;
+ }
+
+ const char *data = _dom_string_data(m);
+ size_t len = _dom_string_length(m);
+
+ if (len == SLEN("AltGraph") && strncmp(data, "AltGraph", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_ALT_GRAPH) != 0);
+ } else if (len == SLEN("Alt") && strncmp(data, "Alt", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_ALT) != 0);
+ } else if (len == SLEN("CapsLock") &&
+ strncmp(data, "CapsLock", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_CAPS_LOCK) != 0);
+ } else if (len == SLEN("Control") &&
+ strncmp(data, "Control", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_CTRL) != 0);
+ } else if (len == SLEN("Meta") && strncmp(data, "Meta", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_META) != 0);
+ } else if (len == SLEN("NumLock") &&
+ strncmp(data, "NumLock", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_NUM_LOCK) != 0);
+ } else if (len == SLEN("Scroll") &&
+ strncmp(data, "Scroll", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_SCROLL) != 0);
+ } else if (len == SLEN("Shift") && strncmp(data, "Shift", len) == 0) {
+ *state = ((evt->modifier_state & DOM_MOD_SHIFT) != 0);
+ }
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Initialise this mouse 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 detail The detail information of this mouse event
+ * \param screen_x The x position of the mouse pointer in screen
+ * \param screen_y The y position of the mouse pointer in screen
+ * \param client_x The x position of the mouse pointer in client window
+ * \param client_y The y position of the mouse pointer in client window
+ * \param alt The state of Alt key, true for pressed, false otherwise
+ * \param shift The state of Shift key, true for pressed, false otherwise
+ * \param mata The state of Meta key, true for pressed, false otherwise
+ * \param button The mouse button pressed
+ * \param et The related target of this event, may be NULL
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_mouse_event_init(dom_mouse_event *evt,
+ struct dom_string *type, bool bubble, bool cancelable,
+ struct dom_abstract_view *view, long detail, long screen_x,
+ long screen_y, long client_x, long client_y, bool ctrl,
+ bool alt, bool shift, bool meta, unsigned short button,
+ dom_event_target *et)
+{
+ evt->sx = screen_x;
+ evt->sy = screen_y;
+ evt->cx = client_x;
+ evt->cy = client_y;
+
+ evt->modifier_state = 0;
+ if (ctrl == true) {
+ evt->modifier_state = evt->modifier_state | DOM_MOD_CTRL;
+ }
+ if (alt == true) {
+ evt->modifier_state = evt->modifier_state | DOM_MOD_ALT;
+ }
+ if (shift == true) {
+ evt->modifier_state = evt->modifier_state | DOM_MOD_SHIFT;
+ }
+ if (meta == true) {
+ evt->modifier_state = evt->modifier_state | DOM_MOD_META;
+ }
+
+ evt->button = button;
+ evt->related_target = et;
+
+ return _dom_ui_event_init(&evt->base, type, bubble, cancelable, view,
+ detail);
+}
+
+/**
+ * Initialise the 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 detail The detail information of this mouse event
+ * \param screen_x The x position of the mouse pointer in screen
+ * \param screen_y The y position of the mouse pointer in screen
+ * \param client_x The x position of the mouse pointer in client window
+ * \param client_y The y position of the mouse pointer in client window
+ * \param alt The state of Alt key, true for pressed, false otherwise
+ * \param shift The state of Shift key, true for pressed, false otherwise
+ * \param mata The state of Meta key, true for pressed, false otherwise
+ * \param button The mouse button pressed
+ * \param et The related target of this event, may be NULL
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_mouse_event_init_ns(dom_mouse_event *evt,
+ struct dom_string *namespace, struct dom_string *type,
+ bool bubble, bool cancelable, struct dom_abstract_view *view,
+ long detail, long screen_x, long screen_y, long client_x,
+ long client_y, bool ctrl, bool alt, bool shift, bool meta,
+ unsigned short button, dom_event_target *et)
+{
+ evt->sx = screen_x;
+ evt->sy = screen_y;
+ evt->cx = client_x;
+ evt->cy = client_y;
+
+ evt->modifier_state = 0;
+ if (ctrl == true) {
+ evt->modifier_state = evt->modifier_state | DOM_MOD_CTRL;
+ }
+ if (alt == true) {
+ evt->modifier_state = evt->modifier_state | DOM_MOD_ALT;
+ }
+ if (shift == true) {
+ evt->modifier_state = evt->modifier_state | DOM_MOD_SHIFT;
+ }
+ if (meta == true) {
+ evt->modifier_state = evt->modifier_state | DOM_MOD_META;
+ }
+
+ evt->button = button;
+ evt->related_target = et;
+
+ return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble,
+ cancelable, view, detail);
+}
+
diff --git a/src/events/mouse_event.h b/src/events/mouse_event.h
new file mode 100644
index 0000000..f5117a1
--- /dev/null
+++ b/src/events/mouse_event.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_interntal_events_mouse_event_h_
+#define dom_interntal_events_mouse_event_h_
+
+#include <dom/events/mouse_event.h>
+
+#include "events/ui_event.h"
+
+/**
+ * The mouse event
+ */
+struct dom_mouse_event {
+ struct dom_ui_event base; /**< Base class */
+
+ long sx; /**< ScreenX */
+ long sy; /**< ScreenY */
+ long cx; /**< ClientX */
+ long cy; /**< ClientY */
+
+ uint32_t modifier_state; /**< The modifier keys state */
+
+ unsigned short button; /**< Which button is clicked */
+ dom_event_target *related_target; /**< The related target */
+};
+
+/* Constructor */
+dom_exception _dom_mouse_event_create(struct dom_document *doc,
+ struct dom_mouse_event **evt);
+
+/* Destructor */
+void _dom_mouse_event_destroy(struct dom_document *doc,
+ struct dom_mouse_event *evt);
+
+/* Initialise function */
+dom_exception _dom_mouse_event_initialise(struct dom_document *doc,
+ struct dom_mouse_event *evt);
+
+/* Finalise function */
+#define _dom_mouse_event_finalise _dom_ui_event_finalise
+
+
+#endif
+
diff --git a/src/events/mouse_multi_wheel_event.c b/src/events/mouse_multi_wheel_event.c
new file mode 100644
index 0000000..bca9c97
--- /dev/null
+++ b/src/events/mouse_multi_wheel_event.c
@@ -0,0 +1,152 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include "events/mouse_multi_wheel_event.h"
+#include "events/keyboard_event.h"
+#include "core/document.h"
+
+#include "utils/utils.h"
+
+static void _virtual_dom_mouse_multi_wheel_event_destroy(
+ struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_mouse_multi_wheel_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_mouse_multi_wheel_event_create(struct dom_document *doc,
+ struct dom_mouse_multi_wheel_event **evt)
+{
+ *evt = _dom_document_alloc(doc, NULL,
+ sizeof(dom_mouse_multi_wheel_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ((struct dom_event *) *evt)->vtable = &_event_vtable;
+
+ return _dom_mouse_multi_wheel_event_initialise(doc, *evt);
+}
+
+/* Destructor */
+void _dom_mouse_multi_wheel_event_destroy(struct dom_document *doc,
+ struct dom_mouse_multi_wheel_event *evt)
+{
+ _dom_mouse_multi_wheel_event_finalise(doc, (dom_ui_event *) evt);
+
+ _dom_document_alloc(doc, evt, 0);
+}
+
+/* Initialise function */
+dom_exception _dom_mouse_multi_wheel_event_initialise(struct dom_document *doc,
+ struct dom_mouse_multi_wheel_event *evt)
+{
+ return _dom_mouse_event_initialise(doc, (dom_mouse_event *) evt);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_mouse_multi_wheel_event_destroy(struct dom_event *evt)
+{
+ _dom_mouse_multi_wheel_event_destroy(evt->doc,
+ (dom_mouse_multi_wheel_event *) evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Get wheelDeltaX
+ *
+ * \param evt The Event object
+ * \param x The returned wheelDeltaX
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_multi_wheel_event_get_wheel_delta_x(
+ dom_mouse_multi_wheel_event *evt, long *x)
+{
+ *x = evt->x;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get wheelDeltaY
+ *
+ * \param evt The Event object
+ * \param y The returned wheelDeltaY
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_multi_wheel_event_get_wheel_delta_y(
+ dom_mouse_multi_wheel_event *evt, long *y)
+{
+ *y = evt->y;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get wheelDeltaZ
+ *
+ * \param evt The Event object
+ * \param z The returned wheelDeltaZ
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_multi_wheel_event_get_wheel_delta_z(
+ dom_mouse_multi_wheel_event *evt, long *z)
+{
+ *z = evt->z;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Intialise this 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 detail The detail information of this mouse event
+ * \param screen_x The x position of the mouse pointer in screen
+ * \param screen_y The y position of the mouse pointer in screen
+ * \param client_x The x position of the mouse pointer in client window
+ * \param client_y The y position of the mouse pointer in client window
+ * \param button The mouse button pressed
+ * \param et The related target of this event, may be NULL
+ * \param modifier_list The string contains the modifier identifier strings
+ * \param wheel_delta_x The wheelDeltaX
+ * \param wheel_delta_y The wheelDeltaY
+ * \param wheel_delta_z The wheelDeltaZ
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_mouse_multi_wheel_event_init_ns(
+ dom_mouse_multi_wheel_event *evt, struct dom_string *namespace,
+ struct dom_string *type, bool bubble, bool cancelable,
+ struct dom_abstract_view *view, long detail, long screen_x,
+ long screen_y, long client_x, long client_y,
+ unsigned short button, dom_event_target *et,
+ struct dom_string *modifier_list, long wheel_delta_x,
+ long wheel_delta_y, long wheel_delta_z)
+{
+ dom_exception err;
+ evt->x = wheel_delta_x;
+ evt->y = wheel_delta_y;
+ evt->z = wheel_delta_z;
+
+ dom_mouse_event *e = (dom_mouse_event *) evt;
+
+ err = _dom_parse_modifier_list(modifier_list, &e->modifier_state);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ return _dom_mouse_event_init_ns(&evt->base, namespace, type, bubble,
+ cancelable, view, detail ,screen_x, screen_y, client_x,
+ client_y, false, false, false, false, button, et);
+}
+
diff --git a/src/events/mouse_multi_wheel_event.h b/src/events/mouse_multi_wheel_event.h
new file mode 100644
index 0000000..043efb8
--- /dev/null
+++ b/src/events/mouse_multi_wheel_event.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_events_internal_mouse_multi_wheel_event_h_
+#define dom_events_internal_mouse_multi_wheel_event_h_
+
+#include <dom/events/mouse_multi_wheel_event.h>
+
+#include "events/mouse_event.h"
+
+/**
+ * The MouseMultiWheelEvent
+ */
+struct dom_mouse_multi_wheel_event {
+ struct dom_mouse_event base; /**< The base class */
+
+ long x; /**< The wheelDeltaX */
+ long y; /**< The wheelDeltaY */
+ long z; /**< The wheelDeltaZ */
+};
+
+/* Constructor */
+dom_exception _dom_mouse_multi_wheel_event_create(struct dom_document *doc,
+ struct dom_mouse_multi_wheel_event **evt);
+
+/* Destructor */
+void _dom_mouse_multi_wheel_event_destroy(struct dom_document *doc,
+ struct dom_mouse_multi_wheel_event *evt);
+
+/* Initialise function */
+dom_exception _dom_mouse_multi_wheel_event_initialise(struct dom_document *doc,
+ struct dom_mouse_multi_wheel_event *evt);
+
+/* Finalise function */
+#define _dom_mouse_multi_wheel_event_finalise _dom_mouse_event_finalise
+
+
+#endif
+
+
diff --git a/src/events/mouse_wheel_event.c b/src/events/mouse_wheel_event.c
new file mode 100644
index 0000000..c38ae3e
--- /dev/null
+++ b/src/events/mouse_wheel_event.c
@@ -0,0 +1,115 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include "events/mouse_wheel_event.h"
+#include "events/keyboard_event.h"
+#include "core/document.h"
+
+#include "utils/utils.h"
+
+static void _virtual_dom_mouse_wheel_event_destroy(struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_mouse_wheel_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_mouse_wheel_event_create(struct dom_document *doc,
+ struct dom_mouse_wheel_event **evt)
+{
+ *evt = _dom_document_alloc(doc, NULL, sizeof(dom_mouse_wheel_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ((struct dom_event *) *evt)->vtable = &_event_vtable;
+
+ return _dom_mouse_wheel_event_initialise(doc,
+ (dom_mouse_wheel_event *) *evt);
+}
+
+/* Destructor */
+void _dom_mouse_wheel_event_destroy(struct dom_document *doc,
+ struct dom_mouse_wheel_event *evt)
+{
+ _dom_mouse_wheel_event_finalise(doc, (dom_ui_event *) evt);
+
+ _dom_document_alloc(doc, evt, 0);
+}
+
+/* Initialise function */
+dom_exception _dom_mouse_wheel_event_initialise(struct dom_document *doc,
+ struct dom_mouse_wheel_event *evt)
+{
+ return _dom_mouse_event_initialise(doc, (dom_mouse_event *) evt);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_mouse_wheel_event_destroy(struct dom_event *evt)
+{
+ _dom_mouse_wheel_event_destroy(evt->doc, (dom_mouse_wheel_event *) evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Get wheelDelta
+ *
+ * \param evt The Event object
+ * \param d The wheelDelta
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mouse_wheel_event_get_wheel_delta(
+ dom_mouse_wheel_event *evt, long *d)
+{
+ *d = evt->delta;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Intialise this 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 detail The detail information of this mouse event
+ * \param screen_x The x position of the mouse pointer in screen
+ * \param screen_y The y position of the mouse pointer in screen
+ * \param client_x The x position of the mouse pointer in client window
+ * \param client_y The y position of the mouse pointer in client window
+ * \param button The mouse button pressed
+ * \param et The related target of this event, may be NULL
+ * \param modifier_list The string contains the modifier identifier strings
+ * \param wheel_delta The wheelDelta
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_mouse_wheel_event_init_ns(
+ dom_mouse_wheel_event *evt, struct dom_string *namespace,
+ struct dom_string *type, bool bubble, bool cancelable,
+ struct dom_abstract_view *view, long detail, long screen_x,
+ long screen_y, long client_x, long client_y,
+ unsigned short button, dom_event_target *et,
+ struct dom_string *modifier_list, long wheel_delta)
+{
+ dom_exception err;
+ evt->delta = wheel_delta;
+ dom_mouse_event *e = (dom_mouse_event *) evt;
+
+ err = _dom_parse_modifier_list(modifier_list, &e->modifier_state);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ return _dom_mouse_event_init_ns(&evt->base, namespace, type, bubble,
+ cancelable, view, detail ,screen_x, screen_y,
+ client_x, client_y, false, false, false, false,
+ button, et);
+}
+
diff --git a/src/events/mouse_wheel_event.h b/src/events/mouse_wheel_event.h
new file mode 100644
index 0000000..ba613e5
--- /dev/null
+++ b/src/events/mouse_wheel_event.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_events_internal_mouse_wheel_event_h_
+#define dom_events_internal_mouse_wheel_event_h_
+
+#include <dom/events/mouse_wheel_event.h>
+
+#include "events/mouse_event.h"
+
+/**
+ * The MouseWheelEvent
+ */
+struct dom_mouse_wheel_event {
+ struct dom_mouse_event base; /**< The base class */
+
+ long delta; /**< The wheelDelta */
+};
+
+/* Constructor */
+dom_exception _dom_mouse_wheel_event_create(struct dom_document *doc,
+ struct dom_mouse_wheel_event **evt);
+
+/* Destructor */
+void _dom_mouse_wheel_event_destroy(struct dom_document *doc,
+ struct dom_mouse_wheel_event *evt);
+
+/* Initialise function */
+dom_exception _dom_mouse_wheel_event_initialise(struct dom_document *doc,
+ struct dom_mouse_wheel_event *evt);
+
+/* Finalise function */
+#define _dom_mouse_wheel_event_finalise _dom_mouse_event_finalise
+
+#endif
+
diff --git a/src/events/mutation_event.c b/src/events/mutation_event.c
new file mode 100644
index 0000000..ea7163c
--- /dev/null
+++ b/src/events/mutation_event.c
@@ -0,0 +1,226 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include "events/mutation_event.h"
+#include "core/document.h"
+
+static void _virtual_dom_mutation_event_destroy(struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_mutation_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_mutation_event_create(struct dom_document *doc,
+ struct dom_mutation_event **evt)
+{
+ *evt = _dom_document_alloc(doc, NULL, sizeof(dom_mutation_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ((struct dom_event *) *evt)->vtable = &_event_vtable;
+
+ return _dom_mutation_event_initialise(doc, *evt);
+}
+
+/* Destructor */
+void _dom_mutation_event_destroy(struct dom_document *doc,
+ struct dom_mutation_event *evt)
+{
+ _dom_mutation_event_finalise(doc, evt);
+
+ _dom_document_alloc(doc, evt, 0);
+}
+
+/* Initialise function */
+dom_exception _dom_mutation_event_initialise(struct dom_document *doc,
+ struct dom_mutation_event *evt)
+{
+ evt->related_node = NULL;
+ evt->prev_value = NULL;
+ evt->new_value = NULL;
+ evt->attr_name = NULL;
+
+ return _dom_event_initialise(doc, &evt->base);
+}
+
+/* Finalise function */
+void _dom_mutation_event_finalise(struct dom_document *doc,
+ struct dom_mutation_event *evt)
+{
+ dom_node_unref(evt->related_node);
+ dom_string_unref(evt->prev_value);
+ dom_string_unref(evt->new_value);
+ dom_string_unref(evt->attr_name);
+
+ _dom_event_finalise(doc, &evt->base);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_mutation_event_destroy(struct dom_event *evt)
+{
+ _dom_mutation_event_destroy(evt->doc, (dom_mutation_event *) evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Get the related node
+ *
+ * \param evt The Event object
+ * \param node The related node
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mutation_event_get_related_node(dom_mutation_event *evt,
+ struct dom_node **node)
+{
+ *node = evt->related_node;
+ dom_node_ref(*node);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the old value
+ *
+ * \param evt The Event object
+ * \param ret The old value
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mutation_event_get_prev_value(dom_mutation_event *evt,
+ struct dom_string **ret)
+{
+ *ret = evt->prev_value;
+ dom_string_ref(*ret);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the new value
+ *
+ * \param evt The Event object
+ * \param ret The new value
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mutation_event_get_new_value(dom_mutation_event *evt,
+ struct dom_string **ret)
+{
+ *ret = evt->new_value;
+ dom_string_ref(*ret);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the attr name
+ *
+ * \param evt The Event object
+ * \param ret The attribute name
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mutation_event_get_attr_name(dom_mutation_event *evt,
+ struct dom_string **ret)
+{
+ *ret = evt->attr_name;
+ dom_string_ref(*ret);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the way the attribute change
+ *
+ * \param evt The Event object
+ * \param type The change type
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mutation_event_get_attr_change(dom_mutation_event *evt,
+ dom_mutation_type *type)
+{
+ *type = evt->change;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Initialise the MutationEvent
+ *
+ * \param evt The Event object
+ * \param type The type of this UIEvent
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \param node The mutation node
+ * \param prev_value The old value
+ * \param new_value The new value
+ * \param attr_name The attribute's name
+ * \param change The change type
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_mutation_event_init(dom_mutation_event *evt,
+ struct dom_string *type, bool bubble, bool cancelable,
+ struct dom_node *node, struct dom_string *prev_value,
+ struct dom_string *new_value, struct dom_string *attr_name,
+ dom_mutation_type change)
+{
+ evt->related_node = node;
+ dom_node_ref(node);
+
+ evt->prev_value = prev_value;
+ dom_string_ref(prev_value);
+
+ evt->new_value = new_value;
+ dom_string_ref(new_value);
+
+ evt->attr_name = attr_name;
+ dom_string_ref(attr_name);
+
+ evt->change = change;
+
+ return _dom_event_init(&evt->base, type, bubble, cancelable);
+}
+
+/**
+ * Initialise the MutationEvent with namespace
+ *
+ * \param evt The Event object
+ * \param namespace The namespace
+ * \param type The type of this UIEvent
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \param node The mutation node
+ * \param prev_value The old value
+ * \param new_value The new value
+ * \param attr_name The attribute's name
+ * \param change The change type
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_mutation_event_init_ns(dom_mutation_event *evt,
+ struct dom_string *namespace, struct dom_string *type,
+ bool bubble, bool cancelable, struct dom_node *node,
+ struct dom_string *prev_value, struct dom_string *new_value,
+ struct dom_string *attr_name, dom_mutation_type change)
+{
+ evt->related_node = node;
+ dom_node_ref(node);
+
+ evt->prev_value = prev_value;
+ dom_string_ref(prev_value);
+
+ evt->new_value = new_value;
+ dom_string_ref(new_value);
+
+ evt->attr_name = attr_name;
+ dom_string_ref(attr_name);
+
+ evt->change = change;
+
+ return _dom_event_init_ns(&evt->base, namespace, type, bubble,
+ cancelable);
+}
+
diff --git a/src/events/mutation_event.h b/src/events/mutation_event.h
new file mode 100644
index 0000000..d6cd733
--- /dev/null
+++ b/src/events/mutation_event.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_interntal_events_mutation_event_h_
+#define dom_interntal_events_mutation_event_h_
+
+#include <dom/events/mutation_event.h>
+
+#include "events/event.h"
+
+/**
+ * The MutationEvent
+ */
+struct dom_mutation_event {
+ struct dom_event base;
+
+ struct dom_node *related_node;
+ struct dom_string *prev_value;
+ struct dom_string *new_value;
+ struct dom_string *attr_name;
+ dom_mutation_type change;
+};
+
+/* Constructor */
+dom_exception _dom_mutation_event_create(struct dom_document *doc,
+ struct dom_mutation_event **evt);
+
+/* Destructor */
+void _dom_mutation_event_destroy(struct dom_document *doc,
+ struct dom_mutation_event *evt);
+
+/* Initialise function */
+dom_exception _dom_mutation_event_initialise(struct dom_document *doc,
+ struct dom_mutation_event *evt);
+
+/* Finalise function */
+void _dom_mutation_event_finalise(struct dom_document *doc,
+ struct dom_mutation_event *evt);
+
+#endif
+
diff --git a/src/events/mutation_name_event.c b/src/events/mutation_name_event.c
new file mode 100644
index 0000000..34b9288
--- /dev/null
+++ b/src/events/mutation_name_event.c
@@ -0,0 +1,159 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include "events/mutation_name_event.h"
+#include "core/document.h"
+
+#include "utils/utils.h"
+
+static void _virtual_dom_mutation_name_event_destroy(struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_mutation_name_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_mutation_name_event_create(struct dom_document *doc,
+ struct dom_mutation_name_event **evt)
+{
+ *evt = _dom_document_alloc(doc, NULL, sizeof(dom_mutation_name_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ((struct dom_event *) *evt)->vtable = &_event_vtable;
+
+ return _dom_mutation_name_event_initialise(doc, *evt);
+}
+
+/* Destructor */
+void _dom_mutation_name_event_destroy(struct dom_document *doc,
+ struct dom_mutation_name_event *evt)
+{
+ _dom_mutation_name_event_finalise(doc, evt);
+
+ _dom_document_alloc(doc, evt, 0);
+}
+
+/* Initialise function */
+dom_exception _dom_mutation_name_event_initialise(struct dom_document *doc,
+ struct dom_mutation_name_event *evt)
+{
+ evt->prev_namespace = NULL;
+ evt->prev_nodename = NULL;
+
+ return _dom_event_initialise(doc, (dom_event *) evt);
+}
+
+/* Finalise function */
+void _dom_mutation_name_event_finalise(struct dom_document *doc,
+ struct dom_mutation_name_event *evt)
+{
+ dom_string_unref(evt->prev_namespace);
+ dom_string_unref(evt->prev_nodename);
+
+ _dom_event_finalise(doc, (dom_event *) evt);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_mutation_name_event_destroy(struct dom_event *evt)
+{
+ _dom_mutation_name_event_destroy(evt->doc,
+ (dom_mutation_name_event *) evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Get the previous namespace
+ *
+ * \param evt The Event object
+ * \param namespace The previous namespace of this event
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mutation_name_event_get_prev_namespace(
+ dom_mutation_name_event *evt, struct dom_string **namespace)
+{
+ *namespace = evt->prev_namespace;
+ dom_string_ref(*namespace);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the previous node name
+ *
+ * \param evt The Event object
+ * \param name The previous node name
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_mutation_name_event_get_prev_node_name(
+ dom_mutation_name_event *evt, struct dom_string **name)
+{
+ *name = evt->prev_nodename;
+ dom_string_ref(*name);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Initialise the MutationNameEvent
+ *
+ * \param evt The Event object
+ * \param type The type of this UIEvent
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \param node The node whose name change
+ * \param prev_ns The old namespace
+ * \param prev_name The old name
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_mutation_name_event_init(dom_mutation_name_event *evt,
+ struct dom_string *type, bool bubble, bool cancelable,
+ struct dom_node *node, struct dom_string *prev_ns,
+ struct dom_string *prev_name)
+{
+ evt->prev_namespace = prev_ns;
+ dom_string_ref(prev_ns);
+
+ evt->prev_nodename = prev_name;
+ dom_string_ref(prev_name);
+
+ return _dom_mutation_event_init((dom_mutation_event *) evt, type,
+ bubble, cancelable, node, NULL, NULL, NULL,
+ DOM_MUTATION_MODIFICATION);
+}
+
+/**
+ * Initialise the MutationNameEvent with namespace
+ *
+ * \param evt The Event object
+ * \param namespace The namespace
+ * \param type The type of this UIEvent
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \param node The node whose name change
+ * \param prev_ns The old namespace
+ * \param prev_name The old name
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_mutation_name_event_init_ns(dom_mutation_name_event *evt,
+ struct dom_string *namespace, struct dom_string *type,
+ bool bubble, bool cancelable, struct dom_node *node,
+ struct dom_string *prev_ns, struct dom_string *prev_name)
+{
+ evt->prev_namespace = prev_ns;
+ dom_string_ref(prev_ns);
+
+ evt->prev_nodename = prev_name;
+ dom_string_ref(prev_name);
+
+ return _dom_mutation_event_init_ns((dom_mutation_event *) evt,
+ namespace, type, bubble, cancelable, node, NULL,
+ NULL, NULL, DOM_MUTATION_MODIFICATION);
+}
+
diff --git a/src/events/mutation_name_event.h b/src/events/mutation_name_event.h
new file mode 100644
index 0000000..2ba74de
--- /dev/null
+++ b/src/events/mutation_name_event.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_interntal_events_mutation_name_event_h_
+#define dom_interntal_events_mutation_name_event_h_
+
+#include <dom/events/mutation_name_event.h>
+
+#include "events/mutation_event.h"
+
+/**
+ * The MutationName event
+ */
+struct dom_mutation_name_event {
+ struct dom_mutation_event base;
+
+ struct dom_string *prev_namespace;
+ struct dom_string *prev_nodename;
+};
+
+/* Constructor */
+dom_exception _dom_mutation_name_event_create(struct dom_document *doc,
+ struct dom_mutation_name_event **evt);
+
+/* Destructor */
+void _dom_mutation_name_event_destroy(struct dom_document *doc,
+ struct dom_mutation_name_event *evt);
+
+/* Initialise function */
+dom_exception _dom_mutation_name_event_initialise(struct dom_document *doc,
+ struct dom_mutation_name_event *evt);
+
+/* Finalise function */
+void _dom_mutation_name_event_finalise(struct dom_document *doc,
+ struct dom_mutation_name_event *evt);
+
+#endif
+
diff --git a/src/events/text_event.c b/src/events/text_event.c
new file mode 100644
index 0000000..24c921a
--- /dev/null
+++ b/src/events/text_event.c
@@ -0,0 +1,125 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include "events/text_event.h"
+#include "core/document.h"
+
+static void _virtual_dom_text_event_destroy(struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_text_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_text_event_create(struct dom_document *doc,
+ struct dom_text_event **evt)
+{
+ *evt = _dom_document_alloc(doc, NULL, sizeof(dom_text_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ((struct dom_event *) *evt)->vtable = &_event_vtable;
+
+ return _dom_text_event_initialise(doc, *evt);
+}
+
+/* Destructor */
+void _dom_text_event_destroy(struct dom_document *doc,
+ struct dom_text_event *evt)
+{
+ _dom_text_event_finalise(doc, evt);
+
+ _dom_document_alloc(doc, evt, 0);
+}
+
+/* Initialise function */
+dom_exception _dom_text_event_initialise(struct dom_document *doc,
+ struct dom_text_event *evt)
+{
+ evt->data = NULL;
+ return _dom_ui_event_initialise(doc, &evt->base);
+}
+
+/* Finalise function */
+void _dom_text_event_finalise(struct dom_document *doc,
+ struct dom_text_event *evt)
+{
+ dom_string_unref(evt->data);
+ _dom_ui_event_finalise(doc, &evt->base);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_text_event_destroy(struct dom_event *evt)
+{
+ _dom_text_event_destroy(evt->doc, (dom_text_event *) evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Get the internal data of this event
+ *
+ * \param evt The Event object
+ * \param data The internal data of this Event
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_text_event_get_data(dom_text_event *evt,
+ struct dom_string **data)
+{
+ *data = evt->data;
+ dom_string_ref(*data);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Initialise the TextEvent
+ *
+ * \param evt The Event object
+ * \param type The type of this UIEvent
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \param view The AbstractView of this UIEvent
+ * \param data The text data
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_text_event_init(dom_text_event *evt,
+ struct dom_string *type, bool bubble, bool cancelable,
+ struct dom_abstract_view *view, struct dom_string *data)
+{
+ evt->data = data;
+ dom_string_ref(data);
+
+ return _dom_ui_event_init(&evt->base, type, bubble, cancelable,
+ view, 0);
+}
+
+/**
+ * Initialise the TextEvent with namespace
+ *
+ * \param evt The Event object
+ * \param namespace The namespace of this Event
+ * \param type The type of this UIEvent
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \param view The AbstractView of this UIEvent
+ * \param data The text data
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_text_event_init_ns(dom_text_event *evt,
+ struct dom_string *namespace, struct dom_string *type,
+ bool bubble, bool cancelable, struct dom_abstract_view *view,
+ struct dom_string *data)
+{
+ evt->data = data;
+ dom_string_ref(data);
+
+ return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble,
+ cancelable, view, 0);
+}
+
diff --git a/src/events/text_event.h b/src/events/text_event.h
new file mode 100644
index 0000000..754a4f6
--- /dev/null
+++ b/src/events/text_event.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_internal_events_text_event_h_
+#define dom_internal_events_text_event_h_
+
+#include <dom/events/text_event.h>
+
+#include "events/ui_event.h"
+
+/**
+ * The TextEvent
+ */
+struct dom_text_event {
+ struct dom_ui_event base;
+ struct dom_string *data;
+};
+
+/* Constructor */
+dom_exception _dom_text_event_create(struct dom_document *doc,
+ struct dom_text_event **evt);
+
+/* Destructor */
+void _dom_text_event_destroy(struct dom_document *doc,
+ struct dom_text_event *evt);
+
+/* Initialise function */
+dom_exception _dom_text_event_initialise(struct dom_document *doc,
+ struct dom_text_event *evt);
+
+/* Finalise function */
+void _dom_text_event_finalise(struct dom_document *doc,
+ struct dom_text_event *evt);
+
+#endif
+
diff --git a/src/events/ui_event.c b/src/events/ui_event.c
new file mode 100644
index 0000000..f18e44f
--- /dev/null
+++ b/src/events/ui_event.c
@@ -0,0 +1,138 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#include "events/ui_event.h"
+#include "core/document.h"
+
+static void _virtual_dom_ui_event_destroy(struct dom_event *evt);
+
+static struct dom_event_private_vtable _event_vtable = {
+ _virtual_dom_ui_event_destroy
+};
+
+/* Constructor */
+dom_exception _dom_ui_event_create(struct dom_document *doc,
+ struct dom_ui_event **evt)
+{
+ *evt = _dom_document_alloc(doc, NULL, sizeof(dom_ui_event));
+ if (*evt == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ((struct dom_event *) *evt)->vtable = &_event_vtable;
+
+ return _dom_ui_event_initialise(doc, *evt);
+}
+
+/* Destructor */
+void _dom_ui_event_destroy(struct dom_document *doc,
+ struct dom_ui_event *evt)
+{
+ _dom_ui_event_finalise(doc, evt);
+
+ _dom_document_alloc(doc, evt, 0);
+}
+
+/* Initialise function */
+dom_exception _dom_ui_event_initialise(struct dom_document *doc,
+ struct dom_ui_event *evt)
+{
+ evt->view = NULL;
+ return _dom_event_initialise(doc, &evt->base);
+}
+
+/* Finalise function */
+void _dom_ui_event_finalise(struct dom_document *doc,
+ struct dom_ui_event *evt)
+{
+ evt->view = NULL;
+ _dom_event_finalise(doc, &evt->base);
+}
+
+/* The virtual destroy function */
+void _virtual_dom_ui_event_destroy(struct dom_event *evt)
+{
+ _dom_ui_event_destroy(evt->doc, (dom_ui_event *) evt);
+}
+
+/*----------------------------------------------------------------------*/
+/* The public API */
+
+/**
+ * Get the AbstractView inside this event
+ *
+ * \param evt The Event object
+ * \param view The returned AbstractView
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_ui_event_get_view(dom_ui_event *evt,
+ struct dom_abstract_view **view)
+{
+ *view = evt->view;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get the detail param of this event
+ *
+ * \param evt The Event object
+ * \param detail The detail object
+ * \return DOM_NO_ERR.
+ */
+dom_exception _dom_ui_event_get_detail(dom_ui_event *evt,
+ long *detail)
+{
+ *detail = evt->detail;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Initialise the UIEvent
+ *
+ * \param evt The Event object
+ * \param type The type of this UIEvent
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \param view The AbstractView of this UIEvent
+ * \param detail The detail object
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_ui_event_init(dom_ui_event *evt, struct dom_string *type,
+ bool bubble, bool cancelable, struct dom_abstract_view *view,
+ long detail)
+{
+ evt->view = view;
+ evt->detail = detail;
+
+ return _dom_event_init(&evt->base, type, bubble, cancelable);
+}
+
+/**
+ * Initialise the UIEvent with namespace
+ *
+ * \param evt The Event object
+ * \param namespace The namespace of this Event
+ * \param type The type of this UIEvent
+ * \param bubble Whether this event can bubble
+ * \param cancelable Whether this event is cancelable
+ * \param view The AbstractView of this UIEvent
+ * \param detail The detail object
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_ui_event_init_ns(dom_ui_event *evt,
+ struct dom_string *namespace, struct dom_string *type,
+ bool bubble, bool cancelable, struct dom_abstract_view *view,
+ long detail)
+{
+ evt->view = view;
+ evt->detail = detail;
+
+ return _dom_event_init_ns(&evt->base, namespace, type, bubble,
+ cancelable);
+}
+
diff --git a/src/events/ui_event.h b/src/events/ui_event.h
new file mode 100644
index 0000000..3a245ab
--- /dev/null
+++ b/src/events/ui_event.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_interntal_events_ui_event_h_
+#define dom_interntal_events_ui_event_h_
+
+#include <dom/events/ui_event.h>
+
+#include "events/event.h"
+
+/**
+ * The modifier key state
+ */
+typedef enum {
+ DOM_MOD_CTRL = (1<<0),
+ DOM_MOD_META = (1<<1),
+ DOM_MOD_SHIFT = (1<<2),
+ DOM_MOD_ALT = (1<<3),
+ DOM_MOD_ALT_GRAPH = (1<<4),
+ DOM_MOD_CAPS_LOCK = (1<<5),
+ DOM_MOD_NUM_LOCK = (1<<6),
+ DOM_MOD_SCROLL = (1<<7)
+} dom_modifier_key;
+
+/**
+ * The UIEvent
+ */
+struct dom_ui_event {
+ struct dom_event base; /**< The base class */
+ struct dom_abstract_view *view; /**< The AbstractView */
+ long detail; /**< Some private data for this event */
+};
+
+/* Constructor */
+dom_exception _dom_ui_event_create(struct dom_document *doc,
+ struct dom_ui_event **evt);
+
+/* Destructor */
+void _dom_ui_event_destroy(struct dom_document *doc,
+ struct dom_ui_event *evt);
+
+/* Initialise function */
+dom_exception _dom_ui_event_initialise(struct dom_document *doc,
+ struct dom_ui_event *evt);
+
+/* Finalise function */
+void _dom_ui_event_finalise(struct dom_document *doc,
+ struct dom_ui_event *evt);
+
+#endif