Jacek Caban : mshtml: Store event handlers in rb tree.
Alexandre Julliard
julliard at winehq.org
Tue Feb 14 16:24:51 CST 2017
Module: wine
Branch: master
Commit: c4e9787e8683ae0f88df8225500e914f42db4397
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c4e9787e8683ae0f88df8225500e914f42db4397
Author: Jacek Caban <jacek at codeweavers.com>
Date: Mon Feb 13 21:12:33 2017 +0100
mshtml: Store event handlers in rb tree.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/mshtml/htmlevent.c | 89 ++++++++++++++++++++++----------------------
dlls/mshtml/htmlevent.h | 1 +
dlls/mshtml/htmlnode.c | 1 +
dlls/mshtml/htmlwindow.c | 1 +
dlls/mshtml/mshtml_private.h | 3 +-
dlls/mshtml/xmlhttprequest.c | 1 +
6 files changed, 49 insertions(+), 47 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 7d11747..27e041c 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -36,15 +36,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
typedef struct {
+ struct wine_rb_entry entry;
+ eventid_t event_id;
IDispatch *handler_prop;
DWORD handler_cnt;
IDispatch **handlers;
} handler_vector_t;
-struct event_target_t {
- handler_vector_t *event_table[EVENTID_LAST];
-};
-
static const WCHAR abortW[] = {'a','b','o','r','t',0};
static const WCHAR onabortW[] = {'o','n','a','b','o','r','t',0};
@@ -899,37 +897,35 @@ HRESULT create_event_obj(IHTMLEventObj **ret)
return S_OK;
}
-static inline event_target_t *get_event_target_data(EventTarget *event_target, BOOL alloc)
+static handler_vector_t *get_handler_vector(EventTarget *event_target, eventid_t eid, BOOL alloc)
{
- const dispex_static_data_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
+ const dispex_static_data_vtbl_t *vtbl;
+ handler_vector_t *handler_vector;
+ struct wine_rb_entry *entry;
- if(vtbl && vtbl->get_event_target)
+ vtbl = dispex_get_vtbl(&event_target->dispex);
+ if(vtbl->get_event_target)
event_target = vtbl->get_event_target(&event_target->dispex);
- if(event_target->ptr || !alloc)
- return event_target->ptr;
- return event_target->ptr = heap_alloc_zero(sizeof(event_target_t));
-}
-
-static handler_vector_t *get_handler_vector(EventTarget *event_target, eventid_t eid, BOOL alloc)
-{
- event_target_t *data;
+ entry = wine_rb_get(&event_target->handler_map, (const void*)eid);
+ if(entry)
+ return WINE_RB_ENTRY_VALUE(entry, handler_vector_t, entry);
+ if(!alloc)
+ return NULL;
- data = get_event_target_data(event_target, alloc);
- if(!data)
+ handler_vector = heap_alloc_zero(sizeof(*handler_vector));
+ if(!handler_vector)
return NULL;
- if(alloc && !data->event_table[eid]) {
- data->event_table[eid] = heap_alloc_zero(sizeof(*data->event_table[eid]));
- if(data->event_table[eid]) {
- const dispex_static_data_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
- if(vtbl->bind_event)
- vtbl->bind_event(&event_target->dispex, eid);
- else
- FIXME("Unsupported event binding on target %p\n", event_target);
- }
- }
- return data->event_table[eid];
+ handler_vector->event_id = eid;
+ vtbl = dispex_get_vtbl(&event_target->dispex);
+ if(vtbl->bind_event)
+ vtbl->bind_event(&event_target->dispex, eid);
+ else
+ FIXME("Unsupported event binding on target %p\n", event_target);
+
+ wine_rb_put(&event_target->handler_map, (const void*)eid, &handler_vector->entry);
+ return handler_vector;
}
static HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
@@ -1642,25 +1638,28 @@ HRESULT doc_init_events(HTMLDocumentNode *doc)
return S_OK;
}
-void release_event_target(EventTarget *event_target)
+static int event_id_cmp(const void *key, const struct wine_rb_entry *entry)
{
- int i;
- unsigned int j;
+ return (INT_PTR)key - WINE_RB_ENTRY_VALUE(entry, handler_vector_t, entry)->event_id;
+}
- if(!event_target->ptr)
- return;
+void init_event_target(EventTarget *event_target)
+{
+ wine_rb_init(&event_target->handler_map, event_id_cmp);
+}
- for(i=0; i < EVENTID_LAST; i++) {
- if(event_target->ptr->event_table[i]) {
- if(event_target->ptr->event_table[i]->handler_prop)
- IDispatch_Release(event_target->ptr->event_table[i]->handler_prop);
- for(j=0; j < event_target->ptr->event_table[i]->handler_cnt; j++)
- if(event_target->ptr->event_table[i]->handlers[j])
- IDispatch_Release(event_target->ptr->event_table[i]->handlers[j]);
- heap_free(event_target->ptr->event_table[i]->handlers);
- heap_free(event_target->ptr->event_table[i]);
- }
- }
+void release_event_target(EventTarget *event_target)
+{
+ handler_vector_t *iter, *iter2;
+ unsigned i;
- heap_free(event_target->ptr);
+ WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter, iter2, &event_target->handler_map, handler_vector_t, entry) {
+ if(iter->handler_prop)
+ IDispatch_Release(iter->handler_prop);
+ for(i = 0; i < iter->handler_cnt; i++)
+ if(iter->handlers[i])
+ IDispatch_Release(iter->handlers[i]);
+ heap_free(iter->handlers);
+ heap_free(iter);
+ }
}
diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h
index d66f359..5bdd435 100644
--- a/dlls/mshtml/htmlevent.h
+++ b/dlls/mshtml/htmlevent.h
@@ -55,6 +55,7 @@ typedef enum {
eventid_t str_to_eid(LPCWSTR) DECLSPEC_HIDDEN;
void check_event_attr(HTMLDocumentNode*,nsIDOMHTMLElement*) DECLSPEC_HIDDEN;
+void init_event_target(EventTarget*) DECLSPEC_HIDDEN;
void release_event_target(EventTarget*) DECLSPEC_HIDDEN;
void fire_event(HTMLDocumentNode*,eventid_t,BOOL,HTMLDOMNode*,nsIDOMEvent*,IDispatch*) DECLSPEC_HIDDEN;
HRESULT set_event_handler(EventTarget*,eventid_t,VARIANT*) DECLSPEC_HIDDEN;
diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c
index ab47323..2dfbeaa 100644
--- a/dlls/mshtml/htmlnode.c
+++ b/dlls/mshtml/htmlnode.c
@@ -1214,6 +1214,7 @@ void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsno
node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
ccref_init(&node->ccref, 1);
+ init_event_target(&node->event_target);
if(&doc->node != node)
htmldoc_addref(&doc->basedoc);
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index e3f22cf..a5db035 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -3020,6 +3020,7 @@ static HRESULT create_inner_window(HTMLOuterWindow *outer_window, IMoniker *mon,
window->base.outer_window = outer_window;
window->base.inner_window = window;
+ init_event_target(&window->event_target);
init_dispex(&window->event_target.dispex, (IUnknown*)&window->base.IHTMLWindow2_iface, &HTMLWindow_dispex);
window->task_magic = get_task_target_magic();
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 457e32b..89f2fcb 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -72,7 +72,6 @@
typedef struct HTMLDOMNode HTMLDOMNode;
typedef struct ConnectionPoint ConnectionPoint;
typedef struct BSCallback BSCallback;
-typedef struct event_target_t event_target_t;
typedef struct EventTarget EventTarget;
#define TID_LIST \
@@ -366,7 +365,7 @@ typedef struct {
struct EventTarget {
DispatchEx dispex;
- event_target_t *ptr;
+ struct wine_rb_tree handler_map;
};
typedef struct {
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c
index 51e2445..ab14c54 100644
--- a/dlls/mshtml/xmlhttprequest.c
+++ b/dlls/mshtml/xmlhttprequest.c
@@ -851,6 +851,7 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor
ret->nsxhr = nsxhr;
ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
+ init_event_target(&ret->event_target);
init_dispex(&ret->event_target.dispex, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
&HTMLXMLHttpRequest_dispex);
ret->ref = 1;
More information about the wine-cvs
mailing list