Jacek Caban : mshtml: Added IHTMLElement2::attachEvent implementation.

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


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

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

mshtml: Added IHTMLElement2::attachEvent implementation.

---

 dlls/mshtml/htmlelem2.c |    6 ++-
 dlls/mshtml/htmlevent.c |   71 +++++++++++++++++++++++++++++++++++++++++++++--
 dlls/mshtml/htmlevent.h |    1 +
 3 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/dlls/mshtml/htmlelem2.c b/dlls/mshtml/htmlelem2.c
index 4d6de2c..542baa7 100644
--- a/dlls/mshtml/htmlelem2.c
+++ b/dlls/mshtml/htmlelem2.c
@@ -605,8 +605,10 @@ static HRESULT WINAPI HTMLElement2_attachEvent(IHTMLElement2 *iface, BSTR event,
                                                IDispatch *pDisp, VARIANT_BOOL *pfResult)
 {
     HTMLElement *This = HTMLELEM2_THIS(iface);
-    FIXME("(%p)->(%s %p %p)\n", This, debugstr_w(event), pDisp, pfResult);
-    return E_NOTIMPL;
+
+    TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(event), pDisp, pfResult);
+
+    return attach_event(&This->node.event_target, This->node.doc, event, pDisp, pfResult);
 }
 
 static HRESULT WINAPI HTMLElement2_detachEvent(IHTMLElement2 *iface, BSTR event, IDispatch *pDisp)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index d732b86..4bde49a 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -127,6 +127,18 @@ eventid_t str_to_eid(LPCWSTR str)
     return EVENTID_LAST;
 }
 
+static eventid_t attr_to_eid(LPCWSTR str)
+{
+    int i;
+
+    for(i=0; i < sizeof(event_info)/sizeof(event_info[0]); i++) {
+        if(!strcmpW(event_info[i].attr_name, str))
+            return i;
+    }
+
+    return EVENTID_LAST;
+}
+
 typedef struct {
     DispatchEx dispex;
     const IHTMLEventObjVtbl  *lpIHTMLEventObjVtbl;
@@ -670,10 +682,11 @@ static IHTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEve
     return HTMLEVENTOBJ(ret);
 }
 
-static void call_event_handlers(HTMLDocument *doc, event_target_t *event_target,
+static void call_event_handlers(HTMLDocument *doc, IHTMLEventObj *event_obj, event_target_t *event_target,
         eventid_t eid, IDispatch *this_obj)
 {
     handler_vector_t *handler_vector;
+    DWORD i;
     HRESULT hres;
 
     if(!event_target || !(handler_vector = event_target->event_table[eid]))
@@ -694,6 +707,25 @@ static void call_event_handlers(HTMLDocument *doc, event_target_t *event_target,
         else
             WARN("%s <<< %08x\n", debugstr_w(event_info[eid].name), hres);
     }
+
+    if(handler_vector->handler_cnt) {
+        VARIANTARG arg;
+        DISPPARAMS dp = {&arg, NULL, 1, 0};
+
+        V_VT(&arg) = VT_DISPATCH;
+        V_DISPATCH(&arg) = (IDispatch*)event_obj;
+
+        for(i=0; i < handler_vector->handler_cnt; i++) {
+            if(handler_vector->handlers[i]) {
+                TRACE("%s [%d] >>>\n", debugstr_w(event_info[eid].name), i);
+                hres = call_disp_func(handler_vector->handlers[i], &dp);
+                if(hres == S_OK)
+                    TRACE("%s [%d] <<<\n", debugstr_w(event_info[eid].name), i);
+                else
+                    WARN("%s [%d] <<< %08x\n", debugstr_w(event_info[eid].name), i, hres);
+            }
+        }
+    }
 }
 
 void fire_event(HTMLDocument *doc, eventid_t eid, nsIDOMNode *target, nsIDOMEvent *nsevent)
@@ -718,7 +750,7 @@ void fire_event(HTMLDocument *doc, eventid_t eid, nsIDOMNode *target, nsIDOMEven
         node = get_node(doc, nsnode, FALSE);
 
         if(node)
-            call_event_handlers(doc, node->event_target, eid, (IDispatch*)HTMLDOMNODE(node));
+            call_event_handlers(doc, event_obj, node->event_target, eid, (IDispatch*)HTMLDOMNODE(node));
 
         if(!(event_info[eid].flags & EVENT_BUBBLE))
             break;
@@ -738,7 +770,7 @@ void fire_event(HTMLDocument *doc, eventid_t eid, nsIDOMNode *target, nsIDOMEven
         nsIDOMNode_Release(nsnode);
 
     if(event_info[eid].flags & EVENT_BUBBLE)
-        call_event_handlers(doc, doc->event_target, eid, (IDispatch*)HTMLDOC(doc));
+        call_event_handlers(doc, event_obj, doc->event_target, eid, (IDispatch*)HTMLDOC(doc));
 
     IHTMLEventObj_Release(event_obj);
     doc->window->event = prev_event;
@@ -841,6 +873,39 @@ HRESULT get_event_handler(event_target_t **event_target, eventid_t eid, VARIANT
     return S_OK;
 }
 
+HRESULT attach_event(event_target_t **event_target_ptr, HTMLDocument *doc, BSTR name, IDispatch *disp, VARIANT_BOOL *res)
+{
+    event_target_t *event_target;
+    eventid_t eid;
+    DWORD i = 0;
+
+    eid = attr_to_eid(name);
+    if(eid == EVENTID_LAST) {
+        WARN("Unknown event\n");
+        *res = VARIANT_TRUE;
+        return S_OK;
+    }
+
+    event_target = get_event_target(event_target_ptr);
+    if(!event_target)
+        return E_OUTOFMEMORY;
+
+    if(event_target->event_table[eid]) {
+        while(i < event_target->event_table[eid]->handler_cnt && event_target->event_table[eid]->handlers[i])
+            i++;
+        if(i == event_target->event_table[eid]->handler_cnt && !alloc_handler_vector(event_target, eid, i+1))
+            return E_OUTOFMEMORY;
+    }else if(!alloc_handler_vector(event_target, eid, i+1)) {
+        return E_OUTOFMEMORY;
+    }
+
+    IDispatch_AddRef(disp);
+    event_target->event_table[eid]->handlers[i] = disp;
+
+    *res = VARIANT_TRUE;
+    return S_OK;
+}
+
 void check_event_attr(HTMLDocument *doc, nsIDOMElement *nselem)
 {
     const PRUnichar *attr_value;
diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h
index 8ca4a96..3ea3d9d 100644
--- a/dlls/mshtml/htmlevent.h
+++ b/dlls/mshtml/htmlevent.h
@@ -41,6 +41,7 @@ void release_event_target(event_target_t*);
 void fire_event(HTMLDocument*,eventid_t,nsIDOMNode*,nsIDOMEvent*);
 HRESULT set_event_handler(event_target_t**,HTMLDocument*,eventid_t,VARIANT*);
 HRESULT get_event_handler(event_target_t**,eventid_t,VARIANT*);
+HRESULT attach_event(event_target_t**,HTMLDocument*,BSTR,IDispatch*,VARIANT_BOOL*);
 
 static inline HRESULT set_node_event(HTMLDOMNode *node, eventid_t eid, VARIANT *var)
 {




More information about the wine-cvs mailing list