Module: wine Branch: master Commit: c4e9787e8683ae0f88df8225500e914f42db4397 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c4e9787e8683ae0f88df822550...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Feb 13 21:12:33 2017 +0100
mshtml: Store event handlers in rb tree.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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;