summaryrefslogtreecommitdiff
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
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
-rw-r--r--Makefile12
-rw-r--r--bindings/hubbub/parser.c5
-rw-r--r--bindings/xml/xmlparser.c6
-rw-r--r--include/dom/bootstrap/implpriv.h3
-rw-r--r--include/dom/core/exceptions.h18
-rw-r--r--include/dom/core/implementation.h2
-rw-r--r--include/dom/events/custom_event.h32
-rw-r--r--include/dom/events/document_event.h47
-rw-r--r--include/dom/events/event.h93
-rw-r--r--include/dom/events/event_listener.h27
-rw-r--r--include/dom/events/event_target.h62
-rw-r--r--include/dom/events/events.h25
-rw-r--r--include/dom/events/keyboard_event.h89
-rw-r--r--include/dom/events/mouse_event.h108
-rw-r--r--include/dom/events/mouse_multi_wheel_event.h56
-rw-r--r--include/dom/events/mouse_wheel_event.h42
-rw-r--r--include/dom/events/mutation_event.h80
-rw-r--r--include/dom/events/mutation_name_event.h54
-rw-r--r--include/dom/events/text_event.h41
-rw-r--r--include/dom/events/ui_event.h45
-rw-r--r--src/bootstrap/implementation.c4
-rw-r--r--src/core/characterdata.c58
-rw-r--r--src/core/document.c21
-rw-r--r--src/core/document.h11
-rw-r--r--src/core/element.c222
-rw-r--r--src/core/implementation.c3
-rw-r--r--src/core/node.c85
-rw-r--r--src/core/node.h5
-rw-r--r--src/core/string.c26
-rw-r--r--src/core/string.h10
-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
-rw-r--r--src/utils/hashtable.c11
-rw-r--r--src/utils/hashtable.h3
-rw-r--r--test/DOMTSHandler.pm6
60 files changed, 5082 insertions, 51 deletions
diff --git a/Makefile b/Makefile
index 5ef0ae5..95b2505 100644
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,18 @@ INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/nodelist.h;$(Is)/string.h
INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/text.h;$(Is)/typeinfo.h
INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/comment.h
+Is := include/dom/events
+I := /include/dom/events
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/event.h;$(Is)/ui_event.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/custom_event.h;$(Is)/mouse_event.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/keyboard_event.h;$(Is)/text_event.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/mouse_wheel_event.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/mouse_multi_wheel_event.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/mutation_event.h;$(Is)/event_target.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/mutation_name_event.h;$(Is)/events.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/event_listener.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/document_event.h
+
INSTALL_ITEMS := $(INSTALL_ITEMS) /lib/pkgconfig:lib$(COMPONENT).pc.in
INSTALL_ITEMS := $(INSTALL_ITEMS) /lib:$(OUTPUT)
diff --git a/bindings/hubbub/parser.c b/bindings/hubbub/parser.c
index 4551f13..a19647b 100644
--- a/bindings/hubbub/parser.c
+++ b/bindings/hubbub/parser.c
@@ -190,8 +190,11 @@ dom_hubbub_parser *dom_hubbub_parser_create(const char *aliases,
/* No longer need the feature string */
dom_string_unref(features);
+ /* TODO: Just pass the dom_events_default_action_fetcher a NULL,
+ * we should pass the real function when we integrate libDOM with
+ * Netsurf */
err = dom_implementation_create_document(parser->impl, NULL, NULL, NULL,
- alloc, pw, ctx, &parser->doc);
+ alloc, pw, ctx, NULL, &parser->doc);
if (err != DOM_NO_ERR) {
hubbub_parser_destroy(parser->parser);
alloc(parser, 0, pw);
diff --git a/bindings/xml/xmlparser.c b/bindings/xml/xmlparser.c
index e451699..8cae01c 100644
--- a/bindings/xml/xmlparser.c
+++ b/bindings/xml/xmlparser.c
@@ -348,12 +348,14 @@ void xml_parser_start_document(void *ctx)
/* Invoke libxml2's default behaviour */
xmlSAX2StartDocument(parser->xml_ctx);
- /* Attempt to create a document */
+ /* TODO: Just pass the dom_events_default_action_fetcher a NULL,
+ * we should pass the real function when we integrate libDOM with
+ * Netsurf */
err = dom_implementation_create_document(parser->impl,
/* namespace */ NULL,
/* qname */ NULL,
/* doctype */ NULL,
- parser->alloc, parser->pw, parser->ctx,
+ parser->alloc, parser->pw, parser->ctx, NULL,
&doc);
if (err != DOM_NO_ERR) {
parser->msg(DOM_MSG_CRITICAL, parser->mctx,
diff --git a/include/dom/bootstrap/implpriv.h b/include/dom/bootstrap/implpriv.h
index f6a7eb2..17ffcde 100644
--- a/include/dom/bootstrap/implpriv.h
+++ b/include/dom/bootstrap/implpriv.h
@@ -28,6 +28,7 @@
#include <stdbool.h>
#include <dom/core/exceptions.h>
+#include <dom/events/document_event.h>
#include <dom/functypes.h>
#include <dom/core/string.h>
@@ -126,6 +127,7 @@ struct dom_implementation {
struct dom_string *qname,
struct dom_document_type *doctype,
dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf,
struct dom_document **doc);
/**
@@ -245,6 +247,7 @@ dom_exception dom_register_source(struct dom_implementation_source *source);
/* Create a DOM document */
dom_exception dom_document_create(struct dom_implementation *impl,
dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf,
struct dom_document **doc);
/* Set a document's buffer */
diff --git a/include/dom/core/exceptions.h b/include/dom/core/exceptions.h
index fc5e247..e128016 100644
--- a/include/dom/core/exceptions.h
+++ b/include/dom/core/exceptions.h
@@ -8,6 +8,18 @@
#ifndef dom_core_exceptions_h_
#define dom_core_exceptions_h_
+/**
+ * Class of a DOM exception.
+ *
+ * The top 16 bits of a dom_exception are a bitfield
+ * indicating which class the exception belongs to.
+ */
+typedef enum {
+ DOM_EXCEPTION_CLASS_NORMAL = 0,
+ DOM_EXCEPTION_CLASS_EVENT = (1<<30),
+ DOM_EXCEPTION_CLASS_INTERNAL = (1<<31)
+} dom_exception_class;
+
/* The DOM spec says that this is actually an unsigned short */
typedef enum {
DOM_NO_ERR = 0,
@@ -28,7 +40,11 @@ typedef enum {
DOM_INVALID_ACCESS_ERR = 15,
DOM_VALIDATION_ERR = 16,
DOM_TYPE_MISMATCH_ERR = 17,
- DOM_NO_MEM_ERR = (1<<16)
+
+ DOM_UNSPECIFIED_EVENT_TYPE_ERR = DOM_EXCEPTION_CLASS_EVENT + 0,
+ DOM_DISPATCH_REQUEST_ERR = DOM_EXCEPTION_CLASS_EVENT + 1,
+
+ DOM_NO_MEM_ERR = DOM_EXCEPTION_CLASS_INTERNAL + 0
/* our own internal error */
} dom_exception;
diff --git a/include/dom/core/implementation.h b/include/dom/core/implementation.h
index cb95f84..92cce99 100644
--- a/include/dom/core/implementation.h
+++ b/include/dom/core/implementation.h
@@ -11,6 +11,7 @@
#include <stdbool.h>
#include <dom/core/exceptions.h>
+#include <dom/events/document_event.h>
#include <dom/functypes.h>
#include <dom/core/string.h>
@@ -38,6 +39,7 @@ dom_exception dom_implementation_create_document(
struct dom_string *namespace, struct dom_string *qname,
struct dom_document_type *doctype,
dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf,
struct dom_document **doc);
dom_exception dom_implementation_get_feature(
diff --git a/include/dom/events/custom_event.h b/include/dom/events/custom_event.h
new file mode 100644
index 0000000..cb97732
--- /dev/null
+++ b/include/dom/events/custom_event.h
@@ -0,0 +1,32 @@
+/*
+ * 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_custom_event_h_
+#define dom_events_custom_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+
+struct dom_string;
+
+typedef struct dom_custom_event dom_custom_event;
+
+dom_exception _dom_custom_event_get_detail(dom_custom_event *evt,
+ void **detail);
+#define dom_custom_event_get_detail(e, d) \
+ _dom_custom_event_get_detail((dom_custom_event *) (e),\
+ (void **) (d))
+
+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);
+#define dom_custom_event_init_ns(e, n, t, b, c, d) \
+ _dom_custom_event_init_ns((dom_custom_event *) (e), \
+ (struct dom_string *) (n), (struct dom_string *) (t), \
+ (bool) (b), (bool) (c), (void *) (d))
+
+#endif
diff --git a/include/dom/events/document_event.h b/include/dom/events/document_event.h
new file mode 100644
index 0000000..e349bc2
--- /dev/null
+++ b/include/dom/events/document_event.h
@@ -0,0 +1,47 @@
+/*
+ * 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_document_event_h_
+#define dom_events_document_event_h_
+
+#include <dom/core/exceptions.h>
+
+struct dom_string;
+struct dom_event;
+struct dom_document;
+struct lwc_context_s;
+struct lwc_string_s;
+
+typedef struct dom_document dom_document_event;
+
+/**
+ * The default action fetcher
+ *
+ * @note: When the implementation reach the end of the event flow, it will call
+ * this function to get the default action handler. If it does not return a
+ * NULL, the returned dom_event_listener will be invoked as the event is not
+ * canceled.
+ */
+typedef struct dom_event_listener *(*dom_events_default_action_fetcher)
+ (struct lwc_string_s *name, struct lwc_string_s *type);
+
+dom_exception _dom_document_event_create_event(dom_document_event *de,
+ struct dom_string *type, struct dom_event **evt);
+#define dom_document_event_create_event(d, t, e) \
+ _dom_document_event_create_event((dom_document_event *) (d), \
+ (struct dom_string *) (t), (struct dom_event **) (e))
+
+dom_exception _dom_document_event_can_dispatch(dom_document_event *de,
+ struct dom_string *namespace, struct dom_string *type,
+ bool* can);
+#define dom_document_event_can_dispatch(d, n, t, c) \
+ _dom_document_event_can_dispatch((dom_document_event *) (d), \
+ (struct dom_string *) (n), (struct dom_string *) (t),\
+ (bool *) (c))
+
+#endif
+
diff --git a/include/dom/events/event.h b/include/dom/events/event.h
new file mode 100644
index 0000000..df50f2e
--- /dev/null
+++ b/include/dom/events/event.h
@@ -0,0 +1,93 @@
+/*
+ * 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_event_h_
+#define dom_events_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+#include <dom/events/event_target.h>
+
+struct dom_string;
+
+typedef enum {
+ DOM_CAPTURING_PHASE = 1,
+ DOM_AT_TARGET = 2,
+ DOM_BUBBLING_PHASE = 3
+} dom_event_flow_phase;
+
+typedef struct dom_event dom_event;
+
+/* The ref/unref methods define */
+void _dom_event_ref(dom_event *evt);
+#define dom_event_ref(n) _dom_event_ref((dom_event *) (n))
+void _dom_event_unref(dom_event *evt);
+#define dom_event_unref(n) _dom_event_unref((dom_event *) (n))
+
+dom_exception _dom_event_get_type(dom_event *evt, struct dom_string **type);
+#define dom_event_get_type(e, t) _dom_event_get_type((dom_event *) (e), \
+ (struct dom_string **) (t))
+
+dom_exception _dom_event_get_target(dom_event *evt, dom_event_target **target);
+#define dom_event_get_target(e, t) _dom_event_get_target((dom_event *) (e), \
+ (dom_event_target **) (t))
+
+dom_exception _dom_event_get_current_target(dom_event *evt,
+ dom_event_target **current);
+#define dom_event_get_current_target(e, c) _dom_event_get_current_target(\
+ (dom_event *) (e), (dom_event_target **) (c))
+
+dom_exception _dom_event_get_bubbles(dom_event *evt, bool *bubbles);
+#define dom_event_get_bubbles(e, b) _dom_event_get_bubbles((dom_event *) (e), \
+ (bool *) (b))
+
+dom_exception _dom_event_get_cancelable(dom_event *evt, bool *cancelable);
+#define dom_event_get_cancelable(e, c) _dom_event_get_cancelable(\
+ (dom_event *) (e), (bool *) (c))
+
+dom_exception _dom_event_get_timestamp(dom_event *evt,
+ unsigned int *timestamp);
+#define dom_event_get_timestamp(e, t) _dom_event_get_timestamp(\
+ (dom_event *) (e), (unsigned int *) (t))
+
+dom_exception _dom_event_stop_propagation(dom_event *evt);
+#define dom_event_stop_propagation(e) _dom_event_stop_propagation(\
+ (dom_event *) (e))
+
+dom_exception _dom_event_prevent_default(dom_event *evt);
+#define dom_event_prevent_default(e) _dom_event_prevent_default(\
+ (dom_event *) (e))
+
+dom_exception _dom_event_init(dom_event *evt, struct dom_string *type,
+ bool bubble, bool cancelable);
+#define dom_event_init(e, t, b, c) _dom_event_init((dom_event *) (e), \
+ (struct dom_string *) (t), (bool) (b), (bool) (c))
+
+dom_exception _dom_event_get_namespace(dom_event *evt,
+ struct dom_string **namespace);
+#define dom_event_get_namespace(e, n) _dom_event_get_namespace(\
+ (dom_event *) (e), (struct dom_string **) (n))
+
+dom_exception _dom_event_is_custom(dom_event *evt, bool *custom);
+#define dom_event_is_custom(e, c) _dom_event_is_custom((dom_event *) (e), \
+ (bool *) (c))
+
+dom_exception _dom_event_stop_immediate_propagation(dom_event *evt);
+#define dom_event_stop_immediate_propagation(e) \
+ _dom_event_stop_immediate_propagation((dom_event *) (e))
+
+dom_exception _dom_event_is_default_prevented(dom_event *evt, bool *prevented);
+#define dom_event_is_default_prevented(e, p) \
+ _dom_event_is_default_prevented((dom_event *) (e), (bool *) (p))
+
+dom_exception _dom_event_init_ns(dom_event *evt, struct dom_string *namespace,
+ struct dom_string *type, bool bubble, bool cancelable);
+#define dom_event_init_ns(e, n, t, b, c) _dom_event_init_ns( \
+ (dom_event *) (e), (struct dom_string *) (n), \
+ (struct dom_string *) (t), (bool) (b), (bool) (c))
+
+#endif
diff --git a/include/dom/events/event_listener.h b/include/dom/events/event_listener.h
new file mode 100644
index 0000000..cb7ff15
--- /dev/null
+++ b/include/dom/events/event_listener.h
@@ -0,0 +1,27 @@
+/*
+ * 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_event_listener_h_
+#define dom_events_event_listener_h_
+
+#include <dom/core/exceptions.h>
+
+struct dom_document;
+struct dom_event;
+
+typedef void (*handle_event)(struct dom_event *evt, void *pw);
+
+typedef struct dom_event_listener dom_event_listener;
+
+dom_exception dom_event_listener_create(struct dom_document *doc,
+ handle_event handler, void *pw, dom_event_listener **listener);
+
+void dom_event_listener_ref(dom_event_listener *listener);
+void dom_event_listener_unref(dom_event_listener *listener);
+
+#endif
+
diff --git a/include/dom/events/event_target.h b/include/dom/events/event_target.h
new file mode 100644
index 0000000..bf3233e
--- /dev/null
+++ b/include/dom/events/event_target.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_events_event_target_h_
+#define dom_events_event_target_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+
+struct dom_string;
+struct dom_event_listener;
+struct dom_event;
+struct dom_node_internal;
+
+typedef struct dom_node_internal dom_event_target;
+
+dom_exception _dom_event_target_add_event_listener(dom_event_target *et,
+ struct dom_string *type, struct dom_event_listener *listener,
+ bool capture);
+#define dom_event_target_add_event_listener(et, t, l, c) \
+ _dom_event_target_add_event_listener((dom_event_target *) (et),\
+ (struct dom_string *) (t), (struct dom_event_listener *) (l), \
+ (bool) (c))
+
+dom_exception _dom_event_target_remove_event_listener(dom_event_target *et,
+ struct dom_string *type, struct dom_event_listener *listener,
+ bool capture);
+#define dom_event_target_remove_event_listener(et, t, l, c) \
+ _dom_event_target_remove_event_listener(\
+ (dom_event_target *) (et), (struct dom_string *) (t),\
+ (struct dom_event_listener *) (l), (bool) (c))
+
+dom_exception _dom_event_target_dispatch_event(dom_event_target *et,
+ struct dom_event *evt, bool *success);
+#define dom_event_target_dispatch_event(et, e, s) \
+ _dom_event_target_dispatch_event((dom_event_target *) (et),\
+ (struct dom_event *) (e), (bool *) (s))
+
+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);
+#define dom_event_target_add_event_listener_ns(et, n, t, l, c) \
+ _dom_event_target_add_event_listener_ns(\
+ (dom_event_target *) (et), (struct dom_string *) (n),\
+ (struct dom_string *) (t), (struct dom_event_listener *) (l),\
+ (bool) (c))
+
+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);
+#define dom_event_target_remove_event_listener_ns(et, n, t, l, c) \
+ _dom_event_target_remove_event_listener_ns(\
+ (dom_event_target *) (et), (struct dom_string *) (n),\
+ (struct dom_string *) (t), (struct dom_event_listener *) (l),\
+ (bool) (c))
+
+#endif
+
diff --git a/include/dom/events/events.h b/include/dom/events/events.h
new file mode 100644
index 0000000..39a8fe7
--- /dev/null
+++ b/include/dom/events/events.h
@@ -0,0 +1,25 @@
+/*
+ * 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_h_
+#define dom_events_h_
+
+#include <dom/events/event.h>
+#include <dom/events/ui_event.h>
+#include <dom/events/custom_event.h>
+#include <dom/events/mouse_event.h>
+#include <dom/events/keyboard_event.h>
+#include <dom/events/mouse_wheel_event.h>
+#include <dom/events/mouse_multi_wheel_event.h>
+#include <dom/events/mutation_event.h>
+#include <dom/events/mutation_name_event.h>
+#include <dom/events/text_event.h>
+#include <dom/events/event_listener.h>
+#include <dom/events/document_event.h>
+#include <dom/events/event_target.h>
+
+#endif
diff --git a/include/dom/events/keyboard_event.h b/include/dom/events/keyboard_event.h
new file mode 100644
index 0000000..bbac4a1
--- /dev/null
+++ b/include/dom/events/keyboard_event.h
@@ -0,0 +1,89 @@
+/*
+ * 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_keyboard_event_h_
+#define dom_events_keyboard_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+
+struct dom_string;
+struct dom_abstract_view;
+
+typedef struct dom_keyboard_event dom_keyboard_event;
+
+typedef enum {
+ DOM_KEY_LOCATION_STANDARD = 0,
+ DOM_KEY_LOCATION_LEFT = 1,
+ DOM_KEY_LOCATION_RIGHT = 2,
+ DOM_KEY_LOCATION_NUMPAD = 3
+} dom_key_location;
+
+dom_exception _dom_keyboard_event_get_key_identifier(dom_keyboard_event *evt,
+ struct dom_string **ident);
+#define dom_keyboard_event_get_key_identifier(e, i) \
+ _dom_keyboard_event_get_key_identifier( \
+ (dom_keyboard_event *) (e), (struct dom_string **) (i))
+
+dom_exception _dom_keyboard_event_get_key_location(dom_keyboard_event *evt,
+ dom_key_location *loc);
+#define dom_keyboard_event_get_key_location(e, l) \
+ _dom_keyboard_event_get_key_location( \
+ (dom_keyboard_event *) (e), (dom_key_location *) (l))
+
+dom_exception _dom_keyboard_event_get_ctrl_key(dom_keyboard_event *evt,
+ bool *key);
+#define dom_keyboard_event_get_ctrl_key(e, k) _dom_keyboard_event_get_ctrl_key(\
+ (dom_keyboard_event *) (e), (bool *) (k))
+
+dom_exception _dom_keyboard_event_get_shift_key(dom_keyboard_event *evt,
+ bool *key);
+#define dom_keyboard_event_get_shift_key(e, k) \
+ _dom_keyboard_event_get_shift_key((dom_keyboard_event *) (e), \
+ (bool *) (k))
+
+dom_exception _dom_keyboard_event_get_alt_key(dom_keyboard_event *evt,
+ bool *key);
+#define dom_keyboard_event_get_alt_key(e, k) _dom_keyboard_event_get_alt_key(\
+ (dom_keyboard_event *) (e), (bool *) (k))
+
+dom_exception _dom_keyboard_event_get_meta_key(dom_keyboard_event *evt,
+ bool *key);
+#define dom_keyboard_event_get_meta_key(e, k) _dom_keyboard_event_get_meta_key(\
+ (dom_keyboard_event *) (e), (bool *) (k))
+
+dom_exception _dom_keyboard_event_get_modifier_state(dom_keyboard_event *evt,
+ struct dom_string *m, bool *state);
+#define dom_keyboard_event_get_modifier_state(e, m, s) \
+ _dom_keyboard_event_get_modifier_state( \
+ (dom_keyboard_event *) (e), (struct dom_string *) (m),\
+ (bool *) (s))
+
+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);
+#define dom_keyboard_event_init(e, t, b, c, v, ki, kl, m) \
+ _dom_keyboard_event_init((dom_keyboard_event *) (e), \
+ (struct dom_string *) (t), (bool) (b), (bool) (c), \
+ (struct dom_abstract_view *) (v), (struct dom_string *) (ki), \
+ (dom_key_location) (kl), (struct dom_string *) (m))
+
+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);
+#define dom_keyboard_event_init_ns(e, n, t, b, c, v, ki, kl, m) \
+ _dom_keyboard_event_init_ns((dom_keyboard_event *) (e), \
+ (struct dom_string *) (n), (struct dom_string *) (t), \
+ (bool) (b), (bool) (c), (struct dom_abstract_view *) (v), \
+ (struct dom_string *) (ki), (dom_key_location) (kl), \
+ (struct dom_string *) (m))
+
+#endif
+
diff --git a/include/dom/events/mouse_event.h b/include/dom/events/mouse_event.h
new file mode 100644
index 0000000..c153dd8
--- /dev/null
+++ b/include/dom/events/mouse_event.h
@@ -0,0 +1,108 @@
+/*
+ * 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_mouse_event_h_
+#define dom_events_mouse_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+#include <dom/events/event_target.h>
+
+struct dom_string;
+struct dom_abstract_view;
+
+typedef struct dom_mouse_event dom_mouse_event;
+
+dom_exception _dom_mouse_event_get_screen_x(dom_mouse_event *evt,
+ long *x);
+#define dom_mouse_event_get_screen_x(e, x) _dom_mouse_event_get_screen_x(\
+ (dom_mouse_event *) (e), (long *) (x))
+
+dom_exception _dom_mouse_event_get_screen_y(dom_mouse_event *evt,
+ long *y);
+#define dom_mouse_event_get_screen_y(e, y) _dom_mouse_event_get_screen_y(\
+ (dom_mouse_event *) (e), (long *) (y))
+
+dom_exception _dom_mouse_event_get_client_x(dom_mouse_event *evt,
+ long *x);
+#define dom_mouse_event_get_client_x(e, x) _dom_mouse_event_get_client_x(\
+ (dom_mouse_event *) (e), (long *) (x))
+
+dom_exception _dom_mouse_event_get_client_y(dom_mouse_event *evt,
+ long *y);
+#define dom_mouse_event_get_client_y(e, y) _dom_mouse_event_get_client_y(\
+ (dom_mouse_event *) (e), (long *) (y))
+
+dom_exception _dom_mouse_event_get_ctrl_key(dom_mouse_event *evt,
+ bool *key);
+#define dom_mouse_event_get_ctrl_key(e, k) _dom_mouse_event_get_ctrl_key( \
+ (dom_mouse_event *) (e), (bool *) (k))
+
+dom_exception _dom_mouse_event_get_shift_key(dom_mouse_event *evt,
+ bool *key);
+#define dom_mouse_event_get_shift_key(e, k) _dom_mouse_event_get_shift_key( \
+ (dom_mouse_event *) (e), (bool *) (k))
+
+dom_exception _dom_mouse_event_get_alt_key(dom_mouse_event *evt,
+ bool *key);
+#define dom_mouse_event_get_alt_key(e, k) _dom_mouse_event_get_alt_key( \
+ (dom_mouse_event *) (e), (bool *) (k))
+
+dom_exception _dom_mouse_event_get_meta_key(dom_mouse_event *evt,
+ bool *key);
+#define dom_mouse_event_get_meta_key(e, k) _dom_mouse_event_get_meta_key( \
+ (dom_mouse_event *) (e), (bool *) (k))
+
+dom_exception _dom_mouse_event_get_button(dom_mouse_event *evt,
+ unsigned short *button);
+#define dom_mouse_event_get_button(e, b) _dom_mouse_event_get_button(\
+ (dom_mouse_event *) (e), (unsigned short *) (b))
+
+dom_exception _dom_mouse_event_get_related_target(dom_mouse_event *evt,
+ dom_event_target **et);
+#define dom_mouse_event_get_related_target(e, t) \
+ _dom_mouse_event_get_related_target((dom_mouse_event *) (e),\
+ (dom_event_target **) (t))
+
+dom_exception _dom_mouse_event_get_modifier_state(dom_mouse_event *evt,
+ struct dom_string *m, bool *state);
+#define dom_mouse_event_get_modifier_state(e, m, s) \
+ _dom_mouse_event_get_modifier_state((dom_mouse_event *) (e), \
+ (struct dom_string *) (m), (bool *) (s))
+
+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);
+#define dom_mouse_event_init(e, t, b, c, v, d, sx, sy, cx, cy, ctrl, alt, \
+ shift, meta, button, et) \
+ _dom_mouse_event_init((dom_mouse_event *) (e), \
+ (struct dom_string *) (t), (bool) (b), (bool) (c),\
+ (struct dom_abstract_view *) (v), (long) (d), (long) (sx), \
+ (long) (sy), (long) (cx), (long) (cy), (bool) (ctrl),\
+ (bool) (alt), (bool) (shift), (bool) (meta), \
+ (unsigned short) (button), (dom_event_target *) (et))
+
+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);
+#define dom_mouse_event_init_ns(e, n, t, b, c, v, d, sx, sy, cx, cy, ctrl, alt,\
+ shift, meta, button, et) \
+ _dom_mouse_event_init_ns((dom_mouse_event *) (e), \
+ (struct dom_string *) (n), (struct dom_string *) (t),\
+ (bool) (b), (bool) (c), (struct dom_abstract_view *) (v),\
+ (long) (d), (long) (sx), (long) (sy), (long) (cx),\
+ (long) (cy), (bool) (ctrl), (bool) (alt), (bool) (shift),\
+ (bool) (meta), (unsigned short) (button),\
+ (dom_event_target *) (et))
+
+#endif
diff --git a/include/dom/events/mouse_multi_wheel_event.h b/include/dom/events/mouse_multi_wheel_event.h
new file mode 100644
index 0000000..7bb85ff
--- /dev/null
+++ b/include/dom/events/mouse_multi_wheel_event.h
@@ -0,0 +1,56 @@
+/*
+ * 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_mouse_multi_wheel_event_h_
+#define dom_events_mouse_multi_wheel_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+#include <dom/events/event_target.h>
+
+struct dom_string;
+struct dom_abstract_view;
+
+typedef struct dom_mouse_multi_wheel_event dom_mouse_multi_wheel_event;
+
+dom_exception _dom_mouse_multi_wheel_event_get_wheel_delta_x(
+ dom_mouse_multi_wheel_event *evt, long *x);
+#define dom_mouse_multi_wheel_event_get_wheel_delta_x(e, x) \
+ _dom_mouse_multi_wheel_event_get_wheel_delta_x( \
+ (dom_mouse_multi_wheel_event *) (e), (long *) (x))
+
+dom_exception _dom_mouse_multi_wheel_event_get_wheel_delta_y(
+ dom_mouse_multi_wheel_event *evt, long *y);
+#define dom_mouse_multi_wheel_event_get_wheel_delta_y(e, y) \
+ _dom_mouse_multi_wheel_event_get_wheel_delta_y( \
+ (dom_mouse_multi_wheel_event *) (e), (long *) (y))
+
+dom_exception _dom_mouse_multi_wheel_event_get_wheel_delta_z(
+ dom_mouse_multi_wheel_event *evt, long *z);
+#define dom_mouse_multi_wheel_event_get_wheel_delta_z(e, z) \
+ _dom_mouse_multi_wheel_event_get_wheel_delta_z( \
+ (dom_mouse_multi_wheel_event *) (e), (long *) (z))
+
+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);
+#define dom_mouse_multi_wheel_event_init_ns(e, n, t, b, c, v, \
+ d, sx, sy, cx, cy, button, et, ml, x, y, z) \
+ _dom_mouse_multi_wheel_event_init_ns( \
+ (dom_mouse_multi_wheel_event *) (e), (struct dom_string *) (n),\
+ (struct dom_string *) (t), (bool) (b), (bool) (c), \
+ (struct dom_abstract_view *) (v), (long) (d), (long) (sx), \
+ (long) (sy), (long) (cx), (long) (cy),\
+ (unsigned short) (button), (dom_event_target *) (et),\
+ (struct dom_string *) (ml), (long) (x), (long) (y), (long) (z))
+
+#endif
diff --git a/include/dom/events/mouse_wheel_event.h b/include/dom/events/mouse_wheel_event.h
new file mode 100644
index 0000000..5f1e83c
--- /dev/null
+++ b/include/dom/events/mouse_wheel_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_events_mouse_wheel_event_h_
+#define dom_events_mouse_wheel_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+#include <dom/events/event_target.h>
+
+struct dom_string;
+struct dom_abstract_view;
+
+typedef struct dom_mouse_wheel_event dom_mouse_wheel_event;
+
+dom_exception _dom_mouse_wheel_event_get_wheel_delta(
+ dom_mouse_wheel_event *evt, long *d);
+#define dom_mouse_wheel_event_get_wheel_delta(e, d) \
+ _dom_mouse_wheel_event_get_wheel_delta( \
+ (dom_mouse_wheel_event *) (e), (long *) (d))
+
+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);
+#define dom_mouse_wheel_event_init_ns(e, n, t, b, c, v, \
+ d, sx, sy, cx, cy, button, et, ml, dt) \
+ _dom_mouse_wheel_event_init_ns((dom_mouse_wheel_event *) (e), \
+ (struct dom_string *) (n), (struct dom_string *) (t), \
+ (bool) (b), (bool) (c), (struct dom_abstract_view *) (v),\
+ (long) (d), (long) (sx), (long) (sy), (long) (cx), (long) (cy),\
+ (unsigned short) (button), (dom_event_target *) (et),\
+ (struct dom_string *) (ml), (long) (dt))
+
+#endif
+
diff --git a/include/dom/events/mutation_event.h b/include/dom/events/mutation_event.h
new file mode 100644
index 0000000..9dc3fdd
--- /dev/null
+++ b/include/dom/events/mutation_event.h
@@ -0,0 +1,80 @@
+/*
+ * 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_mutation_event_h_
+#define dom_events_mutation_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+
+struct dom_string;
+struct dom_node;
+
+typedef enum {
+ DOM_MUTATION_MODIFICATION = 1,
+ DOM_MUTATION_ADDITION = 2,
+ DOM_MUTATION_REMOVAL = 3
+} dom_mutation_type;
+
+typedef struct dom_mutation_event dom_mutation_event;
+
+dom_exception _dom_mutation_event_get_related_node(dom_mutation_event *evt,
+ struct dom_node **node);
+#define dom_mutation_event_get_related_node(e, n) \
+ _dom_mutation_event_get_related_node(\
+ (dom_mutation_event *) (e), (struct dom_node **) (n))
+
+dom_exception _dom_mutation_event_get_prev_value(dom_mutation_event *evt,
+ struct dom_string **ret);
+#define dom_mutation_event_get_prev_value(e, r) \
+ _dom_mutation_event_get_prev_value((dom_mutation_event *) (e), \
+ (struct dom_string **) (r))
+
+dom_exception _dom_mutation_event_get_new_value(dom_mutation_event *evt,
+ struct dom_string **ret);
+#define dom_mutation_event_get_new_value(e, r) \
+ _dom_mutation_event_get_new_value((dom_mutation_event *) (e), \
+ (struct dom_string **) (r))
+
+dom_exception _dom_mutation_event_get_attr_name(dom_mutation_event *evt,
+ struct dom_string **ret);
+#define dom_mutation_event_get_attr_name(e, r) \
+ _dom_mutation_event_get_attr_name((dom_mutation_event *) (e), \
+ (struct dom_string **) (r))
+
+dom_exception _dom_mutation_event_get_attr_change(dom_mutation_event *evt,
+ dom_mutation_type *type);
+#define dom_mutation_event_get_attr_change(e, t) \
+ _dom_mutation_event_get_attr_change((dom_mutation_event *) (e),\
+ (dom_mutation_type *) (t))
+
+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);
+#define dom_mutation_event_init(e, t, b, c, n, p, nv, a, ch) \
+ _dom_mutation_event_init((dom_mutation_event *) (e), \
+ (struct dom_string *) (t), (bool) (b), (bool) (c), \
+ (struct dom_node *) (n), (struct dom_string *) (p), \
+ (struct dom_string *) (nv), (struct dom_string *) (a), \
+ (dom_mutation_type) (ch))
+
+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);
+#define dom_mutation_event_init_ns(e, n, t, b, c, nd, p, nv, a, ch) \
+ _dom_mutation_event_init_ns((dom_mutation_event *) (e), \
+ (struct dom_string *) (n), (struct dom_string *) (t),\
+ (bool) (b), (bool) (c), (struct dom_node *) (nd), \
+ (struct dom_string *) (p), (struct dom_string *) (nv),\
+ (struct dom_string *) (a), (dom_mutation_type) (ch))
+
+#endif
+
diff --git a/include/dom/events/mutation_name_event.h b/include/dom/events/mutation_name_event.h
new file mode 100644
index 0000000..13d27a4
--- /dev/null
+++ b/include/dom/events/mutation_name_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_events_mutation_name_event_h_
+#define dom_events_mutation_name_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+
+struct dom_string;
+struct dom_node;
+
+typedef struct dom_mutation_name_event dom_mutation_name_event;
+
+dom_exception _dom_mutation_name_event_get_prev_namespace(
+ dom_mutation_name_event *evt, struct dom_string **namespace);
+#define dom_mutation_name_event_get_prev_namespace(e, n) \
+ _dom_mutation_name_event_get_prev_namespace(\
+ (dom_mutation_name_event *) (e), (struct dom_string **) (n))
+
+dom_exception _dom_mutation_name_event_get_prev_node_name(
+ dom_mutation_name_event *evt, struct dom_string **name);
+#define dom_mutation_name_event_get_prev_node_name(e, n) \
+ _dom_mutation_name_event_get_prev_node_name(\
+ (dom_mutation_name_event *) (e), (struct dom_string **) (n))
+
+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);
+#define dom_mutation_name_event_init(e, t, b, c, n, p, pn) \
+ _dom_mutation_name_event_init((dom_mutation_name_event *) (e), \
+ (struct dom_string *) (t), (bool) (b), (bool) (c), \
+ (struct dom_node *) (n), (struct dom_string *) (p), \
+ (struct dom_string *) (pn))
+
+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);
+#define dom_mutation_name_event_init_ns(e, n, t, b, c, nv, p, pn) \
+ _dom_mutation_name_event_init_ns(\
+ (dom_mutation_name_event *) (e), (struct dom_string *) (n),\
+ (struct dom_string *) (t), (bool) (b), (bool) (c),\
+ (struct dom_node *) (nv), (struct dom_string *) (p), \
+ (struct dom_string *) (pn))
+
+#endif
+
+
diff --git a/include/dom/events/text_event.h b/include/dom/events/text_event.h
new file mode 100644
index 0000000..cf040ce
--- /dev/null
+++ b/include/dom/events/text_event.h
@@ -0,0 +1,41 @@
+/*
+ * 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_text_event_h_
+#define dom_events_text_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+
+struct dom_abstract_view;
+struct dom_string;
+
+typedef struct dom_text_event dom_text_event;
+
+dom_exception _dom_text_event_get_data(dom_text_event *evt,
+ struct dom_string **data);
+#define dom_text_event_get_data(e, d) _dom_text_event_get_data(\
+ (dom_text_event *) (e), (struct dom_string **) (d))
+
+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);
+#define dom_text_event_init(e, t, b, c, v, d) _dom_text_event_init( \
+ (dom_text_event *) (e), (struct dom_string *) (t), (bool) (b), \
+ (bool) (c), (struct dom_abstract_view *) (v),\
+ (struct dom_string *) (d))
+
+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);
+#define dom_text_event_init_ns(e, n, t, b, c, v, d) _dom_text_event_init_ns( \
+ (dom_text_event *) (e), (struct dom_string *) (n), \
+ (struct dom_string *) (t), (bool) (b), (bool) (c), \
+ (struct dom_abstract_view *) (v), (struct dom_string *) (d))
+
+#endif
diff --git a/include/dom/events/ui_event.h b/include/dom/events/ui_event.h
new file mode 100644
index 0000000..eaded99
--- /dev/null
+++ b/include/dom/events/ui_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_events_ui_event_h_
+#define dom_events_ui_event_h_
+
+#include <stdbool.h>
+#include <dom/core/exceptions.h>
+
+struct dom_string;
+struct dom_abstract_view;
+
+typedef struct dom_ui_event dom_ui_event;
+
+dom_exception _dom_ui_event_get_view(dom_ui_event *evt,
+ struct dom_abstract_view **view);
+#define dom_ui_event_get_view(e, v) _dom_ui_event_get_view( \
+ (dom_ui_event *) (e), (struct dom_abstract_view **) (v))
+
+dom_exception _dom_ui_event_get_detail(dom_ui_event *evt,
+ long *detail);
+#define dom_ui_event_get_detail(e, d) _dom_ui_event_get_detail(\
+ (dom_ui_event *) (e), (long *) (d))
+
+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);
+#define dom_ui_event_init(e, t, b, c, v, d) _dom_ui_event_init( \
+ (dom_ui_event *) (e), (struct dom_string *) (t), (bool) (b), \
+ (bool) (c), (struct dom_abstract_view *) (v), (long) (d))
+
+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);
+#define dom_ui_event_init_ns(e, n, t, b, c, v, d) _dom_ui_event_init_ns( \
+ (dom_ui_event *) (e), (struct dom_string *) (n), \
+ (struct dom_string *) (t), (bool) (b), (bool) (c), \
+ (struct dom_abstract_view *) (v), (long) (d))
+
+#endif
diff --git a/src/bootstrap/implementation.c b/src/bootstrap/implementation.c
index d14fa5b..bb0e125 100644
--- a/src/bootstrap/implementation.c
+++ b/src/bootstrap/implementation.c
@@ -59,6 +59,7 @@ static dom_exception impl_implementation_create_document(
struct dom_string *qname,
struct dom_document_type *doctype,
dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf,
struct dom_document **doc);
static dom_exception impl_implementation_get_feature(
struct dom_implementation *impl,
@@ -286,6 +287,7 @@ dom_exception impl_implementation_create_document(
struct dom_string *qname,
struct dom_document_type *doctype,
dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf,
struct dom_document **doc)
{
struct dom_document *d;
@@ -306,7 +308,7 @@ dom_exception impl_implementation_create_document(
}
/* Create document object */
- err = dom_document_create(impl, alloc, pw, ctx, &d);
+ err = dom_document_create(impl, alloc, pw, ctx, daf, &d);
if (err != DOM_NO_ERR)
return err;
diff --git a/src/core/characterdata.c b/src/core/characterdata.c
index f5b4094..6bb542d 100644
--- a/src/core/characterdata.c
+++ b/src/core/characterdata.c
@@ -10,11 +10,13 @@
#include <dom/core/characterdata.h>
#include <dom/core/string.h>
+#include <dom/events/events.h>
#include "core/characterdata.h"
#include "core/document.h"
#include "core/node.h"
#include "utils/utils.h"
+#include "events/mutation_event.h"
/* The virtual functions for dom_characterdata, we make this vtable
* public to each child class */
@@ -128,6 +130,15 @@ dom_exception _dom_characterdata_set_data(struct dom_characterdata *cdata,
return DOM_NO_MODIFICATION_ALLOWED_ERR;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ dom_exception err;
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
+ data, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
@@ -135,7 +146,8 @@ dom_exception _dom_characterdata_set_data(struct dom_characterdata *cdata,
dom_string_ref(data);
c->value = data;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
/**
@@ -223,13 +235,22 @@ dom_exception _dom_characterdata_append_data(struct dom_characterdata *cdata,
return err;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
+ temp, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
c->value = temp;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
/**
@@ -270,13 +291,22 @@ dom_exception _dom_characterdata_insert_data(struct dom_characterdata *cdata,
return err;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
+ temp, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
c->value = temp;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
/**
@@ -319,13 +349,22 @@ dom_exception _dom_characterdata_delete_data(struct dom_characterdata *cdata,
return err;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
+ temp, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
c->value = temp;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
/**
@@ -370,13 +409,22 @@ dom_exception _dom_characterdata_replace_data(struct dom_characterdata *cdata,
return err;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value, temp,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
c->value = temp;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
diff --git a/src/core/document.c b/src/core/document.c
index 6bd0045..b15eef3 100644
--- a/src/core/document.c
+++ b/src/core/document.c
@@ -76,6 +76,7 @@ static dom_exception dom_document_dup_node(dom_document *doc,
* \param pw Pointer to client-specific private data
* \param doc Pointer to location to receive created document
* \param ctx The intern string context of this document
+ * \param daf The default action fetcher
* \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion.
*
* ::impl will have its reference count increased.
@@ -84,6 +85,7 @@ static dom_exception dom_document_dup_node(dom_document *doc,
*/
dom_exception dom_document_create(struct dom_implementation *impl,
dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf,
struct dom_document **doc)
{
struct dom_document *d;
@@ -103,7 +105,7 @@ dom_exception dom_document_create(struct dom_implementation *impl,
* reaches zero. Documents own themselves (this simplifies the
* rest of the code, as it doesn't need to special case Documents)
*/
- err = _dom_document_initialise(d, impl, alloc, pw, ctx);
+ err = _dom_document_initialise(d, impl, alloc, pw, ctx, daf);
if (err != DOM_NO_ERR) {
/* Clean up document */
alloc(d, 0, pw);
@@ -118,7 +120,8 @@ dom_exception dom_document_create(struct dom_implementation *impl,
/* Initialise the document */
dom_exception _dom_document_initialise(struct dom_document *doc,
struct dom_implementation *impl, dom_alloc alloc, void *pw,
- struct lwc_context_s *ctx)
+ struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf)
{
assert(ctx != NULL);
assert(alloc != NULL);
@@ -150,7 +153,8 @@ dom_exception _dom_document_initialise(struct dom_document *doc,
doc->id_name = NULL;
- return err;
+ /* We should not pass a NULL when all things hook up */
+ return _dom_document_event_internal_initialise(doc, &doc->dei, daf);
}
@@ -185,6 +189,8 @@ bool _dom_document_finalise(struct dom_document *doc)
if (doc->id_name != NULL)
lwc_context_string_unref(doc->context, doc->id_name);
lwc_context_unref(doc->context);
+
+ _dom_document_event_internal_finalise(doc, &doc->dei);
return true;
}
@@ -1302,7 +1308,7 @@ dom_exception _dom_document_create_string(struct dom_document *doc,
return dom_string_create(doc->alloc, doc->pw, data, len, result);
}
-/*
+/**
* Create a lwc_string
*
* \param doc The document object
@@ -1324,6 +1330,13 @@ dom_exception _dom_document_create_lwcstring(struct dom_document *doc,
return _dom_exception_from_lwc_error(lerr);
}
+/* Unref a lwc_string created by this document */
+void _dom_document_unref_lwcstring(struct dom_document *doc,
+ struct lwc_string_s *str)
+{
+ lwc_context_string_unref(doc->context, str);
+}
+
/* Simple accessor for lwc_context of this document */
struct lwc_context_s *_dom_document_get_intern_context(
struct dom_document *doc)
diff --git a/src/core/document.h b/src/core/document.h
index 145eddf..ea961a2 100644
--- a/src/core/document.h
+++ b/src/core/document.h
@@ -21,6 +21,8 @@
#include "utils/resource_mgr.h"
#include "utils/list.h"
+#include "events/document_event.h"
+
struct dom_document;
struct dom_namednodemap;
struct dom_node;
@@ -61,12 +63,16 @@ struct dom_document {
/**< The deletion pending list */
struct lwc_string_s *id_name; /**< The ID attribute's name */
+
+ dom_document_event_internal dei;
+ /**< The DocumentEVent interface */
};
/* Initialise the document */
dom_exception _dom_document_initialise(struct dom_document *doc,
struct dom_implementation *impl, dom_alloc alloc, void *pw,
- struct lwc_context_s *ctx);
+ struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf);
/* Finalise the document */
bool _dom_document_finalise(struct dom_document *doc);
@@ -77,6 +83,9 @@ dom_exception _dom_document_create_string(struct dom_document *doc,
/* Create a lwc_string from C string */
dom_exception _dom_document_create_lwcstring(struct dom_document *doc,
const uint8_t *data, size_t len, struct lwc_string_s **result);
+/* Unref a lwc_string of this document */
+void _dom_document_unref_lwcstring(struct dom_document *doc,
+ struct lwc_string_s *str);
/* Create a dom_string from a lwc_string */
dom_exception _dom_document_create_string_from_lwcstring(
struct dom_document *doc, struct lwc_string_s *str,
diff --git a/src/core/element.c b/src/core/element.c
index 54bb9d1..7609b94 100644
--- a/src/core/element.c
+++ b/src/core/element.c
@@ -16,6 +16,7 @@
#include <dom/core/node.h>
#include <dom/core/string.h>
#include <dom/core/document.h>
+#include <dom/events/events.h>
#include "core/attr.h"
#include "core/document.h"
@@ -26,6 +27,7 @@
#include "utils/namespace.h"
#include "utils/utils.h"
#include "utils/hashtable.h"
+#include "events/mutation_event.h"
/* The three numbers are just random ones, maybe we should change it after some
* more consideration */
@@ -67,8 +69,6 @@ static dom_exception _dom_element_has_attr(struct dom_element *element,
static dom_exception _dom_element_set_id_attr(struct dom_element *element,
struct dom_hash_table *hs, struct dom_string *name, bool is_id);
-static unsigned int _dom_element_hash_lwcstring(void *key);
-
/* The operation set for namednodemap */
static dom_exception attributes_get_length(void *priv,
@@ -114,6 +114,7 @@ static void *_value(void *value, void *value_pw, dom_alloc alloc,
static void *_nsattributes(void *value, void *value_pw, dom_alloc alloc,
void *pw, bool clone);
+
/*----------------------------------------------------------------------*/
/* Constructors and Destructors */
@@ -183,14 +184,14 @@ dom_exception _dom_element_initialise(struct dom_element *el,
assert(doc != NULL);
err = _dom_document_create_hashtable(doc, CHAINS_ATTRIBUTES,
- _dom_element_hash_lwcstring, &el->attributes);
+ _dom_hash_hash_lwcstring, &el->attributes);
if (err != DOM_NO_ERR) {
_dom_document_alloc(doc, el, 0);
return err;
}
err = _dom_document_create_hashtable(doc, CHAINS_NAMESPACE,
- _dom_element_hash_lwcstring, &el->ns_attributes);
+ _dom_hash_hash_lwcstring, &el->ns_attributes);
if (err != DOM_NO_ERR) {
_dom_document_alloc(doc, el, 0);
_dom_document_alloc(doc, el->attributes, 0);
@@ -540,7 +541,7 @@ dom_exception _dom_element_set_attribute_ns(struct dom_element *element,
doc = dom_node_get_owner(element);
assert(doc != NULL);
err = _dom_document_create_hashtable(doc, CHAINS_NS_ATTRIBUTES,
- _dom_element_hash_lwcstring, &attrs);
+ _dom_hash_hash_lwcstring, &attrs);
if (err != DOM_NO_ERR)
return err;
@@ -686,7 +687,7 @@ dom_exception _dom_element_set_attribute_node_ns(struct dom_element *element,
doc = dom_node_get_owner(element);
assert(doc != NULL);
err = _dom_document_create_hashtable(doc, CHAINS_NS_ATTRIBUTES,
- _dom_element_hash_lwcstring, &attrs);
+ _dom_hash_hash_lwcstring, &attrs);
if (err != DOM_NO_ERR)
return err;
@@ -1218,7 +1219,7 @@ dom_exception _dom_element_get_attr(struct dom_element *element,
struct dom_string **value)
{
void *a;
- dom_exception err;
+ dom_exception err = DOM_NO_ERR;
lwc_string *str;
/* Looking for name */
@@ -1232,10 +1233,10 @@ dom_exception _dom_element_get_attr(struct dom_element *element,
if (a == NULL) {
*value = NULL;
} else {
- dom_attr_get_value(((struct dom_attr *) a), value);
+ err = dom_attr_get_value(((struct dom_attr *) a), value);
}
- return DOM_NO_ERR;
+ return err;
}
/**
@@ -1275,6 +1276,28 @@ dom_exception _dom_element_set_attr(struct dom_element *element,
/* Found an existing attribute, so replace its value */
dom_exception err;
+ /* Dispatch a DOMAttrModified event */
+ dom_string *old = NULL;
+ struct dom_document *doc = dom_node_get_owner(element);
+ bool success = true;
+ err = dom_attr_get_value(a, &old);
+ /* TODO: We did not support some node type such as entity
+ * reference, in that case, we should ignore the error to
+ * make sure the event model work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR)
+ return err;
+ err = _dom_dispatch_attr_modified_event(doc, e, old, value, a,
+ name, DOM_MUTATION_MODIFICATION, &success);
+ dom_string_unref(old);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) e, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
err = dom_attr_set_value((struct dom_attr *) a, value);
if (err != DOM_NO_ERR)
return err;
@@ -1294,6 +1317,26 @@ dom_exception _dom_element_set_attr(struct dom_element *element,
return err;
}
+ /* Dispatch a DOMAttrModified event */
+ struct dom_document *doc = dom_node_get_owner(element);
+ bool success = true;
+ err = _dom_dispatch_attr_modified_event(doc, e, NULL, value,
+ (dom_event_target *) attr, name,
+ DOM_MUTATION_ADDITION, &success);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(attr);
+ return err;
+ }
+
+ err = _dom_dispatch_node_change_event(doc,
+ (dom_event_target *) attr,
+ (dom_event_target *) element,
+ DOM_MUTATION_ADDITION, &success);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(attr);
+ return err;
+ }
+
added = _dom_hash_add(hs, str, attr, false);
if (added == false) {
/* If we failed at this step, there must be no memory */
@@ -1304,6 +1347,12 @@ dom_exception _dom_element_set_attr(struct dom_element *element,
dom_node_set_parent(attr, element);
dom_node_unref(attr);
dom_node_remove_pending(attr);
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) element, &success);
+ if (err != DOM_NO_ERR)
+ return err;
}
return DOM_NO_ERR;
@@ -1334,13 +1383,51 @@ dom_exception _dom_element_remove_attr(struct dom_element *element,
if (err != DOM_NO_ERR)
return err;
- a = (dom_node_internal *) _dom_hash_del(hs, str);
+ a = (dom_node_internal *) _dom_hash_get(hs, str);
/* Detach attr node from list */
if (a != NULL) {
+ /* Disptach DOMNodeRemoval event */
+ bool success = true;
+ struct dom_document *doc = dom_node_get_owner(element);
+ err = _dom_dispatch_node_change_event(doc,
+ (dom_event_target *) a,
+ (dom_event_target *) element,
+ DOM_MUTATION_REMOVAL, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ /* Delete the attribute node */
+ _dom_hash_del(hs, str);
+ /* Claim a reference for later event dispatch */
+ dom_node_ref(a);
+
/* And destroy attr */
dom_node_set_parent(a, NULL);
dom_node_try_destroy(a);
+
+ /* Dispatch a DOMAttrModified event */
+ success = true;
+ dom_string *old = NULL;
+ err = dom_attr_get_value(a, &old);
+ /* TODO: We did not support some node type such as entity
+ * reference, in that case, we should ignore the error to
+ * make sure the event model work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR)
+ return err;
+ err = _dom_dispatch_attr_modified_event(doc, e, old, NULL, a,
+ name, DOM_MUTATION_REMOVAL, &success);
+ dom_string_unref(old);
+ /* Release the reference */
+ dom_node_unref(a);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) e, &success);
+ if (err != DOM_NO_ERR)
+ return err;
}
/** \todo defaulted attribute handling */
@@ -1437,14 +1524,50 @@ dom_exception _dom_element_set_attr_node(struct dom_element *element,
if (err != DOM_NO_ERR)
return err;
- a = _dom_hash_del(hs, str);
+ a = _dom_hash_get(hs, str);
*result = NULL;
if (a != NULL) {
+ /* Disptach DOMNodeRemoval event */
+ bool success = true;
+ struct dom_document *doc = dom_node_get_owner(element);
+ err = _dom_dispatch_node_change_event(doc,
+ (dom_event_target *) a,
+ (dom_event_target *) element,
+ DOM_MUTATION_REMOVAL, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ _dom_hash_del(hs, str);
dom_node_ref(a);
*result = (dom_attr *) a;
dom_node_set_parent(a, NULL);
dom_node_mark_pending(a);
+
+ /* Dispatch a DOMAttrModified event */
+ dom_string *old = NULL;
+ success = true;
+ err = dom_attr_get_value(a, &old);
+ /* TODO: We did not support some node type such as entity
+ * reference, in that case, we should ignore the error to
+ * make sure the event model work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR) {
+ dom_node_unref(a);
+ return err;
+ }
+ err = _dom_dispatch_attr_modified_event(doc, e, old, NULL,
+ (dom_event_target *) a, name,
+ DOM_MUTATION_REMOVAL, &success);
+ dom_string_unref(old);
+ dom_node_unref(a);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) e, &success);
+ if (err != DOM_NO_ERR)
+ return err;
}
added = _dom_hash_add(hs, str, attr, false);
@@ -1455,10 +1578,39 @@ dom_exception _dom_element_set_attr_node(struct dom_element *element,
dom_node_set_parent(attr, element);
dom_node_remove_pending(attr);
+ /* Dispatch a DOMAttrModified event */
+ dom_string *new = NULL;
+ struct dom_document *doc = dom_node_get_owner(element);
+ bool success = true;
+ err = dom_attr_get_value(attr, &new);
+ /* TODO: We did not support some node type such as entity reference, in
+ * that case, we should ignore the error to make sure the event model
+ * work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR)
+ return err;
+ err = _dom_dispatch_attr_modified_event(doc, e, NULL, new,
+ (dom_event_target *) attr, name,
+ DOM_MUTATION_ADDITION, &success);
+ dom_string_unref(new);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ err = _dom_dispatch_node_change_event(doc, (dom_event_target *) attr,
+ (dom_event_target *) element, DOM_MUTATION_ADDITION,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
/* Cleanup */
if (name != NULL)
dom_string_unref(name);
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) element, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
return DOM_NO_ERR;
}
@@ -1500,7 +1652,7 @@ dom_exception _dom_element_remove_attr_node(struct dom_element *element,
if (err != DOM_NO_ERR)
return err;
- a = _dom_hash_del(hs, str);
+ a = _dom_hash_get(hs, str);
/* Now, cleaup the dom_string and lwc_string */
dom_string_unref(name);
@@ -1512,16 +1664,53 @@ dom_exception _dom_element_remove_attr_node(struct dom_element *element,
return DOM_NOT_FOUND_ERR;
}
+ /* Dispatch a DOMNodeRemoved event */
+ bool success = true;
+ struct dom_document *doc = dom_node_get_owner(element);
+ err = _dom_dispatch_node_change_event(doc, (dom_event_target *) a,
+ (dom_event_target *) element, DOM_MUTATION_REMOVAL,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ /* Delete the attribute node */
+ _dom_hash_del(hs, str);
+ dom_node_ref(a);
+
+ /* Dispatch a DOMAttrModified event */
+ dom_string *old = NULL;
+ success = true;
+ err = dom_attr_get_value(a, &old);
+ /* TODO: We did not support some node type such as entity reference, in
+ * that case, we should ignore the error to make sure the event model
+ * work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR) {
+ dom_node_unref(a);
+ return err;
+ }
+ err = _dom_dispatch_attr_modified_event(doc, e, old, NULL,
+ (dom_event_target *) a, name,
+ DOM_MUTATION_REMOVAL, &success);
+ dom_string_unref(old);
+ dom_node_unref(a);
+ if (err != DOM_NO_ERR)
+ return err;
+
/* When a Node is removed, it should be destroy. When its refcnt is not
* zero, it will be added to the document's deletion pending list.
* When a Node is removed, its parent should be NULL, but its owner
* should remain to be the document.
*/
- dom_node_ref(a);
*result = (dom_attr *) a;
dom_node_set_parent(a, NULL);
dom_node_mark_pending(a);
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc, (dom_event_target *) e,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
return DOM_NO_ERR;
}
@@ -1704,13 +1893,6 @@ dom_exception _dom_element_get_id(struct dom_element *ele, lwc_string **id)
}
-/* The hash function for attributes and id tables */
-unsigned int _dom_element_hash_lwcstring(void *key)
-{
- lwc_string *lstr = (lwc_string *) key;
-
- return lwc_string_hash_value(lstr);
-}
/*-------------- The dom_namednodemap functions -------------------------*/
diff --git a/src/core/implementation.c b/src/core/implementation.c
index e2b6763..30e1eb3 100644
--- a/src/core/implementation.c
+++ b/src/core/implementation.c
@@ -122,10 +122,11 @@ dom_exception dom_implementation_create_document(
struct dom_string *namespace, struct dom_string *qname,
struct dom_document_type *doctype,
dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf,
struct dom_document **doc)
{
return impl->create_document(impl, namespace, qname, doctype, alloc,
- pw, ctx, doc);
+ pw, ctx, daf, doc);
}
/**
diff --git a/src/core/node.c b/src/core/node.c
index 1c0b28f..1bdcade 100644
--- a/src/core/node.c
+++ b/src/core/node.c
@@ -17,6 +17,7 @@
#include <dom/core/nodelist.h>
#include <dom/core/implementation.h>
#include <dom/core/document_type.h>
+#include <dom/events/events.h>
#include "core/string.h"
#include "core/namednodemap.h"
@@ -33,15 +34,16 @@
#include "core/text.h"
#include "utils/utils.h"
#include "utils/resource_mgr.h"
+#include "events/mutation_event.h"
static bool _dom_node_permitted_child(const dom_node_internal *parent,
const dom_node_internal *child);
-static inline void _dom_node_attach(dom_node_internal *node,
+static inline dom_exception _dom_node_attach(dom_node_internal *node,
dom_node_internal *parent,
dom_node_internal *previous,
dom_node_internal *next);
static inline void _dom_node_detach(dom_node_internal *node);
-static inline void _dom_node_attach_range(dom_node_internal *first,
+static inline dom_exception _dom_node_attach_range(dom_node_internal *first,
dom_node_internal *last,
dom_node_internal *parent,
dom_node_internal *previous,
@@ -51,7 +53,6 @@ static inline void _dom_node_detach_range(dom_node_internal *first,
static inline void _dom_node_replace(dom_node_internal *old,
dom_node_internal *replacement);
-
static struct dom_node_vtable node_vtable = {
DOM_NODE_VTABLE
};
@@ -249,7 +250,7 @@ dom_exception _dom_node_initialise_generic(
dom_node_mark_pending(node);
}
- return DOM_NO_ERR;
+ return _dom_event_target_internal_initialise(doc, &node->eti);
}
/**
@@ -331,7 +332,14 @@ void _dom_node_finalise_generic(dom_node_internal *node, dom_alloc alloc,
if (node->name != NULL)
lwc_context_string_unref(ctx, node->name);
- /* Detach from the pending list, if we are in it */
+ /* If the node has no owner document, we need not to finalise its
+ * dom_event_target_internal structure.
+ */
+ if (node->owner != NULL)
+ _dom_event_target_internal_finalise(node->owner, &node->eti);
+
+ /* Detach from the pending list, if we are in it,
+ * this part of code should always be the end of this function. */
if (node->pending_list.prev != &node->pending_list) {
assert (node->pending_list.next != &node->pending_list);
list_del(&node->pending_list);
@@ -351,7 +359,8 @@ void _dom_node_finalise_generic(dom_node_internal *node, dom_alloc alloc,
*/
void _dom_node_ref(dom_node_internal *node)
{
- node->refcnt++;
+ if (node != NULL)
+ node->refcnt++;
}
@@ -816,6 +825,8 @@ dom_exception _dom_node_insert_before(dom_node_internal *node,
dom_node_internal *new_child, dom_node_internal *ref_child,
dom_node_internal **result)
{
+ dom_exception err;
+
/* Ensure that new_child and node are owned by the same document */
if ((new_child->type == DOM_DOCUMENT_TYPE_NODE &&
new_child->owner != NULL &&
@@ -874,24 +885,29 @@ dom_exception _dom_node_insert_before(dom_node_internal *node,
return DOM_HIERARCHY_REQUEST_ERR;
if (new_child->first_child != NULL) {
- _dom_node_attach_range(new_child->first_child,
+ err = _dom_node_attach_range(new_child->first_child,
new_child->last_child,
node,
ref_child == NULL ? node->last_child
: ref_child->previous,
ref_child == NULL ? NULL
: ref_child);
+ if (err != DOM_NO_ERR)
+ return err;
new_child->first_child = NULL;
new_child->last_child = NULL;
}
} else {
- _dom_node_attach(new_child,
+ err = _dom_node_attach(new_child,
node,
ref_child == NULL ? node->last_child
: ref_child->previous,
ref_child == NULL ? NULL
: ref_child);
+ if (err != DOM_NO_ERR)
+ return err;
+
}
/* DocumentType nodes are created outside the Document so,
@@ -1059,6 +1075,14 @@ dom_exception _dom_node_remove_child(dom_node_internal *node,
if (_dom_node_readonly(node))
return DOM_NO_MODIFICATION_ALLOWED_ERR;
+ /* Dispatch a DOMNodeRemoval event */
+ dom_exception err;
+ bool success = true;
+ err = _dom_dispatch_node_change_event(node->owner, old_child, node,
+ DOM_MUTATION_REMOVAL, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
/* Detach the node */
_dom_node_detach(old_child);
@@ -1070,6 +1094,12 @@ dom_exception _dom_node_remove_child(dom_node_internal *node,
dom_node_try_destroy(old_child);
*result = old_child;
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(node->owner, node,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
return DOM_NO_ERR;
}
@@ -2048,7 +2078,8 @@ dom_exception _dom_node_copy(dom_node_internal *new, dom_node_internal *old)
* so it should be put in the pending list. */
dom_node_mark_pending(new);
- return DOM_NO_ERR;
+ /* Intialise the EventTarget interface */
+ return _dom_event_target_internal_initialise(new->owner, &new->eti);
}
@@ -2162,11 +2193,13 @@ bool _dom_node_readonly(const dom_node_internal *node)
* \param parent Node to attach ::node as child of
* \param previous Previous node in sibling list, or NULL if none
* \param next Next node in sibling list, or NULL if none
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
*/
-void _dom_node_attach(dom_node_internal *node, dom_node_internal *parent,
- dom_node_internal *previous, dom_node_internal *next)
+dom_exception _dom_node_attach(dom_node_internal *node,
+ dom_node_internal *parent, dom_node_internal *previous,
+ dom_node_internal *next)
{
- _dom_node_attach_range(node, node, parent, previous, next);
+ return _dom_node_attach_range(node, node, parent, previous, next);
}
/**
@@ -2191,10 +2224,11 @@ void _dom_node_detach(dom_node_internal *node)
* \param parent Node to attach range to
* \param previous Previous node in sibling list, or NULL if none
* \param next Next node in sibling list, or NULL if none
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
*
* The range is assumed to be a linked list of sibling nodes.
*/
-void _dom_node_attach_range(dom_node_internal *first,
+dom_exception _dom_node_attach_range(dom_node_internal *first,
dom_node_internal *last,
dom_node_internal *parent,
dom_node_internal *previous,
@@ -2213,9 +2247,24 @@ void _dom_node_attach_range(dom_node_internal *first,
else
parent->last_child = last;
+ dom_exception err;
+ bool success = true;
for (dom_node_internal *n = first; n != last->next; n = n->next) {
n->parent = parent;
+ /* Dispatch a DOMNodeInserted event */
+ err = _dom_dispatch_node_change_event(parent->owner, n, parent,
+ DOM_MUTATION_ADDITION, &success);
+ if (err != DOM_NO_ERR)
+ return err;
}
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(parent->owner, parent,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ return DOM_NO_ERR;
}
/**
@@ -2239,10 +2288,20 @@ void _dom_node_detach_range(dom_node_internal *first,
else
last->parent->last_child = first->previous;
+ bool success = true;
+ dom_node_internal *parent = first->parent;
for (dom_node_internal *n = first; n != last->next; n = n->next) {
+ /* Dispatch a DOMNodeRemoval event */
+ _dom_dispatch_node_change_event(n->owner, n, n->parent,
+ DOM_MUTATION_REMOVAL, &success);
+
n->parent = NULL;
}
+ success = true;
+ _dom_dispatch_subtree_modified_event(parent->owner, parent,
+ &success);
+
first->previous = NULL;
last->next = NULL;
}
diff --git a/src/core/node.h b/src/core/node.h
index 68776da..c1a4192 100644
--- a/src/core/node.h
+++ b/src/core/node.h
@@ -15,6 +15,9 @@
#include <dom/core/node.h>
#include <dom/functypes.h>
+#include "events/event_target.h"
+#include "events/mutation_event.h"
+
#include "utils/list.h"
/**
@@ -76,6 +79,8 @@ struct dom_node_internal {
uint32_t refcnt; /**< Reference count */
struct list_entry pending_list; /**< The document delete pending list */
+
+ dom_event_target_internal eti; /**< The EventTarget interface */
};
dom_node_internal * _dom_node_create(struct dom_document *doc);
diff --git a/src/core/string.c b/src/core/string.c
index 081e03d..7442c66 100644
--- a/src/core/string.c
+++ b/src/core/string.c
@@ -56,7 +56,8 @@ static struct dom_string empty_string = {
*/
void dom_string_ref(struct dom_string *str)
{
- str->refcnt++;
+ if (str != NULL)
+ str->refcnt++;
}
/**
@@ -963,3 +964,26 @@ int _dom_lwc_string_compare_raw(struct lwc_string_s *s1,
return memcmp(rs1, rs2, len);
}
+/**
+ * Get the raw character data of the dom_string.
+ *
+ * \param str The dom_string object
+ * \return The C string pointer
+ *
+ * @note: This function is just provided for the convenience of accessing the
+ * raw C string character, no change on the result string is allowed.
+ */
+char *_dom_string_data(struct dom_string *str)
+{
+ return (char *) str->ptr;
+}
+
+/* Get the string length of this dom_string
+ *
+ * \param str The dom_string object
+ */
+size_t _dom_string_length(struct dom_string *str)
+{
+ return str->len;
+}
+
diff --git a/src/core/string.h b/src/core/string.h
index 8372688..46704d8 100644
--- a/src/core/string.h
+++ b/src/core/string.h
@@ -28,5 +28,15 @@ int _dom_lwc_string_compare_raw(struct lwc_string_s *s1,
/* Map the lwc_error to dom_exception */
dom_exception _dom_exception_from_lwc_error(lwc_error err);
+/**
+ * Get the raw character data of the dom_string.
+ * @note: This function is just provided for the convenience of accessing the
+ * raw C string character, no change on the result string is allowed.
+ */
+char *_dom_string_data(struct dom_string *str);
+
+/* Get the string length of this dom_string */
+size_t _dom_string_length(struct dom_string *str);
+
#endif
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
diff --git a/src/utils/hashtable.c b/src/utils/hashtable.c
index c2ff8ce..f1dc076 100644
--- a/src/utils/hashtable.c
+++ b/src/utils/hashtable.c
@@ -16,6 +16,8 @@
#endif
#include "utils/hashtable.h"
+#include <libwapcaplet/libwapcaplet.h>
+
/* The hash table entry */
struct _dom_hash_entry {
void *key; /**< The key pointer */
@@ -353,6 +355,15 @@ dom_hash_func _dom_hash_get_func(struct dom_hash_table *ht)
return ht->hash;
}
+/*-----------------------------------------------------------------------*/
+/* The hash function for lwc_string type */
+unsigned int _dom_hash_hash_lwcstring(void *key)
+{
+ lwc_string *lstr = (lwc_string *) key;
+
+ return lwc_string_hash_value(lstr);
+}
+
/* A simple test rig. To compile, use:
* gcc -g -o hashtest -I../ -I../../include -DTEST_RIG hashtable.c
*
diff --git a/src/utils/hashtable.h b/src/utils/hashtable.h
index 3cfe95d..625e440 100644
--- a/src/utils/hashtable.h
+++ b/src/utils/hashtable.h
@@ -39,4 +39,7 @@ unsigned int _dom_hash_get_length(struct dom_hash_table *ht);
unsigned int _dom_hash_get_chains(struct dom_hash_table *ht);
dom_hash_func _dom_hash_get_func(struct dom_hash_table *ht);
+/*-----------------------------------------------------------------------*/
+unsigned int _dom_hash_hash_lwcstring(void *key);
+
#endif
diff --git a/test/DOMTSHandler.pm b/test/DOMTSHandler.pm
index c7dd61d..5f36d53 100644
--- a/test/DOMTSHandler.pm
+++ b/test/DOMTSHandler.pm
@@ -694,7 +694,11 @@ sub generate_method {
if (exists $ats{'var'}) {
# Add the bootstrap params
if (exists $bootstrap_api{$method}) {
- $params = $params.", myrealloc, NULL, ctx";
+ if ($method eq "dom_implementation_create_document") {
+ $params = $params.", myrealloc, NULL, ctx, NULL";
+ } else {
+ $params = $params.", myrealloc, NULL, ctx";
+ }
}
# Deal with the situation like
#