Jacek Caban : mshtml: Store event handlers in vector structure.

Alexandre Julliard julliard at winehq.org
Tue Sep 8 08:55:24 CDT 2009


Module: wine
Branch: master
Commit: 86410d4a0ced55725a774ccac02f2f323144b9f5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=86410d4a0ced55725a774ccac02f2f323144b9f5

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Sun Sep  6 19:05:40 2009 +0200

mshtml: Store event handlers in vector structure.

---

 dlls/mshtml/htmlevent.c      |   84 ++++++++++++++++++++++++++++++++---------
 dlls/mshtml/mshtml_private.h |    5 ++
 2 files changed, 70 insertions(+), 19 deletions(-)

diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 6f3c606..d732b86 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Jacek Caban for CodeWeavers
+ * Copyright 2008-2009 Jacek Caban for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -32,8 +32,14 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
 
+typedef struct {
+    IDispatch *handler_prop;
+    DWORD handler_cnt;
+    IDispatch *handlers[0];
+} handler_vector_t;
+
 struct event_target_t {
-    IDispatch *event_table[EVENTID_LAST];
+    handler_vector_t *event_table[EVENTID_LAST];
 };
 
 static const WCHAR blurW[] = {'b','l','u','r',0};
@@ -667,12 +673,13 @@ static IHTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEve
 static void call_event_handlers(HTMLDocument *doc, event_target_t *event_target,
         eventid_t eid, IDispatch *this_obj)
 {
+    handler_vector_t *handler_vector;
     HRESULT hres;
 
-    if(!event_target || !event_target->event_table[eid])
+    if(!event_target || !(handler_vector = event_target->event_table[eid]))
         return;
 
-    if(event_target->event_table[eid]) {
+    if(handler_vector->handler_prop) {
         DISPID named_arg = DISPID_THIS;
         VARIANTARG arg;
         DISPPARAMS dp = {&arg, &named_arg, 1, 1};
@@ -681,7 +688,7 @@ static void call_event_handlers(HTMLDocument *doc, event_target_t *event_target,
         V_DISPATCH(&arg) = this_obj;
 
         TRACE("%s >>>\n", debugstr_w(event_info[eid].name));
-        hres = call_disp_func(event_target->event_table[eid], &dp);
+        hres = call_disp_func(handler_vector->handler_prop, &dp);
         if(hres == S_OK)
             TRACE("%s <<<\n", debugstr_w(event_info[eid].name));
         else
@@ -737,14 +744,49 @@ void fire_event(HTMLDocument *doc, eventid_t eid, nsIDOMNode *target, nsIDOMEven
     doc->window->event = prev_event;
 }
 
-static HRESULT set_event_handler_disp(event_target_t **event_target, HTMLDocument *doc, eventid_t eid, IDispatch *disp)
+static inline event_target_t *get_event_target(event_target_t **event_target_ptr)
+{
+    if(!*event_target_ptr)
+        *event_target_ptr = heap_alloc_zero(sizeof(event_target_t));
+    return *event_target_ptr;
+}
+
+static BOOL alloc_handler_vector(event_target_t *event_target, eventid_t eid, int cnt)
 {
-    if(!*event_target)
-        *event_target = heap_alloc_zero(sizeof(event_target_t));
-    else if((*event_target)->event_table[eid])
-        IDispatch_Release((*event_target)->event_table[eid]);
+    handler_vector_t *new_vector, *handler_vector = event_target->event_table[eid];
+
+    if(handler_vector) {
+        if(cnt <= handler_vector->handler_cnt)
+            return TRUE;
+
+        new_vector = heap_realloc_zero(handler_vector, sizeof(handler_vector_t) + sizeof(IDispatch*)*cnt);
+    }else {
+        new_vector = heap_alloc_zero(sizeof(handler_vector_t) + sizeof(IDispatch*)*cnt);
+    }
+
+    if(!new_vector)
+        return FALSE;
 
-    (*event_target)->event_table[eid] = disp;
+    new_vector->handler_cnt = cnt;
+    event_target->event_table[eid] = new_vector;
+    return TRUE;
+}
+
+static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, HTMLDocument *doc, eventid_t eid, IDispatch *disp)
+{
+    event_target_t *event_target;
+
+    event_target = get_event_target(event_target_ptr);
+    if(!event_target)
+        return E_OUTOFMEMORY;
+
+    if(!alloc_handler_vector(event_target, eid, 0))
+        return E_OUTOFMEMORY;
+
+    if(event_target->event_table[eid]->handler_prop)
+        IDispatch_Release(event_target->event_table[eid]->handler_prop);
+
+    event_target->event_table[eid]->handler_prop = disp;
     if(!disp)
         return S_OK;
     IDispatch_AddRef(disp);
@@ -769,9 +811,9 @@ HRESULT set_event_handler(event_target_t **event_target, HTMLDocument *doc, even
 {
     switch(V_VT(var)) {
     case VT_NULL:
-        if(*event_target && (*event_target)->event_table[eid]) {
-            IDispatch_Release((*event_target)->event_table[eid]);
-            (*event_target)->event_table[eid] = NULL;
+        if(*event_target && (*event_target)->event_table[eid] && (*event_target)->event_table[eid]->handler_prop) {
+            IDispatch_Release((*event_target)->event_table[eid]->handler_prop);
+            (*event_target)->event_table[eid]->handler_prop = NULL;
         }
         break;
 
@@ -788,9 +830,9 @@ HRESULT set_event_handler(event_target_t **event_target, HTMLDocument *doc, even
 
 HRESULT get_event_handler(event_target_t **event_target, eventid_t eid, VARIANT *var)
 {
-    if(*event_target && (*event_target)->event_table[eid]) {
+    if(*event_target && (*event_target)->event_table[eid] && (*event_target)->event_table[eid]->handler_prop) {
         V_VT(var) = VT_DISPATCH;
-        V_DISPATCH(var) = (*event_target)->event_table[eid];
+        V_DISPATCH(var) = (*event_target)->event_table[eid]->handler_prop;
         IDispatch_AddRef(V_DISPATCH(var));
     }else {
         V_VT(var) = VT_NULL;
@@ -836,11 +878,15 @@ void check_event_attr(HTMLDocument *doc, nsIDOMElement *nselem)
 
 void release_event_target(event_target_t *event_target)
 {
-    int i;
+    int i, j;
 
     for(i=0; i < EVENTID_LAST; i++) {
-        if(event_target->event_table[i])
-            IDispatch_Release(event_target->event_table[i]);
+        if(event_target->event_table[i]) {
+            if(event_target->event_table[i]->handler_prop)
+                IDispatch_Release(event_target->event_table[i]->handler_prop);
+            for(j=0; j < event_target->event_table[i]->handler_cnt; j++)
+                IDispatch_Release(event_target->event_table[i]->handlers[j]);
+        }
     }
 
     heap_free(event_target);
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index e98666b..d2b0ef8 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -721,6 +721,11 @@ static inline void * __WINE_ALLOC_SIZE(2) heap_realloc(void *mem, size_t len)
     return HeapReAlloc(GetProcessHeap(), 0, mem, len);
 }
 
+static inline void * __WINE_ALLOC_SIZE(2) heap_realloc_zero(void *mem, size_t len)
+{
+    return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, len);
+}
+
 static inline BOOL heap_free(void *mem)
 {
     return HeapFree(GetProcessHeap(), 0, mem);




More information about the wine-cvs mailing list