ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

htmlevent.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.