Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhtmlevent.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2008-2009 Jacek Caban for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include <stdarg.h> 00020 00021 #define COBJMACROS 00022 00023 #include "windef.h" 00024 #include "winbase.h" 00025 #include "winuser.h" 00026 #include "ole2.h" 00027 #include "mshtmdid.h" 00028 00029 #include "mshtml_private.h" 00030 #include "htmlevent.h" 00031 00032 #include "wine/debug.h" 00033 00034 WINE_DEFAULT_DEBUG_CHANNEL(mshtml); 00035 00036 typedef struct { 00037 IDispatch *handler_prop; 00038 DWORD handler_cnt; 00039 IDispatch *handlers[0]; 00040 } handler_vector_t; 00041 00042 struct event_target_t { 00043 DWORD node_handlers_mask; 00044 handler_vector_t *event_table[EVENTID_LAST]; 00045 }; 00046 00047 static const WCHAR beforeunloadW[] = {'b','e','f','o','r','e','u','n','l','o','a','d',0}; 00048 static const WCHAR onbeforeunloadW[] = {'o','n','b','e','f','o','r','e','u','n','l','o','a','d',0}; 00049 00050 static const WCHAR blurW[] = {'b','l','u','r',0}; 00051 static const WCHAR onblurW[] = {'o','n','b','l','u','r',0}; 00052 00053 static const WCHAR changeW[] = {'c','h','a','n','g','e',0}; 00054 static const WCHAR onchangeW[] = {'o','n','c','h','a','n','g','e',0}; 00055 00056 static const WCHAR clickW[] = {'c','l','i','c','k',0}; 00057 static const WCHAR onclickW[] = {'o','n','c','l','i','c','k',0}; 00058 00059 static const WCHAR contextmenuW[] = {'c','o','n','t','e','x','t','m','e','n','u',0}; 00060 static const WCHAR oncontextmenuW[] = {'o','n','c','o','n','t','e','x','t','m','e','n','u',0}; 00061 00062 static const WCHAR dblclickW[] = {'d','b','l','c','l','i','c','k',0}; 00063 static const WCHAR ondblclickW[] = {'o','n','d','b','l','c','l','i','c','k',0}; 00064 00065 static const WCHAR dragW[] = {'d','r','a','g',0}; 00066 static const WCHAR ondragW[] = {'o','n','d','r','a','g',0}; 00067 00068 static const WCHAR dragstartW[] = {'d','r','a','g','s','t','a','r','t',0}; 00069 static const WCHAR ondragstartW[] = {'o','n','d','r','a','g','s','t','a','r','t',0}; 00070 00071 static const WCHAR focusW[] = {'f','o','c','u','s',0}; 00072 static const WCHAR onfocusW[] = {'o','n','f','o','c','u','s',0}; 00073 00074 static const WCHAR keydownW[] = {'k','e','y','d','o','w','n',0}; 00075 static const WCHAR onkeydownW[] = {'o','n','k','e','y','d','o','w','n',0}; 00076 00077 static const WCHAR keyupW[] = {'k','e','y','u','p',0}; 00078 static const WCHAR onkeyupW[] = {'o','n','k','e','y','u','p',0}; 00079 00080 static const WCHAR loadW[] = {'l','o','a','d',0}; 00081 static const WCHAR onloadW[] = {'o','n','l','o','a','d',0}; 00082 00083 static const WCHAR mousedownW[] = {'m','o','u','s','e','d','o','w','n',0}; 00084 static const WCHAR onmousedownW[] = {'o','n','m','o','u','s','e','d','o','w','n',0}; 00085 00086 static const WCHAR mouseoutW[] = {'m','o','u','s','e','o','u','t',0}; 00087 static const WCHAR onmouseoutW[] = {'o','n','m','o','u','s','e','o','u','t',0}; 00088 00089 static const WCHAR mouseoverW[] = {'m','o','u','s','e','o','v','e','r',0}; 00090 static const WCHAR onmouseoverW[] = {'o','n','m','o','u','s','e','o','v','e','r',0}; 00091 00092 static const WCHAR mouseupW[] = {'m','o','u','s','e','u','p',0}; 00093 static const WCHAR onmouseupW[] = {'o','n','m','o','u','s','e','u','p',0}; 00094 00095 static const WCHAR pasteW[] = {'p','a','s','t','e',0}; 00096 static const WCHAR onpasteW[] = {'o','n','p','a','s','t','e',0}; 00097 00098 static const WCHAR readystatechangeW[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0}; 00099 static const WCHAR onreadystatechangeW[] = {'o','n','r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0}; 00100 00101 static const WCHAR resizeW[] = {'r','e','s','i','z','e',0}; 00102 static const WCHAR onresizeW[] = {'o','n','r','e','s','i','z','e',0}; 00103 00104 static const WCHAR selectstartW[] = {'s','e','l','e','c','t','s','t','a','r','t',0}; 00105 static const WCHAR onselectstartW[] = {'o','n','s','e','l','e','c','t','s','t','a','r','t',0}; 00106 00107 static const WCHAR HTMLEventsW[] = {'H','T','M','L','E','v','e','n','t','s',0}; 00108 static const WCHAR KeyboardEventW[] = {'K','e','y','b','o','a','r','d','E','v','e','n','t',0}; 00109 static const WCHAR MouseEventW[] = {'M','o','u','s','e','E','v','e','n','t',0}; 00110 00111 enum { 00112 EVENTT_NONE, 00113 EVENTT_HTML, 00114 EVENTT_KEY, 00115 EVENTT_MOUSE 00116 }; 00117 00118 static const WCHAR *event_types[] = { 00119 NULL, 00120 HTMLEventsW, 00121 KeyboardEventW, 00122 MouseEventW 00123 }; 00124 00125 typedef struct { 00126 LPCWSTR name; 00127 LPCWSTR attr_name; 00128 DWORD type; 00129 DISPID dispid; 00130 DWORD flags; 00131 } event_info_t; 00132 00133 #define EVENT_DEFAULTLISTENER 0x0001 00134 #define EVENT_BUBBLE 0x0002 00135 #define EVENT_FORWARDBODY 0x0004 00136 #define EVENT_NODEHANDLER 0x0008 00137 00138 static const event_info_t event_info[] = { 00139 {beforeunloadW, onbeforeunloadW, EVENTT_NONE, DISPID_EVMETH_ONBEFOREUNLOAD, 00140 EVENT_DEFAULTLISTENER|EVENT_FORWARDBODY}, 00141 {blurW, onblurW, EVENTT_HTML, DISPID_EVMETH_ONBLUR, 00142 EVENT_DEFAULTLISTENER}, 00143 {changeW, onchangeW, EVENTT_HTML, DISPID_EVMETH_ONCHANGE, 00144 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00145 {clickW, onclickW, EVENTT_MOUSE, DISPID_EVMETH_ONCLICK, 00146 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00147 {contextmenuW, oncontextmenuW, EVENTT_MOUSE, DISPID_EVMETH_ONCONTEXTMENU, 00148 EVENT_BUBBLE}, 00149 {dblclickW, ondblclickW, EVENTT_MOUSE, DISPID_EVMETH_ONDBLCLICK, 00150 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00151 {dragW, ondragW, EVENTT_MOUSE, DISPID_EVMETH_ONDRAG, 00152 0}, 00153 {dragstartW, ondragstartW, EVENTT_MOUSE, DISPID_EVMETH_ONDRAGSTART, 00154 0}, 00155 {focusW, onfocusW, EVENTT_HTML, DISPID_EVMETH_ONFOCUS, 00156 EVENT_DEFAULTLISTENER}, 00157 {keydownW, onkeydownW, EVENTT_KEY, DISPID_EVMETH_ONKEYDOWN, 00158 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00159 {keyupW, onkeyupW, EVENTT_KEY, DISPID_EVMETH_ONKEYUP, 00160 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00161 {loadW, onloadW, EVENTT_HTML, DISPID_EVMETH_ONLOAD, 00162 EVENT_NODEHANDLER}, 00163 {mousedownW, onmousedownW, EVENTT_MOUSE, DISPID_EVMETH_ONMOUSEDOWN, 00164 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00165 {mouseoutW, onmouseoutW, EVENTT_MOUSE, DISPID_EVMETH_ONMOUSEOUT, 00166 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00167 {mouseoverW, onmouseoverW, EVENTT_MOUSE, DISPID_EVMETH_ONMOUSEOVER, 00168 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00169 {mouseupW, onmouseupW, EVENTT_MOUSE, DISPID_EVMETH_ONMOUSEUP, 00170 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00171 {pasteW, onpasteW, EVENTT_NONE, DISPID_EVMETH_ONPASTE, 00172 0}, 00173 {readystatechangeW, onreadystatechangeW, EVENTT_NONE, DISPID_EVMETH_ONREADYSTATECHANGE, 00174 0}, 00175 {resizeW, onresizeW, EVENTT_NONE, DISPID_EVMETH_ONRESIZE, 00176 EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, 00177 {selectstartW, onselectstartW, EVENTT_MOUSE, DISPID_EVMETH_ONSELECTSTART, 00178 0} 00179 }; 00180 00181 static const eventid_t node_handled_list[] = { EVENTID_LOAD }; 00182 00183 eventid_t str_to_eid(LPCWSTR str) 00184 { 00185 int i; 00186 00187 for(i=0; i < sizeof(event_info)/sizeof(event_info[0]); i++) { 00188 if(!strcmpW(event_info[i].name, str)) 00189 return i; 00190 } 00191 00192 ERR("unknown type %s\n", debugstr_w(str)); 00193 return EVENTID_LAST; 00194 } 00195 00196 static eventid_t attr_to_eid(LPCWSTR str) 00197 { 00198 int i; 00199 00200 for(i=0; i < sizeof(event_info)/sizeof(event_info[0]); i++) { 00201 if(!strcmpW(event_info[i].attr_name, str)) 00202 return i; 00203 } 00204 00205 return EVENTID_LAST; 00206 } 00207 00208 static DWORD get_node_handler_mask(eventid_t eid) 00209 { 00210 DWORD i; 00211 00212 for(i=0; i<sizeof(node_handled_list)/sizeof(*node_handled_list); i++) { 00213 if(node_handled_list[i] == eid) 00214 return 1 << i; 00215 } 00216 00217 ERR("Invalid eid %d\n", eid); 00218 return ~0; 00219 } 00220 00221 typedef struct { 00222 DispatchEx dispex; 00223 const IHTMLEventObjVtbl *lpIHTMLEventObjVtbl; 00224 00225 LONG ref; 00226 00227 HTMLDOMNode *target; 00228 const event_info_t *type; 00229 nsIDOMEvent *nsevent; 00230 } HTMLEventObj; 00231 00232 #define HTMLEVENTOBJ(x) ((IHTMLEventObj*) &(x)->lpIHTMLEventObjVtbl) 00233 00234 #define HTMLEVENTOBJ_THIS(iface) DEFINE_THIS(HTMLEventObj, IHTMLEventObj, iface) 00235 00236 static HRESULT WINAPI HTMLEventObj_QueryInterface(IHTMLEventObj *iface, REFIID riid, void **ppv) 00237 { 00238 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00239 00240 *ppv = NULL; 00241 00242 if(IsEqualGUID(&IID_IUnknown, riid)) { 00243 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 00244 *ppv = HTMLEVENTOBJ(This); 00245 }else if(IsEqualGUID(&IID_IHTMLEventObj, riid)) { 00246 TRACE("(%p)->(IID_IHTMLEventObj %p)\n", This, ppv); 00247 *ppv = HTMLEVENTOBJ(This); 00248 }else if(dispex_query_interface(&This->dispex, riid, ppv)) { 00249 return *ppv ? S_OK : E_NOINTERFACE; 00250 } 00251 00252 if(*ppv) { 00253 IUnknown_AddRef((IUnknown*)*ppv); 00254 return S_OK; 00255 } 00256 00257 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 00258 return E_NOINTERFACE; 00259 } 00260 00261 static ULONG WINAPI HTMLEventObj_AddRef(IHTMLEventObj *iface) 00262 { 00263 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00264 LONG ref = InterlockedIncrement(&This->ref); 00265 00266 TRACE("(%p) ref=%d\n", This, ref); 00267 00268 return ref; 00269 } 00270 00271 static ULONG WINAPI HTMLEventObj_Release(IHTMLEventObj *iface) 00272 { 00273 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00274 LONG ref = InterlockedDecrement(&This->ref); 00275 00276 TRACE("(%p) ref=%d\n", This, ref); 00277 00278 if(!ref) { 00279 if(This->nsevent) 00280 nsIDOMEvent_Release(This->nsevent); 00281 release_dispex(&This->dispex); 00282 heap_free(This); 00283 } 00284 00285 return ref; 00286 } 00287 00288 static HRESULT WINAPI HTMLEventObj_GetTypeInfoCount(IHTMLEventObj *iface, UINT *pctinfo) 00289 { 00290 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00291 return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo); 00292 } 00293 00294 static HRESULT WINAPI HTMLEventObj_GetTypeInfo(IHTMLEventObj *iface, UINT iTInfo, 00295 LCID lcid, ITypeInfo **ppTInfo) 00296 { 00297 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00298 return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo); 00299 } 00300 00301 static HRESULT WINAPI HTMLEventObj_GetIDsOfNames(IHTMLEventObj *iface, REFIID riid, 00302 LPOLESTR *rgszNames, UINT cNames, 00303 LCID lcid, DISPID *rgDispId) 00304 { 00305 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00306 return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId); 00307 } 00308 00309 static HRESULT WINAPI HTMLEventObj_Invoke(IHTMLEventObj *iface, DISPID dispIdMember, 00310 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 00311 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 00312 { 00313 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00314 return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid, 00315 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 00316 } 00317 00318 static HRESULT WINAPI HTMLEventObj_get_srcElement(IHTMLEventObj *iface, IHTMLElement **p) 00319 { 00320 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00321 00322 TRACE("(%p)->(%p)\n", This, p); 00323 00324 return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(This->target), &IID_IHTMLElement, (void**)p); 00325 } 00326 00327 static HRESULT WINAPI HTMLEventObj_get_altKey(IHTMLEventObj *iface, VARIANT_BOOL *p) 00328 { 00329 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00330 PRBool ret = FALSE; 00331 00332 TRACE("(%p)->(%p)\n", This, p); 00333 00334 if(This->nsevent) { 00335 nsIDOMKeyEvent *key_event; 00336 nsresult nsres; 00337 00338 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); 00339 if(NS_SUCCEEDED(nsres)) { 00340 nsIDOMKeyEvent_GetAltKey(key_event, &ret); 00341 nsIDOMKeyEvent_Release(key_event); 00342 }else { 00343 nsIDOMMouseEvent *mouse_event; 00344 00345 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); 00346 if(NS_SUCCEEDED(nsres)) { 00347 nsIDOMMouseEvent_GetAltKey(mouse_event, &ret); 00348 nsIDOMMouseEvent_Release(mouse_event); 00349 } 00350 } 00351 } 00352 00353 *p = ret ? VARIANT_TRUE : VARIANT_FALSE; 00354 return S_OK; 00355 } 00356 00357 static HRESULT WINAPI HTMLEventObj_get_ctrlKey(IHTMLEventObj *iface, VARIANT_BOOL *p) 00358 { 00359 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00360 PRBool ret = FALSE; 00361 00362 TRACE("(%p)->(%p)\n", This, p); 00363 00364 if(This->nsevent) { 00365 nsIDOMKeyEvent *key_event; 00366 nsresult nsres; 00367 00368 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); 00369 if(NS_SUCCEEDED(nsres)) { 00370 nsIDOMKeyEvent_GetCtrlKey(key_event, &ret); 00371 nsIDOMKeyEvent_Release(key_event); 00372 }else { 00373 nsIDOMMouseEvent *mouse_event; 00374 00375 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); 00376 if(NS_SUCCEEDED(nsres)) { 00377 nsIDOMMouseEvent_GetCtrlKey(mouse_event, &ret); 00378 nsIDOMMouseEvent_Release(mouse_event); 00379 } 00380 } 00381 } 00382 00383 *p = ret ? VARIANT_TRUE : VARIANT_FALSE; 00384 return S_OK; 00385 } 00386 00387 static HRESULT WINAPI HTMLEventObj_get_shiftKey(IHTMLEventObj *iface, VARIANT_BOOL *p) 00388 { 00389 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00390 PRBool ret = FALSE; 00391 00392 TRACE("(%p)->(%p)\n", This, p); 00393 00394 if(This->nsevent) { 00395 nsIDOMKeyEvent *key_event; 00396 nsresult nsres; 00397 00398 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); 00399 if(NS_SUCCEEDED(nsres)) { 00400 nsIDOMKeyEvent_GetShiftKey(key_event, &ret); 00401 nsIDOMKeyEvent_Release(key_event); 00402 }else { 00403 nsIDOMMouseEvent *mouse_event; 00404 00405 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); 00406 if(NS_SUCCEEDED(nsres)) { 00407 nsIDOMMouseEvent_GetShiftKey(mouse_event, &ret); 00408 nsIDOMMouseEvent_Release(mouse_event); 00409 } 00410 } 00411 } 00412 00413 *p = ret ? VARIANT_TRUE : VARIANT_FALSE; 00414 return S_OK; 00415 } 00416 00417 static HRESULT WINAPI HTMLEventObj_put_returnValue(IHTMLEventObj *iface, VARIANT v) 00418 { 00419 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00420 FIXME("(%p)->()\n", This); 00421 return E_NOTIMPL; 00422 } 00423 00424 static HRESULT WINAPI HTMLEventObj_get_returnValue(IHTMLEventObj *iface, VARIANT *p) 00425 { 00426 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00427 00428 FIXME("(%p)->(%p)\n", This, p); 00429 00430 V_VT(p) = VT_EMPTY; 00431 return S_OK; 00432 } 00433 00434 static HRESULT WINAPI HTMLEventObj_put_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL v) 00435 { 00436 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00437 FIXME("(%p)->(%x)\n", This, v); 00438 return E_NOTIMPL; 00439 } 00440 00441 static HRESULT WINAPI HTMLEventObj_get_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL *p) 00442 { 00443 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00444 00445 FIXME("(%p)->(%p)\n", This, p); 00446 00447 *p = VARIANT_FALSE; 00448 return S_OK; 00449 } 00450 00451 static HRESULT WINAPI HTMLEventObj_get_fromElement(IHTMLEventObj *iface, IHTMLElement **p) 00452 { 00453 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00454 00455 FIXME("(%p)->(%p)\n", This, p); 00456 00457 *p = NULL; 00458 return S_OK; 00459 } 00460 00461 static HRESULT WINAPI HTMLEventObj_get_toElement(IHTMLEventObj *iface, IHTMLElement **p) 00462 { 00463 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00464 00465 FIXME("(%p)->(%p)\n", This, p); 00466 00467 *p = NULL; 00468 return S_OK; 00469 } 00470 00471 static HRESULT WINAPI HTMLEventObj_put_keyCode(IHTMLEventObj *iface, LONG v) 00472 { 00473 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00474 FIXME("(%p)->(%d)\n", This, v); 00475 return E_NOTIMPL; 00476 } 00477 00478 static HRESULT WINAPI HTMLEventObj_get_keyCode(IHTMLEventObj *iface, LONG *p) 00479 { 00480 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00481 PRUint32 key_code = 0; 00482 00483 TRACE("(%p)->(%p)\n", This, p); 00484 00485 if(This->nsevent) { 00486 nsIDOMKeyEvent *key_event; 00487 nsresult nsres; 00488 00489 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); 00490 if(NS_SUCCEEDED(nsres)) { 00491 nsIDOMKeyEvent_GetKeyCode(key_event, &key_code); 00492 nsIDOMKeyEvent_Release(key_event); 00493 } 00494 } 00495 00496 *p = key_code; 00497 return S_OK; 00498 } 00499 00500 static HRESULT WINAPI HTMLEventObj_get_button(IHTMLEventObj *iface, LONG *p) 00501 { 00502 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00503 PRUint16 button = 0; 00504 00505 TRACE("(%p)->(%p)\n", This, p); 00506 00507 if(This->nsevent) { 00508 nsIDOMMouseEvent *mouse_event; 00509 nsresult nsres; 00510 00511 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); 00512 if(NS_SUCCEEDED(nsres)) { 00513 nsIDOMMouseEvent_GetButton(mouse_event, &button); 00514 nsIDOMMouseEvent_Release(mouse_event); 00515 } 00516 } 00517 00518 *p = button; 00519 return S_OK; 00520 } 00521 00522 static HRESULT WINAPI HTMLEventObj_get_type(IHTMLEventObj *iface, BSTR *p) 00523 { 00524 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00525 00526 TRACE("(%p)->(%p)\n", This, p); 00527 00528 *p = SysAllocString(This->type->name); 00529 return *p ? S_OK : E_OUTOFMEMORY; 00530 } 00531 00532 static HRESULT WINAPI HTMLEventObj_get_qualifier(IHTMLEventObj *iface, BSTR *p) 00533 { 00534 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00535 00536 FIXME("(%p)->(%p)\n", This, p); 00537 00538 *p = NULL; 00539 return S_OK; 00540 } 00541 00542 static HRESULT WINAPI HTMLEventObj_get_reason(IHTMLEventObj *iface, LONG *p) 00543 { 00544 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00545 00546 FIXME("(%p)->(%p)\n", This, p); 00547 00548 *p = 0; 00549 return S_OK; 00550 } 00551 00552 static HRESULT WINAPI HTMLEventObj_get_x(IHTMLEventObj *iface, LONG *p) 00553 { 00554 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00555 00556 FIXME("(%p)->(%p)\n", This, p); 00557 00558 *p = -1; 00559 return S_OK; 00560 } 00561 00562 static HRESULT WINAPI HTMLEventObj_get_y(IHTMLEventObj *iface, LONG *p) 00563 { 00564 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00565 00566 FIXME("(%p)->(%p)\n", This, p); 00567 00568 *p = -1; 00569 return S_OK; 00570 } 00571 00572 static HRESULT WINAPI HTMLEventObj_get_clientX(IHTMLEventObj *iface, LONG *p) 00573 { 00574 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00575 PRInt32 x = 0; 00576 00577 TRACE("(%p)->(%p)\n", This, p); 00578 00579 if(This->nsevent) { 00580 nsIDOMMouseEvent *mouse_event; 00581 nsresult nsres; 00582 00583 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); 00584 if(NS_SUCCEEDED(nsres)) { 00585 nsIDOMMouseEvent_GetClientX(mouse_event, &x); 00586 nsIDOMMouseEvent_Release(mouse_event); 00587 } 00588 } 00589 00590 *p = x; 00591 return S_OK; 00592 } 00593 00594 static HRESULT WINAPI HTMLEventObj_get_clientY(IHTMLEventObj *iface, LONG *p) 00595 { 00596 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00597 PRInt32 y = 0; 00598 00599 TRACE("(%p)->(%p)\n", This, p); 00600 00601 if(This->nsevent) { 00602 nsIDOMMouseEvent *mouse_event; 00603 nsresult nsres; 00604 00605 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); 00606 if(NS_SUCCEEDED(nsres)) { 00607 nsIDOMMouseEvent_GetClientY(mouse_event, &y); 00608 nsIDOMMouseEvent_Release(mouse_event); 00609 } 00610 } 00611 00612 *p = y; 00613 return S_OK; 00614 } 00615 00616 static HRESULT WINAPI HTMLEventObj_get_offsetX(IHTMLEventObj *iface, LONG *p) 00617 { 00618 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00619 00620 FIXME("(%p)->(%p)\n", This, p); 00621 00622 *p = 0; 00623 return S_OK; 00624 } 00625 00626 static HRESULT WINAPI HTMLEventObj_get_offsetY(IHTMLEventObj *iface, LONG *p) 00627 { 00628 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00629 00630 FIXME("(%p)->(%p)\n", This, p); 00631 00632 *p = 0; 00633 return S_OK; 00634 } 00635 00636 static HRESULT WINAPI HTMLEventObj_get_screenX(IHTMLEventObj *iface, LONG *p) 00637 { 00638 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00639 PRInt32 x = 0; 00640 00641 TRACE("(%p)->(%p)\n", This, p); 00642 00643 if(This->nsevent) { 00644 nsIDOMMouseEvent *mouse_event; 00645 nsresult nsres; 00646 00647 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); 00648 if(NS_SUCCEEDED(nsres)) { 00649 nsIDOMMouseEvent_GetScreenX(mouse_event, &x); 00650 nsIDOMMouseEvent_Release(mouse_event); 00651 } 00652 } 00653 00654 *p = x; 00655 return S_OK; 00656 } 00657 00658 static HRESULT WINAPI HTMLEventObj_get_screenY(IHTMLEventObj *iface, LONG *p) 00659 { 00660 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00661 PRInt32 y = 0; 00662 00663 TRACE("(%p)->(%p)\n", This, p); 00664 00665 if(This->nsevent) { 00666 nsIDOMMouseEvent *mouse_event; 00667 nsresult nsres; 00668 00669 nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); 00670 if(NS_SUCCEEDED(nsres)) { 00671 nsIDOMMouseEvent_GetScreenY(mouse_event, &y); 00672 nsIDOMMouseEvent_Release(mouse_event); 00673 } 00674 } 00675 00676 *p = y; 00677 return S_OK; 00678 } 00679 00680 static HRESULT WINAPI HTMLEventObj_get_srcFilter(IHTMLEventObj *iface, IDispatch **p) 00681 { 00682 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface); 00683 00684 FIXME("(%p)->(%p)\n", This, p); 00685 00686 *p = NULL; 00687 return S_OK; 00688 } 00689 00690 #undef HTMLEVENTOBJ_THIS 00691 00692 static const IHTMLEventObjVtbl HTMLEventObjVtbl = { 00693 HTMLEventObj_QueryInterface, 00694 HTMLEventObj_AddRef, 00695 HTMLEventObj_Release, 00696 HTMLEventObj_GetTypeInfoCount, 00697 HTMLEventObj_GetTypeInfo, 00698 HTMLEventObj_GetIDsOfNames, 00699 HTMLEventObj_Invoke, 00700 HTMLEventObj_get_srcElement, 00701 HTMLEventObj_get_altKey, 00702 HTMLEventObj_get_ctrlKey, 00703 HTMLEventObj_get_shiftKey, 00704 HTMLEventObj_put_returnValue, 00705 HTMLEventObj_get_returnValue, 00706 HTMLEventObj_put_cancelBubble, 00707 HTMLEventObj_get_cancelBubble, 00708 HTMLEventObj_get_fromElement, 00709 HTMLEventObj_get_toElement, 00710 HTMLEventObj_put_keyCode, 00711 HTMLEventObj_get_keyCode, 00712 HTMLEventObj_get_button, 00713 HTMLEventObj_get_type, 00714 HTMLEventObj_get_qualifier, 00715 HTMLEventObj_get_reason, 00716 HTMLEventObj_get_x, 00717 HTMLEventObj_get_y, 00718 HTMLEventObj_get_clientX, 00719 HTMLEventObj_get_clientY, 00720 HTMLEventObj_get_offsetX, 00721 HTMLEventObj_get_offsetY, 00722 HTMLEventObj_get_screenX, 00723 HTMLEventObj_get_screenY, 00724 HTMLEventObj_get_srcFilter 00725 }; 00726 00727 static const tid_t HTMLEventObj_iface_tids[] = { 00728 IHTMLEventObj_tid, 00729 0 00730 }; 00731 00732 static dispex_static_data_t HTMLEventObj_dispex = { 00733 NULL, 00734 DispCEventObj_tid, 00735 NULL, 00736 HTMLEventObj_iface_tids 00737 }; 00738 00739 static IHTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEvent *nsevent) 00740 { 00741 HTMLEventObj *ret; 00742 00743 ret = heap_alloc(sizeof(*ret)); 00744 if(!ret) 00745 return NULL; 00746 00747 ret->lpIHTMLEventObjVtbl = &HTMLEventObjVtbl; 00748 ret->ref = 1; 00749 ret->type = event_info+eid; 00750 00751 ret->nsevent = nsevent; 00752 if(nsevent) { 00753 nsIDOMEvent_AddRef(nsevent); 00754 }else if(event_types[event_info[eid].type]) { 00755 nsIDOMDocumentEvent *doc_event; 00756 nsresult nsres; 00757 00758 nsres = nsIDOMHTMLDocument_QueryInterface(target->doc->nsdoc, &IID_nsIDOMDocumentEvent, 00759 (void**)&doc_event); 00760 if(NS_SUCCEEDED(nsres)) { 00761 nsAString type_str; 00762 00763 nsAString_InitDepend(&type_str, event_types[event_info[eid].type]); 00764 nsres = nsIDOMDocumentEvent_CreateEvent(doc_event, &type_str, &ret->nsevent); 00765 nsAString_Finish(&type_str); 00766 nsIDOMDocumentEvent_Release(doc_event); 00767 } 00768 if(NS_FAILED(nsres)) { 00769 ERR("Could not create event: %08x\n", nsres); 00770 IHTMLEventObj_Release(HTMLEVENTOBJ(ret)); 00771 return NULL; 00772 } 00773 } 00774 00775 ret->target = target; 00776 IHTMLDOMNode_AddRef(HTMLDOMNODE(target)); 00777 00778 init_dispex(&ret->dispex, (IUnknown*)HTMLEVENTOBJ(ret), &HTMLEventObj_dispex); 00779 00780 return HTMLEVENTOBJ(ret); 00781 } 00782 00783 static HRESULT call_cp_func(IDispatch *disp, DISPID dispid) 00784 { 00785 DISPPARAMS dp = {NULL,NULL,0,0}; 00786 ULONG argerr; 00787 EXCEPINFO ei; 00788 VARIANT vres; 00789 HRESULT hres; 00790 00791 V_VT(&vres) = VT_EMPTY; 00792 memset(&ei, 0, sizeof(ei)); 00793 hres = IDispatch_Invoke(disp, dispid, &IID_NULL, 0, DISPATCH_METHOD, &dp, &vres, &ei, &argerr); 00794 if(SUCCEEDED(hres) && V_VT(&vres) != VT_EMPTY) { 00795 FIXME("handle result %s\n", debugstr_variant(&vres)); 00796 VariantClear(&vres); 00797 } 00798 00799 return hres; 00800 } 00801 00802 static BOOL is_cp_event(cp_static_data_t *data, DISPID dispid) 00803 { 00804 int min, max, i; 00805 HRESULT hres; 00806 00807 if(!data) 00808 return FALSE; 00809 00810 if(!data->ids) { 00811 hres = get_dispids(data->tid, &data->id_cnt, &data->ids); 00812 if(FAILED(hres)) 00813 return FALSE; 00814 } 00815 00816 min = 0; 00817 max = data->id_cnt-1; 00818 while(min <= max) { 00819 i = (min+max)/2; 00820 if(data->ids[i] == dispid) 00821 return TRUE; 00822 00823 if(data->ids[i] < dispid) 00824 min = i+1; 00825 else 00826 max = i-1; 00827 } 00828 00829 return FALSE; 00830 } 00831 00832 static void call_event_handlers(HTMLDocumentNode *doc, IHTMLEventObj *event_obj, event_target_t *event_target, 00833 ConnectionPointContainer *cp_container, eventid_t eid, IDispatch *this_obj) 00834 { 00835 handler_vector_t *handler_vector = NULL; 00836 int i; 00837 HRESULT hres; 00838 00839 if(event_target) 00840 handler_vector = event_target->event_table[eid]; 00841 00842 if(handler_vector && handler_vector->handler_prop) { 00843 DISPID named_arg = DISPID_THIS; 00844 VARIANTARG arg; 00845 DISPPARAMS dp = {&arg, &named_arg, 1, 1}; 00846 00847 V_VT(&arg) = VT_DISPATCH; 00848 V_DISPATCH(&arg) = this_obj; 00849 00850 TRACE("%s >>>\n", debugstr_w(event_info[eid].name)); 00851 hres = call_disp_func(handler_vector->handler_prop, &dp); 00852 if(hres == S_OK) 00853 TRACE("%s <<<\n", debugstr_w(event_info[eid].name)); 00854 else 00855 WARN("%s <<< %08x\n", debugstr_w(event_info[eid].name), hres); 00856 } 00857 00858 if(handler_vector && handler_vector->handler_cnt) { 00859 VARIANTARG arg; 00860 DISPPARAMS dp = {&arg, NULL, 1, 0}; 00861 00862 V_VT(&arg) = VT_DISPATCH; 00863 V_DISPATCH(&arg) = (IDispatch*)event_obj; 00864 00865 i = handler_vector->handler_cnt; 00866 while(i--) { 00867 if(handler_vector->handlers[i]) { 00868 TRACE("%s [%d] >>>\n", debugstr_w(event_info[eid].name), i); 00869 hres = call_disp_func(handler_vector->handlers[i], &dp); 00870 if(hres == S_OK) 00871 TRACE("%s [%d] <<<\n", debugstr_w(event_info[eid].name), i); 00872 else 00873 WARN("%s [%d] <<< %08x\n", debugstr_w(event_info[eid].name), i, hres); 00874 } 00875 } 00876 } 00877 00878 if(cp_container) { 00879 ConnectionPoint *cp; 00880 00881 if(cp_container->forward_container) 00882 cp_container = cp_container->forward_container; 00883 00884 for(cp = cp_container->cp_list; cp; cp = cp->next) { 00885 if(cp->sinks_size && is_cp_event(cp->data, event_info[eid].dispid)) { 00886 for(i=0; i < cp->sinks_size; i++) { 00887 if(!cp->sinks[i].disp) 00888 continue; 00889 00890 TRACE("cp %s [%d] >>>\n", debugstr_w(event_info[eid].name), i); 00891 hres = call_cp_func(cp->sinks[i].disp, event_info[eid].dispid); 00892 if(hres == S_OK) 00893 TRACE("cp %s [%d] <<<\n", debugstr_w(event_info[eid].name), i); 00894 else 00895 WARN("cp %s [%d] <<< %08x\n", debugstr_w(event_info[eid].name), i, hres); 00896 } 00897 } 00898 } 00899 } 00900 } 00901 00902 void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode *target, nsIDOMEvent *nsevent) 00903 { 00904 IHTMLEventObj *prev_event, *event_obj = NULL; 00905 nsIDOMNode *parent, *nsnode; 00906 HTMLDOMNode *node; 00907 PRUint16 node_type; 00908 00909 TRACE("(%p) %s\n", doc, debugstr_w(event_info[eid].name)); 00910 00911 prev_event = doc->basedoc.window->event; 00912 if(set_event) 00913 event_obj = create_event(get_node(doc, target, TRUE), eid, nsevent); 00914 doc->basedoc.window->event = event_obj; 00915 00916 nsIDOMNode_GetNodeType(target, &node_type); 00917 nsnode = target; 00918 nsIDOMNode_AddRef(nsnode); 00919 00920 switch(node_type) { 00921 case ELEMENT_NODE: 00922 do { 00923 node = get_node(doc, nsnode, FALSE); 00924 if(node) 00925 call_event_handlers(doc, event_obj, *get_node_event_target(node), node->cp_container, eid, 00926 (IDispatch*)HTMLDOMNODE(node)); 00927 00928 if(!(event_info[eid].flags & EVENT_BUBBLE)) 00929 break; 00930 00931 nsIDOMNode_GetParentNode(nsnode, &parent); 00932 nsIDOMNode_Release(nsnode); 00933 nsnode = parent; 00934 if(!nsnode) 00935 break; 00936 00937 nsIDOMNode_GetNodeType(nsnode, &node_type); 00938 }while(node_type == ELEMENT_NODE); 00939 00940 if(!(event_info[eid].flags & EVENT_BUBBLE)) 00941 break; 00942 00943 case DOCUMENT_NODE: 00944 if(event_info[eid].flags & EVENT_FORWARDBODY) { 00945 nsIDOMHTMLElement *nsbody; 00946 nsresult nsres; 00947 00948 nsres = nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody); 00949 if(NS_SUCCEEDED(nsres) && nsbody) { 00950 node = get_node(doc, (nsIDOMNode*)nsbody, FALSE); 00951 if(node) 00952 call_event_handlers(doc, event_obj, *get_node_event_target(node), node->cp_container, 00953 eid, (IDispatch*)HTMLDOMNODE(node)); 00954 nsIDOMHTMLElement_Release(nsbody); 00955 }else { 00956 ERR("Could not get body: %08x\n", nsres); 00957 } 00958 } 00959 00960 call_event_handlers(doc, event_obj, doc->node.event_target, &doc->basedoc.cp_container, eid, 00961 (IDispatch*)HTMLDOC(&doc->basedoc)); 00962 break; 00963 00964 default: 00965 FIXME("unimplemented node type %d\n", node_type); 00966 } 00967 00968 if(nsnode) 00969 nsIDOMNode_Release(nsnode); 00970 00971 if(event_obj) 00972 IHTMLEventObj_Release(event_obj); 00973 doc->basedoc.window->event = prev_event; 00974 } 00975 00976 HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *event_obj, VARIANT_BOOL *cancelled) 00977 { 00978 eventid_t eid; 00979 00980 eid = attr_to_eid(event_name); 00981 if(eid == EVENTID_LAST) { 00982 WARN("unknown event %s\n", debugstr_w(event_name)); 00983 return E_INVALIDARG; 00984 } 00985 00986 if(event_obj && V_VT(event_obj) != VT_EMPTY && V_VT(event_obj) != VT_ERROR) 00987 FIXME("event_obj not implemented\n"); 00988 00989 if(!(event_info[eid].flags & EVENT_DEFAULTLISTENER)) { 00990 FIXME("not EVENT_DEFAULTEVENTHANDLER\n"); 00991 return E_NOTIMPL; 00992 } 00993 00994 fire_event(node->doc, eid, TRUE, node->nsnode, NULL); 00995 00996 *cancelled = VARIANT_TRUE; /* FIXME */ 00997 return S_OK; 00998 } 00999 01000 HRESULT call_event(HTMLDOMNode *node, eventid_t eid) 01001 { 01002 HRESULT hres; 01003 01004 if(node->vtbl->call_event) { 01005 BOOL handled = FALSE; 01006 01007 hres = node->vtbl->call_event(node, eid, &handled); 01008 if(handled) 01009 return hres; 01010 } 01011 01012 fire_event(node->doc, eid, TRUE, node->nsnode, NULL); 01013 return S_OK; 01014 } 01015 01016 static inline event_target_t *get_event_target(event_target_t **event_target_ptr) 01017 { 01018 if(!*event_target_ptr) 01019 *event_target_ptr = heap_alloc_zero(sizeof(event_target_t)); 01020 return *event_target_ptr; 01021 } 01022 01023 static BOOL alloc_handler_vector(event_target_t *event_target, eventid_t eid, int cnt) 01024 { 01025 handler_vector_t *new_vector, *handler_vector = event_target->event_table[eid]; 01026 01027 if(handler_vector) { 01028 if(cnt <= handler_vector->handler_cnt) 01029 return TRUE; 01030 01031 new_vector = heap_realloc_zero(handler_vector, sizeof(handler_vector_t) + sizeof(IDispatch*)*cnt); 01032 }else { 01033 new_vector = heap_alloc_zero(sizeof(handler_vector_t) + sizeof(IDispatch*)*cnt); 01034 } 01035 01036 if(!new_vector) 01037 return FALSE; 01038 01039 new_vector->handler_cnt = cnt; 01040 event_target->event_table[eid] = new_vector; 01041 return TRUE; 01042 } 01043 01044 static HRESULT ensure_nsevent_handler(HTMLDocumentNode *doc, event_target_t *event_target, nsIDOMNode *nsnode, eventid_t eid) 01045 { 01046 if(!doc->nsdoc) 01047 return S_OK; 01048 01049 if(event_info[eid].flags & EVENT_NODEHANDLER) { 01050 DWORD mask; 01051 01052 mask = get_node_handler_mask(eid); 01053 if(event_target->node_handlers_mask & mask) 01054 return S_OK; 01055 01056 add_nsevent_listener(doc, nsnode, event_info[eid].name); 01057 event_target->node_handlers_mask |= mask; 01058 return S_OK; 01059 } 01060 01061 if(!(event_info[eid].flags & EVENT_DEFAULTLISTENER)) 01062 return S_OK; 01063 01064 if(!doc->event_vector) { 01065 doc->event_vector = heap_alloc_zero(EVENTID_LAST*sizeof(BOOL)); 01066 if(!doc->event_vector) 01067 return E_OUTOFMEMORY; 01068 } 01069 01070 if(!doc->event_vector[eid]) { 01071 doc->event_vector[eid] = TRUE; 01072 add_nsevent_listener(doc, NULL, event_info[eid].name); 01073 } 01074 01075 return S_OK; 01076 } 01077 01078 static HRESULT remove_event_handler(event_target_t **event_target, eventid_t eid) 01079 { 01080 if(*event_target && (*event_target)->event_table[eid] && (*event_target)->event_table[eid]->handler_prop) { 01081 IDispatch_Release((*event_target)->event_table[eid]->handler_prop); 01082 (*event_target)->event_table[eid]->handler_prop = NULL; 01083 } 01084 01085 return S_OK; 01086 } 01087 01088 static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, nsIDOMNode *nsnode, HTMLDocumentNode *doc, 01089 eventid_t eid, IDispatch *disp) 01090 { 01091 event_target_t *event_target; 01092 01093 if(!disp) 01094 return remove_event_handler(event_target_ptr, eid); 01095 01096 event_target = get_event_target(event_target_ptr); 01097 if(!event_target) 01098 return E_OUTOFMEMORY; 01099 01100 if(!alloc_handler_vector(event_target, eid, 0)) 01101 return E_OUTOFMEMORY; 01102 01103 if(event_target->event_table[eid]->handler_prop) 01104 IDispatch_Release(event_target->event_table[eid]->handler_prop); 01105 01106 event_target->event_table[eid]->handler_prop = disp; 01107 IDispatch_AddRef(disp); 01108 01109 return ensure_nsevent_handler(doc, event_target, nsnode, eid); 01110 } 01111 01112 HRESULT set_event_handler(event_target_t **event_target, nsIDOMNode *nsnode, HTMLDocumentNode *doc, eventid_t eid, VARIANT *var) 01113 { 01114 switch(V_VT(var)) { 01115 case VT_NULL: 01116 return remove_event_handler(event_target, eid); 01117 01118 case VT_DISPATCH: 01119 return set_event_handler_disp(event_target, nsnode, doc, eid, V_DISPATCH(var)); 01120 01121 default: 01122 FIXME("not supported vt=%d\n", V_VT(var)); 01123 case VT_EMPTY: 01124 return E_NOTIMPL; 01125 } 01126 01127 return S_OK; 01128 } 01129 01130 HRESULT get_event_handler(event_target_t **event_target, eventid_t eid, VARIANT *var) 01131 { 01132 if(*event_target && (*event_target)->event_table[eid] && (*event_target)->event_table[eid]->handler_prop) { 01133 V_VT(var) = VT_DISPATCH; 01134 V_DISPATCH(var) = (*event_target)->event_table[eid]->handler_prop; 01135 IDispatch_AddRef(V_DISPATCH(var)); 01136 }else { 01137 V_VT(var) = VT_NULL; 01138 } 01139 01140 return S_OK; 01141 } 01142 01143 HRESULT attach_event(event_target_t **event_target_ptr, nsIDOMNode *nsnode, HTMLDocument *doc, BSTR name, 01144 IDispatch *disp, VARIANT_BOOL *res) 01145 { 01146 event_target_t *event_target; 01147 eventid_t eid; 01148 DWORD i = 0; 01149 01150 eid = attr_to_eid(name); 01151 if(eid == EVENTID_LAST) { 01152 WARN("Unknown event\n"); 01153 *res = VARIANT_TRUE; 01154 return S_OK; 01155 } 01156 01157 event_target = get_event_target(event_target_ptr); 01158 if(!event_target) 01159 return E_OUTOFMEMORY; 01160 01161 if(event_target->event_table[eid]) { 01162 while(i < event_target->event_table[eid]->handler_cnt && event_target->event_table[eid]->handlers[i]) 01163 i++; 01164 if(i == event_target->event_table[eid]->handler_cnt && !alloc_handler_vector(event_target, eid, i+1)) 01165 return E_OUTOFMEMORY; 01166 }else if(!alloc_handler_vector(event_target, eid, i+1)) { 01167 return E_OUTOFMEMORY; 01168 } 01169 01170 IDispatch_AddRef(disp); 01171 event_target->event_table[eid]->handlers[i] = disp; 01172 01173 *res = VARIANT_TRUE; 01174 return ensure_nsevent_handler(doc->doc_node, event_target, nsnode, eid); 01175 } 01176 01177 HRESULT detach_event(event_target_t *event_target, HTMLDocument *doc, BSTR name, IDispatch *disp) 01178 { 01179 eventid_t eid; 01180 DWORD i = 0; 01181 01182 if(!event_target) 01183 return S_OK; 01184 01185 eid = attr_to_eid(name); 01186 if(eid == EVENTID_LAST) { 01187 WARN("Unknown event\n"); 01188 return S_OK; 01189 } 01190 01191 if(!event_target->event_table[eid]) 01192 return S_OK; 01193 01194 while(i < event_target->event_table[eid]->handler_cnt) { 01195 if(event_target->event_table[eid]->handlers[i] == disp) { 01196 IDispatch_Release(event_target->event_table[eid]->handlers[i]); 01197 event_target->event_table[eid]->handlers[i] = NULL; 01198 } 01199 i++; 01200 } 01201 01202 return S_OK; 01203 } 01204 01205 void update_cp_events(HTMLWindow *window, event_target_t **event_target_ptr, cp_static_data_t *cp, nsIDOMNode *nsnode) 01206 { 01207 event_target_t *event_target; 01208 int i; 01209 01210 event_target = get_event_target(event_target_ptr); 01211 if(!event_target) 01212 return; /* FIXME */ 01213 01214 for(i=0; i < EVENTID_LAST; i++) { 01215 if((event_info[i].flags & EVENT_DEFAULTLISTENER) && is_cp_event(cp, event_info[i].dispid)) 01216 ensure_nsevent_handler(window->doc, event_target, nsnode, i); 01217 } 01218 } 01219 01220 void check_event_attr(HTMLDocumentNode *doc, nsIDOMElement *nselem) 01221 { 01222 const PRUnichar *attr_value; 01223 nsAString attr_name_str, attr_value_str; 01224 IDispatch *disp; 01225 HTMLDOMNode *node; 01226 int i; 01227 nsresult nsres; 01228 01229 nsAString_Init(&attr_value_str, NULL); 01230 nsAString_Init(&attr_name_str, NULL); 01231 01232 for(i=0; i < EVENTID_LAST; i++) { 01233 nsAString_SetData(&attr_name_str, event_info[i].attr_name); 01234 nsres = nsIDOMElement_GetAttribute(nselem, &attr_name_str, &attr_value_str); 01235 if(NS_SUCCEEDED(nsres)) { 01236 nsAString_GetData(&attr_value_str, &attr_value); 01237 if(!*attr_value) 01238 continue; 01239 01240 TRACE("%p.%s = %s\n", nselem, debugstr_w(event_info[i].attr_name), debugstr_w(attr_value)); 01241 01242 disp = script_parse_event(doc->basedoc.window, attr_value); 01243 if(disp) { 01244 node = get_node(doc, (nsIDOMNode*)nselem, TRUE); 01245 set_event_handler_disp(get_node_event_target(node), node->nsnode, node->doc, i, disp); 01246 IDispatch_Release(disp); 01247 } 01248 } 01249 } 01250 01251 nsAString_Finish(&attr_value_str); 01252 nsAString_Finish(&attr_name_str); 01253 } 01254 01255 void release_event_target(event_target_t *event_target) 01256 { 01257 int i, j; 01258 01259 for(i=0; i < EVENTID_LAST; i++) { 01260 if(event_target->event_table[i]) { 01261 if(event_target->event_table[i]->handler_prop) 01262 IDispatch_Release(event_target->event_table[i]->handler_prop); 01263 for(j=0; j < event_target->event_table[i]->handler_cnt; j++) 01264 IDispatch_Release(event_target->event_table[i]->handlers[j]); 01265 } 01266 } 01267 01268 heap_free(event_target); 01269 } Generated on Sat May 26 2012 04:23:30 for ReactOS by
1.7.6.1
|