From 724fde7e9189a85ab677a4fbfbb1acc0ce461ab7 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Sun, 6 Sep 2009 19:06:10 +0200 Subject: [PATCH] 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 4d6de2c6b93..542baa7d11e 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 d732b86c9c9..4bde49a91fc 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 8ca4a96894d..3ea3d9d2784 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) {