mshtml: Added IHTMLElement::put_onmouseover implementation.
[wine/hacks.git] / dlls / mshtml / htmlevent.c
blob2b05eb7838b1c4de631f28078163387d5a009d43
1 /*
2 * Copyright 2008 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
28 #include "mshtml_private.h"
29 #include "htmlevent.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
35 struct event_target_t {
36 IDispatch *event_table[EVENTID_LAST];
39 static const WCHAR changeW[] = {'c','h','a','n','g','e',0};
40 static const WCHAR onchangeW[] = {'o','n','c','h','a','n','g','e',0};
42 static const WCHAR clickW[] = {'c','l','i','c','k',0};
43 static const WCHAR onclickW[] = {'o','n','c','l','i','c','k',0};
45 static const WCHAR keyupW[] = {'k','e','y','u','p',0};
46 static const WCHAR onkeyupW[] = {'o','n','k','e','y','u','p',0};
48 static const WCHAR loadW[] = {'l','o','a','d',0};
49 static const WCHAR onloadW[] = {'o','n','l','o','a','d',0};
51 static const WCHAR mouseoverW[] = {'m','o','u','s','e','o','v','e','r',0};
52 static const WCHAR onmouseoverW[] = {'o','n','m','o','u','s','e','o','v','e','r',0};
54 typedef struct {
55 LPCWSTR name;
56 LPCWSTR attr_name;
57 DWORD flags;
58 } event_info_t;
60 #define EVENT_DEFAULTLISTENER 0x0001
62 static const event_info_t event_info[] = {
63 {changeW, onchangeW, EVENT_DEFAULTLISTENER},
64 {clickW, onclickW, EVENT_DEFAULTLISTENER},
65 {keyupW, onkeyupW, EVENT_DEFAULTLISTENER},
66 {loadW, onloadW, 0},
67 {mouseoverW, onmouseoverW, EVENT_DEFAULTLISTENER}
70 eventid_t str_to_eid(LPCWSTR str)
72 int i;
74 for(i=0; i < sizeof(event_info)/sizeof(event_info[0]); i++) {
75 if(!strcmpW(event_info[i].name, str))
76 return i;
79 ERR("unknown type %s\n", debugstr_w(str));
80 return EVENTID_LAST;
83 typedef struct {
84 DispatchEx dispex;
85 const IHTMLEventObjVtbl *lpIHTMLEventObjVtbl;
86 LONG ref;
87 } HTMLEventObj;
89 #define HTMLEVENTOBJ(x) ((IHTMLEventObj*) &(x)->lpIHTMLEventObjVtbl)
91 #define HTMLEVENTOBJ_THIS(iface) DEFINE_THIS(HTMLEventObj, IHTMLEventObj, iface)
93 static HRESULT WINAPI HTMLEventObj_QueryInterface(IHTMLEventObj *iface, REFIID riid, void **ppv)
95 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
97 *ppv = NULL;
99 if(IsEqualGUID(&IID_IUnknown, riid)) {
100 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
101 *ppv = HTMLEVENTOBJ(This);
102 }else if(IsEqualGUID(&IID_IHTMLEventObj, riid)) {
103 TRACE("(%p)->(IID_IHTMLEventObj %p)\n", This, ppv);
104 *ppv = HTMLEVENTOBJ(This);
105 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
106 return *ppv ? S_OK : E_NOINTERFACE;
109 if(*ppv) {
110 IUnknown_AddRef((IUnknown*)*ppv);
111 return S_OK;
114 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
115 return E_NOINTERFACE;
118 static ULONG WINAPI HTMLEventObj_AddRef(IHTMLEventObj *iface)
120 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
121 LONG ref = InterlockedIncrement(&This->ref);
123 TRACE("(%p) ref=%d\n", This, ref);
125 return ref;
128 static ULONG WINAPI HTMLEventObj_Release(IHTMLEventObj *iface)
130 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
131 LONG ref = InterlockedDecrement(&This->ref);
133 TRACE("(%p) ref=%d\n", This, ref);
135 if(!ref)
136 heap_free(This);
138 return ref;
141 static HRESULT WINAPI HTMLEventObj_GetTypeInfoCount(IHTMLEventObj *iface, UINT *pctinfo)
143 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
144 FIXME("(%p)->(%p)\n", This, pctinfo);
145 return E_NOTIMPL;
148 static HRESULT WINAPI HTMLEventObj_GetTypeInfo(IHTMLEventObj *iface, UINT iTInfo,
149 LCID lcid, ITypeInfo **ppTInfo)
151 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
152 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
153 return E_NOTIMPL;
156 static HRESULT WINAPI HTMLEventObj_GetIDsOfNames(IHTMLEventObj *iface, REFIID riid,
157 LPOLESTR *rgszNames, UINT cNames,
158 LCID lcid, DISPID *rgDispId)
160 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
161 FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
162 lcid, rgDispId);
163 return E_NOTIMPL;
166 static HRESULT WINAPI HTMLEventObj_Invoke(IHTMLEventObj *iface, DISPID dispIdMember,
167 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
168 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
170 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
171 FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
172 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
173 return E_NOTIMPL;
176 static HRESULT WINAPI HTMLEventObj_get_srcElement(IHTMLEventObj *iface, IHTMLElement **p)
178 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
179 FIXME("(%p)->(%p)\n", This, p);
180 return E_NOTIMPL;
183 static HRESULT WINAPI HTMLEventObj_get_altKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
185 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
186 FIXME("(%p)->(%p)\n", This, p);
187 return E_NOTIMPL;
190 static HRESULT WINAPI HTMLEventObj_get_ctrlKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
192 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
193 FIXME("(%p)->(%p)\n", This, p);
194 return E_NOTIMPL;
197 static HRESULT WINAPI HTMLEventObj_get_shiftKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
199 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
200 FIXME("(%p)->(%p)\n", This, p);
201 return E_NOTIMPL;
204 static HRESULT WINAPI HTMLEventObj_put_returnValue(IHTMLEventObj *iface, VARIANT v)
206 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
207 FIXME("(%p)->()\n", This);
208 return E_NOTIMPL;
211 static HRESULT WINAPI HTMLEventObj_get_returnValue(IHTMLEventObj *iface, VARIANT *p)
213 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
214 FIXME("(%p)->(%p)\n", This, p);
215 return E_NOTIMPL;
218 static HRESULT WINAPI HTMLEventObj_put_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL v)
220 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
221 FIXME("(%p)->(%x)\n", This, v);
222 return E_NOTIMPL;
225 static HRESULT WINAPI HTMLEventObj_get_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL *p)
227 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
228 FIXME("(%p)->(%p)\n", This, p);
229 return E_NOTIMPL;
232 static HRESULT WINAPI HTMLEventObj_get_fromElement(IHTMLEventObj *iface, IHTMLElement **p)
234 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
235 FIXME("(%p)->(%p)\n", This, p);
236 return E_NOTIMPL;
239 static HRESULT WINAPI HTMLEventObj_get_toElement(IHTMLEventObj *iface, IHTMLElement **p)
241 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
242 FIXME("(%p)->(%p)\n", This, p);
243 return E_NOTIMPL;
246 static HRESULT WINAPI HTMLEventObj_put_keyCode(IHTMLEventObj *iface, long v)
248 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
249 FIXME("(%p)->(%ld)\n", This, v);
250 return E_NOTIMPL;
253 static HRESULT WINAPI HTMLEventObj_get_keyCode(IHTMLEventObj *iface, long *p)
255 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
256 FIXME("(%p)->(%p)\n", This, p);
257 return E_NOTIMPL;
260 static HRESULT WINAPI HTMLEventObj_get_button(IHTMLEventObj *iface, long *p)
262 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
263 FIXME("(%p)->(%p)\n", This, p);
264 return E_NOTIMPL;
267 static HRESULT WINAPI HTMLEventObj_get_type(IHTMLEventObj *iface, BSTR *p)
269 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
270 FIXME("(%p)->(%p)\n", This, p);
271 return E_NOTIMPL;
274 static HRESULT WINAPI HTMLEventObj_get_qualifier(IHTMLEventObj *iface, BSTR *p)
276 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
277 FIXME("(%p)->(%p)\n", This, p);
278 return E_NOTIMPL;
281 static HRESULT WINAPI HTMLEventObj_get_reason(IHTMLEventObj *iface, long *p)
283 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
284 FIXME("(%p)->(%p)\n", This, p);
285 return E_NOTIMPL;
288 static HRESULT WINAPI HTMLEventObj_get_x(IHTMLEventObj *iface, long *p)
290 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
291 FIXME("(%p)->(%p)\n", This, p);
292 return E_NOTIMPL;
295 static HRESULT WINAPI HTMLEventObj_get_y(IHTMLEventObj *iface, long *p)
297 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
298 FIXME("(%p)->(%p)\n", This, p);
299 return E_NOTIMPL;
302 static HRESULT WINAPI HTMLEventObj_get_clientX(IHTMLEventObj *iface, long *p)
304 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
305 FIXME("(%p)->(%p)\n", This, p);
306 return E_NOTIMPL;
309 static HRESULT WINAPI HTMLEventObj_get_clientY(IHTMLEventObj *iface, long *p)
311 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
312 FIXME("(%p)->(%p)\n", This, p);
313 return E_NOTIMPL;
316 static HRESULT WINAPI HTMLEventObj_get_offsetX(IHTMLEventObj *iface, long *p)
318 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
319 FIXME("(%p)->(%p)\n", This, p);
320 return E_NOTIMPL;
323 static HRESULT WINAPI HTMLEventObj_get_offsetY(IHTMLEventObj *iface, long *p)
325 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
326 FIXME("(%p)->(%p)\n", This, p);
327 return E_NOTIMPL;
330 static HRESULT WINAPI HTMLEventObj_get_screenX(IHTMLEventObj *iface, long *p)
332 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
333 FIXME("(%p)->(%p)\n", This, p);
334 return E_NOTIMPL;
337 static HRESULT WINAPI HTMLEventObj_get_screenY(IHTMLEventObj *iface, long *p)
339 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
340 FIXME("(%p)->(%p)\n", This, p);
341 return E_NOTIMPL;
344 static HRESULT WINAPI HTMLEventObj_get_srcFilter(IHTMLEventObj *iface, IDispatch **p)
346 HTMLEventObj *This = HTMLEVENTOBJ_THIS(iface);
347 FIXME("(%p)->(%p)\n", This, p);
348 return E_NOTIMPL;
351 #undef HTMLEVENTOBJ_THIS
353 static const IHTMLEventObjVtbl HTMLEventObjVtbl = {
354 HTMLEventObj_QueryInterface,
355 HTMLEventObj_AddRef,
356 HTMLEventObj_Release,
357 HTMLEventObj_GetTypeInfoCount,
358 HTMLEventObj_GetTypeInfo,
359 HTMLEventObj_GetIDsOfNames,
360 HTMLEventObj_Invoke,
361 HTMLEventObj_get_srcElement,
362 HTMLEventObj_get_altKey,
363 HTMLEventObj_get_ctrlKey,
364 HTMLEventObj_get_shiftKey,
365 HTMLEventObj_put_returnValue,
366 HTMLEventObj_get_returnValue,
367 HTMLEventObj_put_cancelBubble,
368 HTMLEventObj_get_cancelBubble,
369 HTMLEventObj_get_fromElement,
370 HTMLEventObj_get_toElement,
371 HTMLEventObj_put_keyCode,
372 HTMLEventObj_get_keyCode,
373 HTMLEventObj_get_button,
374 HTMLEventObj_get_type,
375 HTMLEventObj_get_qualifier,
376 HTMLEventObj_get_reason,
377 HTMLEventObj_get_x,
378 HTMLEventObj_get_y,
379 HTMLEventObj_get_clientX,
380 HTMLEventObj_get_clientY,
381 HTMLEventObj_get_offsetX,
382 HTMLEventObj_get_offsetY,
383 HTMLEventObj_get_screenX,
384 HTMLEventObj_get_screenY,
385 HTMLEventObj_get_srcFilter
388 static const tid_t HTMLEventObj_iface_tids[] = {
389 IHTMLEventObj_tid,
393 static dispex_static_data_t HTMLEventObj_dispex = {
394 NULL,
395 DispCEventObj_tid,
396 NULL,
397 HTMLEventObj_iface_tids
400 static IHTMLEventObj *create_event(void)
402 HTMLEventObj *ret;
404 ret = heap_alloc(sizeof(*ret));
405 ret->lpIHTMLEventObjVtbl = &HTMLEventObjVtbl;
406 ret->ref = 1;
408 init_dispex(&ret->dispex, (IUnknown*)HTMLEVENTOBJ(ret), &HTMLEventObj_dispex);
410 return HTMLEVENTOBJ(ret);
413 void fire_event(HTMLDocument *doc, eventid_t eid, nsIDOMNode *target)
415 HTMLDOMNode *node;
417 node = get_node(doc, target, FALSE);
418 if(!node)
419 return;
421 if(node->event_target && node->event_target->event_table[eid]) {
422 doc->window->event = create_event();
424 TRACE("%s >>>\n", debugstr_w(event_info[eid].name));
425 call_disp_func(doc, node->event_target->event_table[eid]);
426 TRACE("%s <<<\n", debugstr_w(event_info[eid].name));
428 IHTMLEventObj_Release(doc->window->event);
429 doc->window->event = NULL;
433 static HRESULT set_node_event_disp(HTMLDOMNode *node, eventid_t eid, IDispatch *disp)
435 if(!node->event_target)
436 node->event_target = heap_alloc_zero(sizeof(event_target_t));
437 else if(node->event_target->event_table[eid])
438 IDispatch_Release(node->event_target->event_table[eid]);
440 IDispatch_AddRef(disp);
441 node->event_target->event_table[eid] = disp;
443 if(event_info[eid].flags & EVENT_DEFAULTLISTENER) {
444 if(!node->doc->nscontainer->event_vector) {
445 node->doc->nscontainer->event_vector = heap_alloc_zero(EVENTID_LAST*sizeof(BOOL));
446 if(!node->doc->nscontainer->event_vector)
447 return E_OUTOFMEMORY;
450 if(!node->doc->nscontainer->event_vector[eid]) {
451 node->doc->nscontainer->event_vector[eid] = TRUE;
452 add_nsevent_listener(node->doc->nscontainer, event_info[eid].name);
456 return S_OK;
459 HRESULT set_node_event(HTMLDOMNode *node, eventid_t eid, VARIANT *var)
461 switch(V_VT(var)) {
462 case VT_DISPATCH:
463 return set_node_event_disp(node, eid, V_DISPATCH(var));
465 default:
466 FIXME("not supported vt=%d\n", V_VT(var));
469 return E_NOTIMPL;
472 void check_event_attr(HTMLDocument *doc, nsIDOMElement *nselem)
474 const PRUnichar *attr_value;
475 nsAString attr_name_str, attr_value_str;
476 IDispatch *disp;
477 HTMLDOMNode *node;
478 int i;
479 nsresult nsres;
481 nsAString_Init(&attr_value_str, NULL);
482 nsAString_Init(&attr_name_str, NULL);
484 for(i=0; i < EVENTID_LAST; i++) {
485 nsAString_SetData(&attr_name_str, event_info[i].attr_name);
486 nsres = nsIDOMElement_GetAttribute(nselem, &attr_name_str, &attr_value_str);
487 if(NS_SUCCEEDED(nsres)) {
488 nsAString_GetData(&attr_value_str, &attr_value);
489 if(!*attr_value)
490 continue;
492 TRACE("%p.%s = %s\n", nselem, debugstr_w(event_info[i].attr_name), debugstr_w(attr_value));
494 disp = script_parse_event(doc, attr_value);
495 if(disp) {
496 node = get_node(doc, (nsIDOMNode*)nselem, TRUE);
497 set_node_event_disp(node, i, disp);
498 IDispatch_Release(disp);
503 nsAString_Finish(&attr_value_str);
504 nsAString_Finish(&attr_name_str);
507 void release_event_target(event_target_t *event_target)
509 int i;
511 for(i=0; i < EVENTID_LAST; i++) {
512 if(event_target->event_table[i])
513 IDispatch_Release(event_target->event_table[i]);
516 heap_free(event_target);