mshtml: Correctly handle comment nodes in IHTMLElement::[get|put]_title implementation.
[wine] / dlls / mshtml / htmlelem.c
1 /*
2  * Copyright 2006 Jacek Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19
20 #include <stdarg.h>
21
22 #define COBJMACROS
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "ole2.h"
29 #include "shlwapi.h"
30
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33
34 #include "mshtml_private.h"
35 #include "htmlevent.h"
36
37 typedef struct
38 {
39     DispatchEx dispex;
40     const IHTMLFiltersCollectionVtbl *lpHTMLFiltersCollectionVtbl;
41
42     LONG ref;
43 } HTMLFiltersCollection;
44
45 #define HTMLFILTERSCOLLECTION(x)     ((IHTMLFiltersCollection*)  &(x)->lpHTMLFiltersCollectionVtbl)
46
47 #define HTMLFILTERSCOLLECTION_THIS(iface) \
48     DEFINE_THIS(HTMLFiltersCollection, HTMLFiltersCollection, iface)
49
50 IHTMLFiltersCollection *HTMLFiltersCollection_Create(void);
51
52
53 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
54
55 #define HTMLELEM_THIS(iface) DEFINE_THIS(HTMLElement, HTMLElement, iface)
56
57 HRESULT create_nselem(HTMLDocumentNode *doc, const WCHAR *tag, nsIDOMHTMLElement **ret)
58 {
59     nsIDOMElement *nselem;
60     nsAString tag_str;
61     nsresult nsres;
62
63     if(!doc->nsdoc) {
64         WARN("NULL nsdoc\n");
65         return E_UNEXPECTED;
66     }
67
68     nsAString_InitDepend(&tag_str, tag);
69     nsres = nsIDOMDocument_CreateElement(doc->nsdoc, &tag_str, &nselem);
70     nsAString_Finish(&tag_str);
71     if(NS_FAILED(nsres)) {
72         ERR("CreateElement failed: %08x\n", nsres);
73         return E_FAIL;
74     }
75
76     nsres = nsIDOMElement_QueryInterface(nselem, &IID_nsIDOMHTMLElement, (void**)ret);
77     nsIDOMElement_Release(nselem);
78     if(NS_FAILED(nsres)) {
79         ERR("Could not get nsIDOMHTMLElement iface: %08x\n", nsres);
80         return E_FAIL;
81     }
82
83     return S_OK;
84 }
85
86 #define HTMLELEM_NODE_THIS(iface) DEFINE_THIS2(HTMLElement, node, iface)
87
88 static HRESULT WINAPI HTMLElement_QueryInterface(IHTMLElement *iface,
89                                                  REFIID riid, void **ppv)
90 {
91     HTMLElement *This = HTMLELEM_THIS(iface);
92
93     return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(&This->node), riid, ppv);
94 }
95
96 static ULONG WINAPI HTMLElement_AddRef(IHTMLElement *iface)
97 {
98     HTMLElement *This = HTMLELEM_THIS(iface);
99
100     return IHTMLDOMNode_AddRef(HTMLDOMNODE(&This->node));
101 }
102
103 static ULONG WINAPI HTMLElement_Release(IHTMLElement *iface)
104 {
105     HTMLElement *This = HTMLELEM_THIS(iface);
106
107     return IHTMLDOMNode_Release(HTMLDOMNODE(&This->node));
108 }
109
110 static HRESULT WINAPI HTMLElement_GetTypeInfoCount(IHTMLElement *iface, UINT *pctinfo)
111 {
112     HTMLElement *This = HTMLELEM_THIS(iface);
113     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->node.dispex), pctinfo);
114 }
115
116 static HRESULT WINAPI HTMLElement_GetTypeInfo(IHTMLElement *iface, UINT iTInfo,
117                                               LCID lcid, ITypeInfo **ppTInfo)
118 {
119     HTMLElement *This = HTMLELEM_THIS(iface);
120     return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->node.dispex), iTInfo, lcid, ppTInfo);
121 }
122
123 static HRESULT WINAPI HTMLElement_GetIDsOfNames(IHTMLElement *iface, REFIID riid,
124                                                 LPOLESTR *rgszNames, UINT cNames,
125                                                 LCID lcid, DISPID *rgDispId)
126 {
127     HTMLElement *This = HTMLELEM_THIS(iface);
128     return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->node.dispex), riid, rgszNames, cNames, lcid, rgDispId);
129 }
130
131 static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMember,
132                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
133                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
134 {
135     HTMLElement *This = HTMLELEM_THIS(iface);
136     return IDispatchEx_Invoke(DISPATCHEX(&This->node.dispex), dispIdMember, riid, lcid,
137             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
138 }
139
140 static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName,
141                                                VARIANT AttributeValue, LONG lFlags)
142 {
143     HTMLElement *This = HTMLELEM_THIS(iface);
144     HRESULT hres;
145     DISPID dispid, dispidNamed = DISPID_PROPERTYPUT;
146     DISPPARAMS dispParams;
147     EXCEPINFO excep;
148
149     TRACE("(%p)->(%s . %08x)\n", This, debugstr_w(strAttributeName), lFlags);
150
151     hres = IDispatchEx_GetDispID(DISPATCHEX(&This->node.dispex), strAttributeName,
152             fdexNameCaseInsensitive | fdexNameEnsure, &dispid);
153     if(FAILED(hres))
154         return hres;
155
156     dispParams.cArgs = 1;
157     dispParams.cNamedArgs = 1;
158     dispParams.rgdispidNamedArgs = &dispidNamed;
159     dispParams.rgvarg = &AttributeValue;
160
161     hres = IDispatchEx_InvokeEx(DISPATCHEX(&This->node.dispex), dispid,
162             LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispParams,
163             NULL, &excep, NULL);
164     return hres;
165 }
166
167 static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttributeName,
168                                                LONG lFlags, VARIANT *AttributeValue)
169 {
170     HTMLElement *This = HTMLELEM_THIS(iface);
171     DISPID dispid;
172     HRESULT hres;
173     DISPPARAMS dispParams = {NULL, NULL, 0, 0};
174     EXCEPINFO excep;
175
176     TRACE("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
177
178     hres = IDispatchEx_GetDispID(DISPATCHEX(&This->node.dispex), strAttributeName,
179             fdexNameCaseInsensitive, &dispid);
180     if(hres == DISP_E_UNKNOWNNAME) {
181         V_VT(AttributeValue) = VT_NULL;
182         return S_OK;
183     }
184
185     if(FAILED(hres)) {
186         V_VT(AttributeValue) = VT_NULL;
187         return hres;
188     }
189
190     hres = IDispatchEx_InvokeEx(DISPATCHEX(&This->node.dispex), dispid,
191             LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispParams,
192             AttributeValue, &excep, NULL);
193
194     return hres;
195 }
196
197 static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strAttributeName,
198                                                   LONG lFlags, VARIANT_BOOL *pfSuccess)
199 {
200     HTMLElement *This = HTMLELEM_THIS(iface);
201     FIXME("(%p)->()\n", This);
202     return E_NOTIMPL;
203 }
204
205 static HRESULT WINAPI HTMLElement_put_className(IHTMLElement *iface, BSTR v)
206 {
207     HTMLElement *This = HTMLELEM_THIS(iface);
208     nsAString classname_str;
209     nsresult nsres;
210
211     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
212
213     if(!This->nselem) {
214         FIXME("NULL nselem\n");
215         return E_NOTIMPL;
216     }
217
218     nsAString_InitDepend(&classname_str, v);
219     nsres = nsIDOMHTMLElement_SetClassName(This->nselem, &classname_str);
220     nsAString_Finish(&classname_str);
221     if(NS_FAILED(nsres))
222         ERR("SetClassName failed: %08x\n", nsres);
223
224     return S_OK;
225 }
226
227 static HRESULT WINAPI HTMLElement_get_className(IHTMLElement *iface, BSTR *p)
228 {
229     HTMLElement *This = HTMLELEM_THIS(iface);
230     nsAString class_str;
231     nsresult nsres;
232     HRESULT hres = S_OK;
233
234     TRACE("(%p)->(%p)\n", This, p);
235
236     if(!This->nselem) {
237         FIXME("NULL nselem\n");
238         return E_NOTIMPL;
239     }
240
241     nsAString_Init(&class_str, NULL);
242     nsres = nsIDOMHTMLElement_GetClassName(This->nselem, &class_str);
243
244     if(NS_SUCCEEDED(nsres)) {
245         const PRUnichar *class;
246         nsAString_GetData(&class_str, &class);
247         *p = *class ? SysAllocString(class) : NULL;
248     }else {
249         ERR("GetClassName failed: %08x\n", nsres);
250         hres = E_FAIL;
251     }
252
253     nsAString_Finish(&class_str);
254
255     TRACE("className=%s\n", debugstr_w(*p));
256     return hres;
257 }
258
259 static HRESULT WINAPI HTMLElement_put_id(IHTMLElement *iface, BSTR v)
260 {
261     HTMLElement *This = HTMLELEM_THIS(iface);
262     nsAString id_str;
263     nsresult nsres;
264
265     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
266
267     if(!This->nselem) {
268         FIXME("nselem == NULL\n");
269         return S_OK;
270     }
271
272     nsAString_InitDepend(&id_str, v);
273     nsres = nsIDOMHTMLElement_SetId(This->nselem, &id_str);
274     nsAString_Finish(&id_str);
275     if(NS_FAILED(nsres))
276         ERR("SetId failed: %08x\n", nsres);
277
278     return S_OK;
279 }
280
281 static HRESULT WINAPI HTMLElement_get_id(IHTMLElement *iface, BSTR *p)
282 {
283     HTMLElement *This = HTMLELEM_THIS(iface);
284     const PRUnichar *id;
285     nsAString id_str;
286     nsresult nsres;
287
288     TRACE("(%p)->(%p)\n", This, p);
289
290     *p = NULL;
291
292     if(!This->nselem)
293         return S_OK;
294
295     nsAString_Init(&id_str, NULL);
296     nsres = nsIDOMHTMLElement_GetId(This->nselem, &id_str);
297     nsAString_GetData(&id_str, &id);
298
299     if(NS_FAILED(nsres))
300         ERR("GetId failed: %08x\n", nsres);
301     else if(*id)
302         *p = SysAllocString(id);
303
304     nsAString_Finish(&id_str);
305     return S_OK;
306 }
307
308 static HRESULT WINAPI HTMLElement_get_tagName(IHTMLElement *iface, BSTR *p)
309 {
310     HTMLElement *This = HTMLELEM_THIS(iface);
311     const PRUnichar *tag;
312     nsAString tag_str;
313     nsresult nsres;
314
315     TRACE("(%p)->(%p)\n", This, p);
316
317     if(!This->nselem) {
318         static const WCHAR comment_tagW[] = {'!',0};
319
320         WARN("NULL nselem, assuming comment\n");
321
322         *p = SysAllocString(comment_tagW);
323         return S_OK;
324     }
325
326     nsAString_Init(&tag_str, NULL);
327     nsres = nsIDOMHTMLElement_GetTagName(This->nselem, &tag_str);
328     if(NS_SUCCEEDED(nsres)) {
329         nsAString_GetData(&tag_str, &tag);
330         *p = SysAllocString(tag);
331     }else {
332         ERR("GetTagName failed: %08x\n", nsres);
333         *p = NULL;
334     }
335     nsAString_Finish(&tag_str);
336
337     return S_OK;
338 }
339
340 static HRESULT WINAPI HTMLElement_get_parentElement(IHTMLElement *iface, IHTMLElement **p)
341 {
342     HTMLElement *This = HTMLELEM_THIS(iface);
343     IHTMLDOMNode *node;
344     HRESULT hres;
345
346     TRACE("(%p)->(%p)\n", This, p);
347
348     hres = IHTMLDOMNode_get_parentNode(HTMLDOMNODE(&This->node), &node);
349     if(FAILED(hres))
350         return hres;
351
352     hres = IHTMLDOMNode_QueryInterface(node, &IID_IHTMLElement, (void**)p);
353     IHTMLDOMNode_Release(node);
354     if(FAILED(hres))
355         *p = NULL;
356
357     return S_OK;
358 }
359
360 static HRESULT WINAPI HTMLElement_get_style(IHTMLElement *iface, IHTMLStyle **p)
361 {
362     HTMLElement *This = HTMLELEM_THIS(iface);
363     nsIDOMElementCSSInlineStyle *nselemstyle;
364     nsIDOMCSSStyleDeclaration *nsstyle;
365     nsresult nsres;
366
367     TRACE("(%p)->(%p)\n", This, p);
368
369     if(!This->nselem) {
370         FIXME("NULL nselem\n");
371         return E_NOTIMPL;
372     }
373
374     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMElementCSSInlineStyle,
375                                              (void**)&nselemstyle);
376     if(NS_FAILED(nsres)) {
377         ERR("Coud not get nsIDOMCSSStyleDeclaration interface: %08x\n", nsres);
378         return E_FAIL;
379     }
380
381     nsres = nsIDOMElementCSSInlineStyle_GetStyle(nselemstyle, &nsstyle);
382     nsIDOMElementCSSInlineStyle_Release(nselemstyle);
383     if(NS_FAILED(nsres)) {
384         ERR("GetStyle failed: %08x\n", nsres);
385         return E_FAIL;
386     }
387
388     /* FIXME: Store style instead of creating a new instance in each call */
389     *p = HTMLStyle_Create(nsstyle);
390
391     nsIDOMCSSStyleDeclaration_Release(nsstyle);
392     return S_OK;
393 }
394
395 static HRESULT WINAPI HTMLElement_put_onhelp(IHTMLElement *iface, VARIANT v)
396 {
397     HTMLElement *This = HTMLELEM_THIS(iface);
398     FIXME("(%p)->()\n", This);
399     return E_NOTIMPL;
400 }
401
402 static HRESULT WINAPI HTMLElement_get_onhelp(IHTMLElement *iface, VARIANT *p)
403 {
404     HTMLElement *This = HTMLELEM_THIS(iface);
405     FIXME("(%p)->(%p)\n", This, p);
406     return E_NOTIMPL;
407 }
408
409 static HRESULT WINAPI HTMLElement_put_onclick(IHTMLElement *iface, VARIANT v)
410 {
411     HTMLElement *This = HTMLELEM_THIS(iface);
412
413     TRACE("(%p)->()\n", This);
414
415     return set_node_event(&This->node, EVENTID_CLICK, &v);
416 }
417
418 static HRESULT WINAPI HTMLElement_get_onclick(IHTMLElement *iface, VARIANT *p)
419 {
420     HTMLElement *This = HTMLELEM_THIS(iface);
421
422     TRACE("(%p)->(%p)\n", This, p);
423
424     return get_node_event(&This->node, EVENTID_CLICK, p);
425 }
426
427 static HRESULT WINAPI HTMLElement_put_ondblclick(IHTMLElement *iface, VARIANT v)
428 {
429     HTMLElement *This = HTMLELEM_THIS(iface);
430
431     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
432
433     return set_node_event(&This->node, EVENTID_DBLCLICK, &v);
434 }
435
436 static HRESULT WINAPI HTMLElement_get_ondblclick(IHTMLElement *iface, VARIANT *p)
437 {
438     HTMLElement *This = HTMLELEM_THIS(iface);
439
440     TRACE("(%p)->(%p)\n", This, p);
441
442     return get_node_event(&This->node, EVENTID_DBLCLICK, p);
443 }
444
445 static HRESULT WINAPI HTMLElement_put_onkeydown(IHTMLElement *iface, VARIANT v)
446 {
447     HTMLElement *This = HTMLELEM_THIS(iface);
448
449     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
450
451     return set_node_event(&This->node, EVENTID_KEYDOWN, &v);
452 }
453
454 static HRESULT WINAPI HTMLElement_get_onkeydown(IHTMLElement *iface, VARIANT *p)
455 {
456     HTMLElement *This = HTMLELEM_THIS(iface);
457
458     TRACE("(%p)->(%p)\n", This, p);
459
460     return get_node_event(&This->node, EVENTID_KEYDOWN, p);
461 }
462
463 static HRESULT WINAPI HTMLElement_put_onkeyup(IHTMLElement *iface, VARIANT v)
464 {
465     HTMLElement *This = HTMLELEM_THIS(iface);
466
467     TRACE("(%p)->()\n", This);
468
469     return set_node_event(&This->node, EVENTID_KEYUP, &v);
470 }
471
472 static HRESULT WINAPI HTMLElement_get_onkeyup(IHTMLElement *iface, VARIANT *p)
473 {
474     HTMLElement *This = HTMLELEM_THIS(iface);
475     FIXME("(%p)->(%p)\n", This, p);
476     return E_NOTIMPL;
477 }
478
479 static HRESULT WINAPI HTMLElement_put_onkeypress(IHTMLElement *iface, VARIANT v)
480 {
481     HTMLElement *This = HTMLELEM_THIS(iface);
482     FIXME("(%p)->()\n", This);
483     return E_NOTIMPL;
484 }
485
486 static HRESULT WINAPI HTMLElement_get_onkeypress(IHTMLElement *iface, VARIANT *p)
487 {
488     HTMLElement *This = HTMLELEM_THIS(iface);
489     FIXME("(%p)->(%p)\n", This, p);
490     return E_NOTIMPL;
491 }
492
493 static HRESULT WINAPI HTMLElement_put_onmouseout(IHTMLElement *iface, VARIANT v)
494 {
495     HTMLElement *This = HTMLELEM_THIS(iface);
496
497     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
498
499     return set_node_event(&This->node, EVENTID_MOUSEOUT, &v);
500 }
501
502 static HRESULT WINAPI HTMLElement_get_onmouseout(IHTMLElement *iface, VARIANT *p)
503 {
504     HTMLElement *This = HTMLELEM_THIS(iface);
505
506     TRACE("(%p)->(%p)\n", This, p);
507
508     return get_node_event(&This->node, EVENTID_MOUSEOUT, p);
509 }
510
511 static HRESULT WINAPI HTMLElement_put_onmouseover(IHTMLElement *iface, VARIANT v)
512 {
513     HTMLElement *This = HTMLELEM_THIS(iface);
514
515     TRACE("(%p)->()\n", This);
516
517     return set_node_event(&This->node, EVENTID_MOUSEOVER, &v);
518 }
519
520 static HRESULT WINAPI HTMLElement_get_onmouseover(IHTMLElement *iface, VARIANT *p)
521 {
522     HTMLElement *This = HTMLELEM_THIS(iface);
523
524     TRACE("(%p)->(%p)\n", This, p);
525
526     return get_node_event(&This->node, EVENTID_MOUSEOVER, p);
527 }
528
529 static HRESULT WINAPI HTMLElement_put_onmousemove(IHTMLElement *iface, VARIANT v)
530 {
531     HTMLElement *This = HTMLELEM_THIS(iface);
532     FIXME("(%p)->()\n", This);
533     return E_NOTIMPL;
534 }
535
536 static HRESULT WINAPI HTMLElement_get_onmousemove(IHTMLElement *iface, VARIANT *p)
537 {
538     HTMLElement *This = HTMLELEM_THIS(iface);
539     FIXME("(%p)->(%p)\n", This, p);
540     return E_NOTIMPL;
541 }
542
543 static HRESULT WINAPI HTMLElement_put_onmousedown(IHTMLElement *iface, VARIANT v)
544 {
545     HTMLElement *This = HTMLELEM_THIS(iface);
546
547     TRACE("(%p)->()\n", This);
548
549     return set_node_event(&This->node, EVENTID_MOUSEDOWN, &v);
550 }
551
552 static HRESULT WINAPI HTMLElement_get_onmousedown(IHTMLElement *iface, VARIANT *p)
553 {
554     HTMLElement *This = HTMLELEM_THIS(iface);
555
556     TRACE("(%p)->(%p)\n", This, p);
557
558     return get_node_event(&This->node, EVENTID_MOUSEDOWN, p);
559 }
560
561 static HRESULT WINAPI HTMLElement_put_onmouseup(IHTMLElement *iface, VARIANT v)
562 {
563     HTMLElement *This = HTMLELEM_THIS(iface);
564
565     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
566
567     return set_node_event(&This->node, EVENTID_MOUSEUP, &v);
568 }
569
570 static HRESULT WINAPI HTMLElement_get_onmouseup(IHTMLElement *iface, VARIANT *p)
571 {
572     HTMLElement *This = HTMLELEM_THIS(iface);
573
574     TRACE("(%p)->(%p)\n", This, p);
575
576     return get_node_event(&This->node, EVENTID_MOUSEUP, p);
577 }
578
579 static HRESULT WINAPI HTMLElement_get_document(IHTMLElement *iface, IDispatch **p)
580 {
581     HTMLElement *This = HTMLELEM_THIS(iface);
582
583     TRACE("(%p)->(%p)\n", This, p);
584
585     if(!p)
586         return E_POINTER;
587
588     if(This->node.vtbl->get_document)
589         return This->node.vtbl->get_document(&This->node, p);
590
591     *p = (IDispatch*)HTMLDOC(&This->node.doc->basedoc);
592     IDispatch_AddRef(*p);
593     return S_OK;
594 }
595
596 static const WCHAR titleW[] = {'t','i','t','l','e',0};
597
598 static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v)
599 {
600     HTMLElement *This = HTMLELEM_THIS(iface);
601     nsAString title_str;
602     nsresult nsres;
603
604     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
605
606     if(!This->nselem) {
607         VARIANT *var;
608         HRESULT hres;
609
610         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, TRUE, &var);
611         if(FAILED(hres))
612             return hres;
613
614         VariantClear(var);
615         V_VT(var) = VT_BSTR;
616         V_BSTR(var) = v ? SysAllocString(v) : NULL;
617         return S_OK;
618     }
619
620     nsAString_InitDepend(&title_str, v);
621     nsres = nsIDOMHTMLElement_SetTitle(This->nselem, &title_str);
622     nsAString_Finish(&title_str);
623     if(NS_FAILED(nsres))
624         ERR("SetTitle failed: %08x\n", nsres);
625
626     return S_OK;
627 }
628
629 static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *p)
630 {
631     HTMLElement *This = HTMLELEM_THIS(iface);
632     nsAString title_str;
633     nsresult nsres;
634
635     TRACE("(%p)->(%p)\n", This, p);
636
637     if(!This->nselem) {
638         VARIANT *var;
639         HRESULT hres;
640
641         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, FALSE, &var);
642         if(hres == DISP_E_UNKNOWNNAME) {
643             *p = NULL;
644         }else if(V_VT(var) != VT_BSTR) {
645             FIXME("title = %s\n", debugstr_variant(var));
646             return E_FAIL;
647         }else {
648             *p = V_BSTR(var) ? SysAllocString(V_BSTR(var)) : NULL;
649         }
650
651         return S_OK;
652     }
653
654     nsAString_Init(&title_str, NULL);
655     nsres = nsIDOMHTMLElement_GetTitle(This->nselem, &title_str);
656     if(NS_SUCCEEDED(nsres)) {
657         const PRUnichar *title;
658
659         nsAString_GetData(&title_str, &title);
660         *p = *title ? SysAllocString(title) : NULL;
661     }else {
662         ERR("GetTitle failed: %08x\n", nsres);
663         return E_FAIL;
664     }
665
666     return S_OK;
667 }
668
669 static HRESULT WINAPI HTMLElement_put_language(IHTMLElement *iface, BSTR v)
670 {
671     HTMLElement *This = HTMLELEM_THIS(iface);
672     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
673     return E_NOTIMPL;
674 }
675
676 static HRESULT WINAPI HTMLElement_get_language(IHTMLElement *iface, BSTR *p)
677 {
678     HTMLElement *This = HTMLELEM_THIS(iface);
679     FIXME("(%p)->(%p)\n", This, p);
680     return E_NOTIMPL;
681 }
682
683 static HRESULT WINAPI HTMLElement_put_onselectstart(IHTMLElement *iface, VARIANT v)
684 {
685     HTMLElement *This = HTMLELEM_THIS(iface);
686
687     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
688
689     return set_node_event(&This->node, EVENTID_SELECTSTART, &v);
690 }
691
692 static HRESULT WINAPI HTMLElement_get_onselectstart(IHTMLElement *iface, VARIANT *p)
693 {
694     HTMLElement *This = HTMLELEM_THIS(iface);
695
696     TRACE("(%p)->(%p)\n", This, p);
697
698     return get_node_event(&This->node, EVENTID_SELECTSTART, p);
699 }
700
701 static HRESULT WINAPI HTMLElement_scrollIntoView(IHTMLElement *iface, VARIANT varargStart)
702 {
703     HTMLElement *This = HTMLELEM_THIS(iface);
704     FIXME("(%p)->()\n", This);
705     return E_NOTIMPL;
706 }
707
708 static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pChild,
709                                            VARIANT_BOOL *pfResult)
710 {
711     HTMLElement *This = HTMLELEM_THIS(iface);
712     FIXME("(%p)->(%p %p)\n", This, pChild, pfResult);
713     return E_NOTIMPL;
714 }
715
716 static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, LONG *p)
717 {
718     HTMLElement *This = HTMLELEM_THIS(iface);
719     FIXME("(%p)->(%p)\n", This, p);
720     return E_NOTIMPL;
721 }
722
723 static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
724 {
725     HTMLElement *This = HTMLELEM_THIS(iface);
726     FIXME("(%p)->(%p)\n", This, p);
727     return E_NOTIMPL;
728 }
729
730 static HRESULT WINAPI HTMLElement_put_lang(IHTMLElement *iface, BSTR v)
731 {
732     HTMLElement *This = HTMLELEM_THIS(iface);
733     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
734     return E_NOTIMPL;
735 }
736
737 static HRESULT WINAPI HTMLElement_get_lang(IHTMLElement *iface, BSTR *p)
738 {
739     HTMLElement *This = HTMLELEM_THIS(iface);
740     FIXME("(%p)->(%p)\n", This, p);
741     return E_NOTIMPL;
742 }
743
744 static HRESULT WINAPI HTMLElement_get_offsetLeft(IHTMLElement *iface, LONG *p)
745 {
746     HTMLElement *This = HTMLELEM_THIS(iface);
747     FIXME("(%p)->(%p)\n", This, p);
748     return E_NOTIMPL;
749 }
750
751 static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, LONG *p)
752 {
753     HTMLElement *This = HTMLELEM_THIS(iface);
754     nsIDOMNSHTMLElement *nselem;
755     PRInt32 top = 0;
756     nsresult nsres;
757
758     TRACE("(%p)->(%p)\n", This, p);
759
760     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
761     if(NS_FAILED(nsres)) {
762         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
763         return E_FAIL;
764     }
765
766     nsres = nsIDOMNSHTMLElement_GetOffsetTop(nselem, &top);
767     nsIDOMNSHTMLElement_Release(nselem);
768     if(NS_FAILED(nsres)) {
769         ERR("GetOffsetTop failed: %08x\n", nsres);
770         return E_FAIL;
771     }
772
773     *p = top;
774     return S_OK;
775 }
776
777 static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, LONG *p)
778 {
779     HTMLElement *This = HTMLELEM_THIS(iface);
780     nsIDOMNSHTMLElement *nselem;
781     PRInt32 offset = 0;
782     nsresult nsres;
783
784     TRACE("(%p)->(%p)\n", This, p);
785
786     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
787     if(NS_FAILED(nsres)) {
788         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
789         return E_FAIL;
790     }
791
792     nsres = nsIDOMNSHTMLElement_GetOffsetWidth(nselem, &offset);
793     nsIDOMNSHTMLElement_Release(nselem);
794     if(NS_FAILED(nsres)) {
795         ERR("GetOffsetWidth failed: %08x\n", nsres);
796         return E_FAIL;
797     }
798
799     *p = offset;
800     return S_OK;
801 }
802
803 static HRESULT WINAPI HTMLElement_get_offsetHeight(IHTMLElement *iface, LONG *p)
804 {
805     HTMLElement *This = HTMLELEM_THIS(iface);
806     nsIDOMNSHTMLElement *nselem;
807     PRInt32 offset = 0;
808     nsresult nsres;
809
810     TRACE("(%p)->(%p)\n", This, p);
811
812     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
813     if(NS_FAILED(nsres)) {
814         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
815         return E_FAIL;
816     }
817
818     nsres = nsIDOMNSHTMLElement_GetOffsetHeight(nselem, &offset);
819     nsIDOMNSHTMLElement_Release(nselem);
820     if(NS_FAILED(nsres)) {
821         ERR("GetOffsetHeight failed: %08x\n", nsres);
822         return E_FAIL;
823     }
824
825     *p = offset;
826     return S_OK;
827 }
828
829 static HRESULT WINAPI HTMLElement_get_offsetParent(IHTMLElement *iface, IHTMLElement **p)
830 {
831     HTMLElement *This = HTMLELEM_THIS(iface);
832     FIXME("(%p)->(%p)\n", This, p);
833     return E_NOTIMPL;
834 }
835
836 static HRESULT WINAPI HTMLElement_put_innerHTML(IHTMLElement *iface, BSTR v)
837 {
838     HTMLElement *This = HTMLELEM_THIS(iface);
839     nsIDOMNSHTMLElement *nselem;
840     nsAString html_str;
841     nsresult nsres;
842
843     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
844
845     if(!This->nselem) {
846         FIXME("NULL nselem\n");
847         return E_NOTIMPL;
848     }
849
850     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
851     if(NS_FAILED(nsres)) {
852         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
853         return E_FAIL;
854     }
855
856     nsAString_InitDepend(&html_str, v);
857     nsres = nsIDOMNSHTMLElement_SetInnerHTML(nselem, &html_str);
858     nsAString_Finish(&html_str);
859
860     if(NS_FAILED(nsres)) {
861         FIXME("SetInnerHtml failed %08x\n", nsres);
862         return E_FAIL;
863     }
864
865     return S_OK;
866 }
867
868 static HRESULT WINAPI HTMLElement_get_innerHTML(IHTMLElement *iface, BSTR *p)
869 {
870     HTMLElement *This = HTMLELEM_THIS(iface);
871     nsIDOMNSHTMLElement *nselem;
872     nsAString html_str;
873     nsresult nsres;
874
875     TRACE("(%p)->(%p)\n", This, p);
876
877     if(!This->nselem) {
878         FIXME("NULL nselem\n");
879         return E_NOTIMPL;
880     }
881
882     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
883     if(NS_FAILED(nsres)) {
884         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
885         return E_FAIL;
886     }
887
888     nsAString_Init(&html_str, NULL);
889     nsres = nsIDOMNSHTMLElement_GetInnerHTML(nselem, &html_str);
890     if(NS_SUCCEEDED(nsres)) {
891         const PRUnichar *html;
892
893         nsAString_GetData(&html_str, &html);
894         *p = *html ? SysAllocString(html) : NULL;
895     }else {
896         FIXME("SetInnerHtml failed %08x\n", nsres);
897         *p = NULL;
898     }
899
900     nsAString_Finish(&html_str);
901     return S_OK;
902 }
903
904 static HRESULT WINAPI HTMLElement_put_innerText(IHTMLElement *iface, BSTR v)
905 {
906     HTMLElement *This = HTMLELEM_THIS(iface);
907     nsIDOMNode *nschild, *tmp;
908     nsIDOMText *text_node;
909     nsAString text_str;
910     nsresult nsres;
911
912     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
913
914     while(1) {
915         nsres = nsIDOMHTMLElement_GetLastChild(This->nselem, &nschild);
916         if(NS_FAILED(nsres)) {
917             ERR("GetLastChild failed: %08x\n", nsres);
918             return E_FAIL;
919         }
920         if(!nschild)
921             break;
922
923         nsres = nsIDOMHTMLElement_RemoveChild(This->nselem, nschild, &tmp);
924         nsIDOMNode_Release(nschild);
925         if(NS_FAILED(nsres)) {
926             ERR("RemoveChild failed: %08x\n", nsres);
927             return E_FAIL;
928         }
929         nsIDOMNode_Release(tmp);
930     }
931
932     nsAString_InitDepend(&text_str, v);
933     nsres = nsIDOMHTMLDocument_CreateTextNode(This->node.doc->nsdoc, &text_str, &text_node);
934     nsAString_Finish(&text_str);
935     if(NS_FAILED(nsres)) {
936         ERR("CreateTextNode failed: %08x\n", nsres);
937         return E_FAIL;
938     }
939
940     nsres = nsIDOMHTMLElement_AppendChild(This->nselem, (nsIDOMNode*)text_node, &tmp);
941     if(NS_FAILED(nsres)) {
942         ERR("AppendChild failed: %08x\n", nsres);
943         return E_FAIL;
944     }
945
946     nsIDOMNode_Release(tmp);
947     return S_OK;
948 }
949
950 static HRESULT WINAPI HTMLElement_get_innerText(IHTMLElement *iface, BSTR *p)
951 {
952     HTMLElement *This = HTMLELEM_THIS(iface);
953
954     TRACE("(%p)->(%p)\n", This, p);
955
956     return get_node_text(&This->node, p);
957 }
958
959 static HRESULT WINAPI HTMLElement_put_outerHTML(IHTMLElement *iface, BSTR v)
960 {
961     HTMLElement *This = HTMLELEM_THIS(iface);
962     nsIDOMDocumentFragment *nsfragment;
963     nsIDOMDocumentRange *nsdocrange;
964     nsIDOMNSRange *nsrange;
965     nsIDOMNode *nsparent;
966     nsIDOMRange *range;
967     nsAString html_str;
968     nsresult nsres;
969     HRESULT hres = S_OK;
970
971     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
972
973     nsres = nsIDOMHTMLDocument_QueryInterface(This->node.doc->nsdoc, &IID_nsIDOMDocumentRange, (void**)&nsdocrange);
974     if(NS_FAILED(nsres))
975         return E_FAIL;
976
977     nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &range);
978     nsIDOMDocumentRange_Release(nsdocrange);
979     if(NS_FAILED(nsres)) {
980         ERR("CreateRange failed: %08x\n", nsres);
981         return E_FAIL;
982     }
983
984     nsres = nsIDOMRange_QueryInterface(range, &IID_nsIDOMNSRange, (void**)&nsrange);
985     nsIDOMRange_Release(range);
986     if(NS_FAILED(nsres)) {
987         ERR("Could not get nsIDOMNSRange: %08x\n", nsres);
988         return E_FAIL;
989     }
990
991     nsAString_InitDepend(&html_str, v);
992     nsIDOMNSRange_CreateContextualFragment(nsrange, &html_str, &nsfragment);
993     nsIDOMNSRange_Release(nsrange);
994     nsAString_Finish(&html_str);
995     if(NS_FAILED(nsres)) {
996         ERR("CreateContextualFragment failed: %08x\n", nsres);
997         return E_FAIL;
998     }
999
1000     nsres = nsIDOMNode_GetParentNode(This->node.nsnode, &nsparent);
1001     if(NS_SUCCEEDED(nsres) && nsparent) {
1002         nsIDOMNode *nstmp;
1003
1004         nsres = nsIDOMNode_ReplaceChild(nsparent, (nsIDOMNode*)nsfragment, This->node.nsnode, &nstmp);
1005         nsIDOMNode_Release(nsparent);
1006         if(NS_FAILED(nsres)) {
1007             ERR("ReplaceChild failed: %08x\n", nsres);
1008             hres = E_FAIL;
1009         }else if(nstmp) {
1010             nsIDOMNode_Release(nstmp);
1011         }
1012     }else {
1013         ERR("GetParentNode failed: %08x\n", nsres);
1014         hres = E_FAIL;
1015     }
1016
1017     nsIDOMDocumentFragment_Release(nsfragment);
1018     return hres;
1019 }
1020
1021 static HRESULT WINAPI HTMLElement_get_outerHTML(IHTMLElement *iface, BSTR *p)
1022 {
1023     HTMLElement *This = HTMLELEM_THIS(iface);
1024     nsAString html_str;
1025     HRESULT hres;
1026
1027     WARN("(%p)->(%p) semi-stub\n", This, p);
1028
1029     nsAString_Init(&html_str, NULL);
1030     hres = nsnode_to_nsstring(This->node.nsnode, &html_str);
1031     if(SUCCEEDED(hres)) {
1032         const PRUnichar *html;
1033
1034         nsAString_GetData(&html_str, &html);
1035         *p = SysAllocString(html);
1036         if(!*p)
1037             hres = E_OUTOFMEMORY;
1038     }
1039
1040     nsAString_Finish(&html_str);
1041
1042     TRACE("ret %s\n", debugstr_w(*p));
1043     return S_OK;
1044 }
1045
1046 static HRESULT WINAPI HTMLElement_put_outerText(IHTMLElement *iface, BSTR v)
1047 {
1048     HTMLElement *This = HTMLELEM_THIS(iface);
1049     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
1050     return E_NOTIMPL;
1051 }
1052
1053 static HRESULT WINAPI HTMLElement_get_outerText(IHTMLElement *iface, BSTR *p)
1054 {
1055     HTMLElement *This = HTMLELEM_THIS(iface);
1056     FIXME("(%p)->(%p)\n", This, p);
1057     return E_NOTIMPL;
1058 }
1059
1060 static HRESULT HTMLElement_InsertAdjacentNode(HTMLElement *This, BSTR where, nsIDOMNode *nsnode)
1061 {
1062     static const WCHAR wszBeforeBegin[] = {'b','e','f','o','r','e','B','e','g','i','n',0};
1063     static const WCHAR wszAfterBegin[] = {'a','f','t','e','r','B','e','g','i','n',0};
1064     static const WCHAR wszBeforeEnd[] = {'b','e','f','o','r','e','E','n','d',0};
1065     static const WCHAR wszAfterEnd[] = {'a','f','t','e','r','E','n','d',0};
1066     nsresult nsres;
1067
1068     if (!strcmpiW(where, wszBeforeBegin))
1069     {
1070         nsIDOMNode *unused;
1071         nsIDOMNode *parent;
1072         nsres = nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1073         if (!parent) return E_INVALIDARG;
1074         nsres = nsIDOMNode_InsertBefore(parent, nsnode, This->node.nsnode, &unused);
1075         if (unused) nsIDOMNode_Release(unused);
1076         nsIDOMNode_Release(parent);
1077     }
1078     else if (!strcmpiW(where, wszAfterBegin))
1079     {
1080         nsIDOMNode *unused;
1081         nsIDOMNode *first_child;
1082         nsIDOMNode_GetFirstChild(This->node.nsnode, &first_child);
1083         nsres = nsIDOMNode_InsertBefore(This->node.nsnode, nsnode, first_child, &unused);
1084         if (unused) nsIDOMNode_Release(unused);
1085         if (first_child) nsIDOMNode_Release(first_child);
1086     }
1087     else if (!strcmpiW(where, wszBeforeEnd))
1088     {
1089         nsIDOMNode *unused;
1090         nsres = nsIDOMNode_AppendChild(This->node.nsnode, nsnode, &unused);
1091         if (unused) nsIDOMNode_Release(unused);
1092     }
1093     else if (!strcmpiW(where, wszAfterEnd))
1094     {
1095         nsIDOMNode *unused;
1096         nsIDOMNode *next_sibling;
1097         nsIDOMNode *parent;
1098         nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1099         if (!parent) return E_INVALIDARG;
1100
1101         nsIDOMNode_GetNextSibling(This->node.nsnode, &next_sibling);
1102         if (next_sibling)
1103         {
1104             nsres = nsIDOMNode_InsertBefore(parent, nsnode, next_sibling, &unused);
1105             nsIDOMNode_Release(next_sibling);
1106         }
1107         else
1108             nsres = nsIDOMNode_AppendChild(parent, nsnode, &unused);
1109         nsIDOMNode_Release(parent);
1110         if (unused) nsIDOMNode_Release(unused);
1111     }
1112     else
1113     {
1114         ERR("invalid where: %s\n", debugstr_w(where));
1115         return E_INVALIDARG;
1116     }
1117
1118     if (NS_FAILED(nsres))
1119         return E_FAIL;
1120     else
1121         return S_OK;
1122 }
1123
1124 static HRESULT WINAPI HTMLElement_insertAdjacentHTML(IHTMLElement *iface, BSTR where,
1125                                                      BSTR html)
1126 {
1127     HTMLElement *This = HTMLELEM_THIS(iface);
1128     nsIDOMDocumentRange *nsdocrange;
1129     nsIDOMRange *range;
1130     nsIDOMNSRange *nsrange;
1131     nsIDOMNode *nsnode;
1132     nsAString ns_html;
1133     nsresult nsres;
1134     HRESULT hr;
1135
1136     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(html));
1137
1138     if(!This->node.doc->nsdoc) {
1139         WARN("NULL nsdoc\n");
1140         return E_UNEXPECTED;
1141     }
1142
1143     nsres = nsIDOMDocument_QueryInterface(This->node.doc->nsdoc, &IID_nsIDOMDocumentRange, (void **)&nsdocrange);
1144     if(NS_FAILED(nsres))
1145     {
1146         ERR("getting nsIDOMDocumentRange failed: %08x\n", nsres);
1147         return E_FAIL;
1148     }
1149     nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &range);
1150     nsIDOMDocumentRange_Release(nsdocrange);
1151     if(NS_FAILED(nsres))
1152     {
1153         ERR("CreateRange failed: %08x\n", nsres);
1154         return E_FAIL;
1155     }
1156
1157     nsIDOMRange_SetStartBefore(range, This->node.nsnode);
1158
1159     nsIDOMRange_QueryInterface(range, &IID_nsIDOMNSRange, (void **)&nsrange);
1160     nsIDOMRange_Release(range);
1161     if(NS_FAILED(nsres))
1162     {
1163         ERR("getting nsIDOMNSRange failed: %08x\n", nsres);
1164         return E_FAIL;
1165     }
1166
1167     nsAString_InitDepend(&ns_html, html);
1168
1169     nsres = nsIDOMNSRange_CreateContextualFragment(nsrange, &ns_html, (nsIDOMDocumentFragment **)&nsnode);
1170     nsIDOMNSRange_Release(nsrange);
1171     nsAString_Finish(&ns_html);
1172
1173     if(NS_FAILED(nsres) || !nsnode)
1174     {
1175         ERR("CreateTextNode failed: %08x\n", nsres);
1176         return E_FAIL;
1177     }
1178
1179     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
1180     nsIDOMNode_Release(nsnode);
1181
1182     return hr;
1183 }
1184
1185 static HRESULT WINAPI HTMLElement_insertAdjacentText(IHTMLElement *iface, BSTR where,
1186                                                      BSTR text)
1187 {
1188     HTMLElement *This = HTMLELEM_THIS(iface);
1189     nsIDOMNode *nsnode;
1190     nsAString ns_text;
1191     nsresult nsres;
1192     HRESULT hr;
1193
1194     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(text));
1195
1196     if(!This->node.doc->nsdoc) {
1197         WARN("NULL nsdoc\n");
1198         return E_UNEXPECTED;
1199     }
1200
1201
1202     nsAString_InitDepend(&ns_text, text);
1203     nsres = nsIDOMDocument_CreateTextNode(This->node.doc->nsdoc, &ns_text, (nsIDOMText **)&nsnode);
1204     nsAString_Finish(&ns_text);
1205
1206     if(NS_FAILED(nsres) || !nsnode)
1207     {
1208         ERR("CreateTextNode failed: %08x\n", nsres);
1209         return E_FAIL;
1210     }
1211
1212     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
1213     nsIDOMNode_Release(nsnode);
1214
1215     return hr;
1216 }
1217
1218 static HRESULT WINAPI HTMLElement_get_parentTextEdit(IHTMLElement *iface, IHTMLElement **p)
1219 {
1220     HTMLElement *This = HTMLELEM_THIS(iface);
1221     FIXME("(%p)->(%p)\n", This, p);
1222     return E_NOTIMPL;
1223 }
1224
1225 static HRESULT WINAPI HTMLElement_get_isTextEdit(IHTMLElement *iface, VARIANT_BOOL *p)
1226 {
1227     HTMLElement *This = HTMLELEM_THIS(iface);
1228     FIXME("(%p)->(%p)\n", This, p);
1229     return E_NOTIMPL;
1230 }
1231
1232 static HRESULT WINAPI HTMLElement_click(IHTMLElement *iface)
1233 {
1234     HTMLElement *This = HTMLELEM_THIS(iface);
1235
1236     TRACE("(%p)\n", This);
1237
1238     return call_event(&This->node, EVENTID_CLICK);
1239 }
1240
1241 static HRESULT WINAPI HTMLElement_get_filters(IHTMLElement *iface,
1242                                               IHTMLFiltersCollection **p)
1243 {
1244     HTMLElement *This = HTMLELEM_THIS(iface);
1245     TRACE("(%p)->(%p)\n", This, p);
1246
1247     if(!p)
1248         return E_POINTER;
1249
1250     *p = HTMLFiltersCollection_Create();
1251
1252     return S_OK;
1253 }
1254
1255 static HRESULT WINAPI HTMLElement_put_ondragstart(IHTMLElement *iface, VARIANT v)
1256 {
1257     HTMLElement *This = HTMLELEM_THIS(iface);
1258     FIXME("(%p)->()\n", This);
1259     return E_NOTIMPL;
1260 }
1261
1262 static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *p)
1263 {
1264     HTMLElement *This = HTMLELEM_THIS(iface);
1265     FIXME("(%p)->(%p)\n", This, p);
1266     return E_NOTIMPL;
1267 }
1268
1269 static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
1270 {
1271     HTMLElement *This = HTMLELEM_THIS(iface);
1272     FIXME("(%p)->(%p)\n", This, String);
1273     return E_NOTIMPL;
1274 }
1275
1276 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
1277 {
1278     HTMLElement *This = HTMLELEM_THIS(iface);
1279     FIXME("(%p)->()\n", This);
1280     return E_NOTIMPL;
1281 }
1282
1283 static HRESULT WINAPI HTMLElement_get_onbeforeupdate(IHTMLElement *iface, VARIANT *p)
1284 {
1285     HTMLElement *This = HTMLELEM_THIS(iface);
1286     FIXME("(%p)->(%p)\n", This, p);
1287     return E_NOTIMPL;
1288 }
1289
1290 static HRESULT WINAPI HTMLElement_put_onafterupdate(IHTMLElement *iface, VARIANT v)
1291 {
1292     HTMLElement *This = HTMLELEM_THIS(iface);
1293     FIXME("(%p)->()\n", This);
1294     return E_NOTIMPL;
1295 }
1296
1297 static HRESULT WINAPI HTMLElement_get_onafterupdate(IHTMLElement *iface, VARIANT *p)
1298 {
1299     HTMLElement *This = HTMLELEM_THIS(iface);
1300     FIXME("(%p)->(%p)\n", This, p);
1301     return E_NOTIMPL;
1302 }
1303
1304 static HRESULT WINAPI HTMLElement_put_onerrorupdate(IHTMLElement *iface, VARIANT v)
1305 {
1306     HTMLElement *This = HTMLELEM_THIS(iface);
1307     FIXME("(%p)->()\n", This);
1308     return E_NOTIMPL;
1309 }
1310
1311 static HRESULT WINAPI HTMLElement_get_onerrorupdate(IHTMLElement *iface, VARIANT *p)
1312 {
1313     HTMLElement *This = HTMLELEM_THIS(iface);
1314     FIXME("(%p)->(%p)\n", This, p);
1315     return E_NOTIMPL;
1316 }
1317
1318 static HRESULT WINAPI HTMLElement_put_onrowexit(IHTMLElement *iface, VARIANT v)
1319 {
1320     HTMLElement *This = HTMLELEM_THIS(iface);
1321     FIXME("(%p)->()\n", This);
1322     return E_NOTIMPL;
1323 }
1324
1325 static HRESULT WINAPI HTMLElement_get_onrowexit(IHTMLElement *iface, VARIANT *p)
1326 {
1327     HTMLElement *This = HTMLELEM_THIS(iface);
1328     FIXME("(%p)->(%p)\n", This, p);
1329     return E_NOTIMPL;
1330 }
1331
1332 static HRESULT WINAPI HTMLElement_put_onrowenter(IHTMLElement *iface, VARIANT v)
1333 {
1334     HTMLElement *This = HTMLELEM_THIS(iface);
1335     FIXME("(%p)->()\n", This);
1336     return E_NOTIMPL;
1337 }
1338
1339 static HRESULT WINAPI HTMLElement_get_onrowenter(IHTMLElement *iface, VARIANT *p)
1340 {
1341     HTMLElement *This = HTMLELEM_THIS(iface);
1342     FIXME("(%p)->(%p)\n", This, p);
1343     return E_NOTIMPL;
1344 }
1345
1346 static HRESULT WINAPI HTMLElement_put_ondatasetchanged(IHTMLElement *iface, VARIANT v)
1347 {
1348     HTMLElement *This = HTMLELEM_THIS(iface);
1349     FIXME("(%p)->()\n", This);
1350     return E_NOTIMPL;
1351 }
1352
1353 static HRESULT WINAPI HTMLElement_get_ondatasetchanged(IHTMLElement *iface, VARIANT *p)
1354 {
1355     HTMLElement *This = HTMLELEM_THIS(iface);
1356     FIXME("(%p)->(%p)\n", This, p);
1357     return E_NOTIMPL;
1358 }
1359
1360 static HRESULT WINAPI HTMLElement_put_ondataavailable(IHTMLElement *iface, VARIANT v)
1361 {
1362     HTMLElement *This = HTMLELEM_THIS(iface);
1363     FIXME("(%p)->()\n", This);
1364     return E_NOTIMPL;
1365 }
1366
1367 static HRESULT WINAPI HTMLElement_get_ondataavailable(IHTMLElement *iface, VARIANT *p)
1368 {
1369     HTMLElement *This = HTMLELEM_THIS(iface);
1370     FIXME("(%p)->(%p)\n", This, p);
1371     return E_NOTIMPL;
1372 }
1373
1374 static HRESULT WINAPI HTMLElement_put_ondatasetcomplete(IHTMLElement *iface, VARIANT v)
1375 {
1376     HTMLElement *This = HTMLELEM_THIS(iface);
1377     FIXME("(%p)->()\n", This);
1378     return E_NOTIMPL;
1379 }
1380
1381 static HRESULT WINAPI HTMLElement_get_ondatasetcomplete(IHTMLElement *iface, VARIANT *p)
1382 {
1383     HTMLElement *This = HTMLELEM_THIS(iface);
1384     FIXME("(%p)->(%p)\n", This, p);
1385     return E_NOTIMPL;
1386 }
1387
1388 static HRESULT WINAPI HTMLElement_put_onfilterchange(IHTMLElement *iface, VARIANT v)
1389 {
1390     HTMLElement *This = HTMLELEM_THIS(iface);
1391     FIXME("(%p)->()\n", This);
1392     return E_NOTIMPL;
1393 }
1394
1395 static HRESULT WINAPI HTMLElement_get_onfilterchange(IHTMLElement *iface, VARIANT *p)
1396 {
1397     HTMLElement *This = HTMLELEM_THIS(iface);
1398     FIXME("(%p)->(%p)\n", This, p);
1399     return E_NOTIMPL;
1400 }
1401
1402 static HRESULT WINAPI HTMLElement_get_children(IHTMLElement *iface, IDispatch **p)
1403 {
1404     HTMLElement *This = HTMLELEM_THIS(iface);
1405     nsIDOMNodeList *nsnode_list;
1406     nsresult nsres;
1407
1408     TRACE("(%p)->(%p)\n", This, p);
1409
1410     nsres = nsIDOMNode_GetChildNodes(This->node.nsnode, &nsnode_list);
1411     if(NS_FAILED(nsres)) {
1412         ERR("GetChildNodes failed: %08x\n", nsres);
1413         return E_FAIL;
1414     }
1415
1416     *p = (IDispatch*)create_collection_from_nodelist(This->node.doc, (IUnknown*)HTMLELEM(This), nsnode_list);
1417
1418     nsIDOMNodeList_Release(nsnode_list);
1419     return S_OK;
1420 }
1421
1422 static HRESULT WINAPI HTMLElement_get_all(IHTMLElement *iface, IDispatch **p)
1423 {
1424     HTMLElement *This = HTMLELEM_THIS(iface);
1425
1426     TRACE("(%p)->(%p)\n", This, p);
1427
1428     *p = (IDispatch*)create_all_collection(&This->node, FALSE);
1429     return S_OK;
1430 }
1431
1432 static HRESULT HTMLElement_get_dispid(IUnknown *iface, BSTR name,
1433         DWORD grfdex, DISPID *pid)
1434 {
1435     HTMLElement *This = HTMLELEM_THIS(iface);
1436
1437     if(This->node.vtbl->get_dispid)
1438         return This->node.vtbl->get_dispid(&This->node, name, grfdex, pid);
1439
1440     return DISP_E_UNKNOWNNAME;
1441 }
1442
1443 static HRESULT HTMLElement_invoke(IUnknown *iface, DISPID id, LCID lcid,
1444         WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei,
1445         IServiceProvider *caller)
1446 {
1447     HTMLElement *This = HTMLELEM_THIS(iface);
1448
1449     if(This->node.vtbl->invoke)
1450         return This->node.vtbl->invoke(&This->node, id, lcid, flags,
1451                 params, res, ei, caller);
1452
1453     ERR("(%p): element has no invoke method\n", This);
1454     return E_NOTIMPL;
1455 }
1456
1457 #undef HTMLELEM_THIS
1458
1459 static const IHTMLElementVtbl HTMLElementVtbl = {
1460     HTMLElement_QueryInterface,
1461     HTMLElement_AddRef,
1462     HTMLElement_Release,
1463     HTMLElement_GetTypeInfoCount,
1464     HTMLElement_GetTypeInfo,
1465     HTMLElement_GetIDsOfNames,
1466     HTMLElement_Invoke,
1467     HTMLElement_setAttribute,
1468     HTMLElement_getAttribute,
1469     HTMLElement_removeAttribute,
1470     HTMLElement_put_className,
1471     HTMLElement_get_className,
1472     HTMLElement_put_id,
1473     HTMLElement_get_id,
1474     HTMLElement_get_tagName,
1475     HTMLElement_get_parentElement,
1476     HTMLElement_get_style,
1477     HTMLElement_put_onhelp,
1478     HTMLElement_get_onhelp,
1479     HTMLElement_put_onclick,
1480     HTMLElement_get_onclick,
1481     HTMLElement_put_ondblclick,
1482     HTMLElement_get_ondblclick,
1483     HTMLElement_put_onkeydown,
1484     HTMLElement_get_onkeydown,
1485     HTMLElement_put_onkeyup,
1486     HTMLElement_get_onkeyup,
1487     HTMLElement_put_onkeypress,
1488     HTMLElement_get_onkeypress,
1489     HTMLElement_put_onmouseout,
1490     HTMLElement_get_onmouseout,
1491     HTMLElement_put_onmouseover,
1492     HTMLElement_get_onmouseover,
1493     HTMLElement_put_onmousemove,
1494     HTMLElement_get_onmousemove,
1495     HTMLElement_put_onmousedown,
1496     HTMLElement_get_onmousedown,
1497     HTMLElement_put_onmouseup,
1498     HTMLElement_get_onmouseup,
1499     HTMLElement_get_document,
1500     HTMLElement_put_title,
1501     HTMLElement_get_title,
1502     HTMLElement_put_language,
1503     HTMLElement_get_language,
1504     HTMLElement_put_onselectstart,
1505     HTMLElement_get_onselectstart,
1506     HTMLElement_scrollIntoView,
1507     HTMLElement_contains,
1508     HTMLElement_get_sourceIndex,
1509     HTMLElement_get_recordNumber,
1510     HTMLElement_put_lang,
1511     HTMLElement_get_lang,
1512     HTMLElement_get_offsetLeft,
1513     HTMLElement_get_offsetTop,
1514     HTMLElement_get_offsetWidth,
1515     HTMLElement_get_offsetHeight,
1516     HTMLElement_get_offsetParent,
1517     HTMLElement_put_innerHTML,
1518     HTMLElement_get_innerHTML,
1519     HTMLElement_put_innerText,
1520     HTMLElement_get_innerText,
1521     HTMLElement_put_outerHTML,
1522     HTMLElement_get_outerHTML,
1523     HTMLElement_put_outerText,
1524     HTMLElement_get_outerText,
1525     HTMLElement_insertAdjacentHTML,
1526     HTMLElement_insertAdjacentText,
1527     HTMLElement_get_parentTextEdit,
1528     HTMLElement_get_isTextEdit,
1529     HTMLElement_click,
1530     HTMLElement_get_filters,
1531     HTMLElement_put_ondragstart,
1532     HTMLElement_get_ondragstart,
1533     HTMLElement_toString,
1534     HTMLElement_put_onbeforeupdate,
1535     HTMLElement_get_onbeforeupdate,
1536     HTMLElement_put_onafterupdate,
1537     HTMLElement_get_onafterupdate,
1538     HTMLElement_put_onerrorupdate,
1539     HTMLElement_get_onerrorupdate,
1540     HTMLElement_put_onrowexit,
1541     HTMLElement_get_onrowexit,
1542     HTMLElement_put_onrowenter,
1543     HTMLElement_get_onrowenter,
1544     HTMLElement_put_ondatasetchanged,
1545     HTMLElement_get_ondatasetchanged,
1546     HTMLElement_put_ondataavailable,
1547     HTMLElement_get_ondataavailable,
1548     HTMLElement_put_ondatasetcomplete,
1549     HTMLElement_get_ondatasetcomplete,
1550     HTMLElement_put_onfilterchange,
1551     HTMLElement_get_onfilterchange,
1552     HTMLElement_get_children,
1553     HTMLElement_get_all
1554 };
1555
1556 HRESULT HTMLElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
1557 {
1558     HTMLElement *This = HTMLELEM_NODE_THIS(iface);
1559
1560     *ppv =  NULL;
1561
1562     if(IsEqualGUID(&IID_IUnknown, riid)) {
1563         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1564         *ppv = HTMLELEM(This);
1565     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1566         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1567         *ppv = HTMLELEM(This);
1568     }else if(IsEqualGUID(&IID_IHTMLElement, riid)) {
1569         TRACE("(%p)->(IID_IHTMLElement %p)\n", This, ppv);
1570         *ppv = HTMLELEM(This);
1571     }else if(IsEqualGUID(&IID_IHTMLElement2, riid)) {
1572         TRACE("(%p)->(IID_IHTMLElement2 %p)\n", This, ppv);
1573         *ppv = HTMLELEM2(This);
1574     }else if(IsEqualGUID(&IID_IHTMLElement3, riid)) {
1575         TRACE("(%p)->(IID_IHTMLElement3 %p)\n", This, ppv);
1576         *ppv = HTMLELEM3(This);
1577     }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) {
1578         TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv);
1579         *ppv = CONPTCONT(&This->cp_container);
1580     }
1581
1582     if(*ppv) {
1583         IHTMLElement_AddRef(HTMLELEM(This));
1584         return S_OK;
1585     }
1586
1587     return HTMLDOMNode_QI(&This->node, riid, ppv);
1588 }
1589
1590 void HTMLElement_destructor(HTMLDOMNode *iface)
1591 {
1592     HTMLElement *This = HTMLELEM_NODE_THIS(iface);
1593
1594     ConnectionPointContainer_Destroy(&This->cp_container);
1595
1596     if(This->nselem)
1597         nsIDOMHTMLElement_Release(This->nselem);
1598
1599     HTMLDOMNode_destructor(&This->node);
1600 }
1601
1602 static const NodeImplVtbl HTMLElementImplVtbl = {
1603     HTMLElement_QI,
1604     HTMLElement_destructor
1605 };
1606
1607 static const tid_t HTMLElement_iface_tids[] = {
1608     HTMLELEMENT_TIDS,
1609     0
1610 };
1611
1612 static dispex_static_data_vtbl_t HTMLElement_dispex_vtbl = {
1613     NULL,
1614     HTMLElement_get_dispid,
1615     HTMLElement_invoke
1616 };
1617
1618 static dispex_static_data_t HTMLElement_dispex = {
1619     &HTMLElement_dispex_vtbl,
1620     DispHTMLUnknownElement_tid,
1621     NULL,
1622     HTMLElement_iface_tids
1623 };
1624
1625 void HTMLElement_Init(HTMLElement *This, HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, dispex_static_data_t *dispex_data)
1626 {
1627     This->lpHTMLElementVtbl = &HTMLElementVtbl;
1628
1629     HTMLElement2_Init(This);
1630     HTMLElement3_Init(This);
1631
1632     if(dispex_data && !dispex_data->vtbl)
1633         dispex_data->vtbl = &HTMLElement_dispex_vtbl;
1634     init_dispex(&This->node.dispex, (IUnknown*)HTMLELEM(This), dispex_data ? dispex_data : &HTMLElement_dispex);
1635
1636     if(nselem)
1637         nsIDOMHTMLElement_AddRef(nselem);
1638     This->nselem = nselem;
1639
1640     HTMLDOMNode_Init(doc, &This->node, (nsIDOMNode*)nselem);
1641
1642     ConnectionPointContainer_Init(&This->cp_container, (IUnknown*)HTMLELEM(This));
1643 }
1644
1645 HTMLElement *HTMLElement_Create(HTMLDocumentNode *doc, nsIDOMNode *nsnode, BOOL use_generic)
1646 {
1647     nsIDOMHTMLElement *nselem;
1648     HTMLElement *ret = NULL;
1649     nsAString class_name_str;
1650     const PRUnichar *class_name;
1651     nsresult nsres;
1652
1653     static const WCHAR wszA[]        = {'A',0};
1654     static const WCHAR wszBODY[]     = {'B','O','D','Y',0};
1655     static const WCHAR wszFORM[]     = {'F','O','R','M',0};
1656     static const WCHAR wszFRAME[]    = {'F','R','A','M','E',0};
1657     static const WCHAR wszIFRAME[]   = {'I','F','R','A','M','E',0};
1658     static const WCHAR wszIMG[]      = {'I','M','G',0};
1659     static const WCHAR wszINPUT[]    = {'I','N','P','U','T',0};
1660     static const WCHAR wszOPTION[]   = {'O','P','T','I','O','N',0};
1661     static const WCHAR wszSCRIPT[]   = {'S','C','R','I','P','T',0};
1662     static const WCHAR wszSELECT[]   = {'S','E','L','E','C','T',0};
1663     static const WCHAR wszTABLE[]    = {'T','A','B','L','E',0};
1664     static const WCHAR wszTR[]       = {'T','R',0};
1665     static const WCHAR wszTEXTAREA[] = {'T','E','X','T','A','R','E','A',0};
1666
1667     nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMHTMLElement, (void**)&nselem);
1668     if(NS_FAILED(nsres))
1669         return NULL;
1670
1671     nsAString_Init(&class_name_str, NULL);
1672     nsIDOMHTMLElement_GetTagName(nselem, &class_name_str);
1673
1674     nsAString_GetData(&class_name_str, &class_name);
1675
1676     if(!strcmpW(class_name, wszA))
1677         ret = HTMLAnchorElement_Create(doc, nselem);
1678     else if(!strcmpW(class_name, wszBODY))
1679         ret = HTMLBodyElement_Create(doc, nselem);
1680     else if(!strcmpW(class_name, wszFORM))
1681         ret = HTMLFormElement_Create(doc, nselem);
1682     else if(!strcmpW(class_name, wszFRAME))
1683         ret = HTMLFrameElement_Create(doc, nselem);
1684     else if(!strcmpW(class_name, wszIFRAME))
1685         ret = HTMLIFrame_Create(doc, nselem);
1686     else if(!strcmpW(class_name, wszIMG))
1687         ret = HTMLImgElement_Create(doc, nselem);
1688     else if(!strcmpW(class_name, wszINPUT))
1689         ret = HTMLInputElement_Create(doc, nselem);
1690     else if(!strcmpW(class_name, wszOPTION))
1691         ret = HTMLOptionElement_Create(doc, nselem);
1692     else if(!strcmpW(class_name, wszSCRIPT))
1693         ret = HTMLScriptElement_Create(doc, nselem);
1694     else if(!strcmpW(class_name, wszSELECT))
1695         ret = HTMLSelectElement_Create(doc, nselem);
1696     else if(!strcmpW(class_name, wszTABLE))
1697         ret = HTMLTable_Create(doc, nselem);
1698     else if(!strcmpW(class_name, wszTR))
1699         ret = HTMLTableRow_Create(doc, nselem);
1700     else if(!strcmpW(class_name, wszTEXTAREA))
1701         ret = HTMLTextAreaElement_Create(doc, nselem);
1702     else if(use_generic)
1703         ret = HTMLGenericElement_Create(doc, nselem);
1704
1705     if(!ret) {
1706         ret = heap_alloc_zero(sizeof(HTMLElement));
1707         HTMLElement_Init(ret, doc, nselem, &HTMLElement_dispex);
1708         ret->node.vtbl = &HTMLElementImplVtbl;
1709     }
1710
1711     TRACE("%s ret %p\n", debugstr_w(class_name), ret);
1712
1713     nsIDOMElement_Release(nselem);
1714     nsAString_Finish(&class_name_str);
1715
1716     return ret;
1717 }
1718
1719 /* interaface IHTMLFiltersCollection */
1720 static HRESULT WINAPI HTMLFiltersCollection_QueryInterface(IHTMLFiltersCollection *iface, REFIID riid, void **ppv)
1721 {
1722     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1723
1724     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppv );
1725
1726     if(IsEqualGUID(&IID_IUnknown, riid)) {
1727         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1728         *ppv = HTMLFILTERSCOLLECTION(This);
1729     }else if(IsEqualGUID(&IID_IHTMLFiltersCollection, riid)) {
1730         TRACE("(%p)->(IID_IHTMLFiltersCollection %p)\n", This, ppv);
1731         *ppv = HTMLFILTERSCOLLECTION(This);
1732     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1733         return *ppv ? S_OK : E_NOINTERFACE;
1734     }
1735
1736     if(*ppv) {
1737         IUnknown_AddRef((IUnknown*)*ppv);
1738         return S_OK;
1739     }
1740
1741     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1742     return E_NOINTERFACE;
1743 }
1744
1745 static ULONG WINAPI HTMLFiltersCollection_AddRef(IHTMLFiltersCollection *iface)
1746 {
1747     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1748     LONG ref = InterlockedIncrement(&This->ref);
1749
1750     TRACE("(%p) ref=%d\n", This, ref);
1751
1752     return ref;
1753 }
1754
1755 static ULONG WINAPI HTMLFiltersCollection_Release(IHTMLFiltersCollection *iface)
1756 {
1757     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1758     LONG ref = InterlockedDecrement(&This->ref);
1759
1760     TRACE("(%p) ref=%d\n", This, ref);
1761
1762     if(!ref)
1763     {
1764         heap_free(This);
1765     }
1766
1767     return ref;
1768 }
1769
1770 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfoCount(IHTMLFiltersCollection *iface, UINT *pctinfo)
1771 {
1772     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1773     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo);
1774 }
1775
1776 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfo(IHTMLFiltersCollection *iface,
1777                                     UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1778 {
1779     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1780     return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo);
1781 }
1782
1783 static HRESULT WINAPI HTMLFiltersCollection_GetIDsOfNames(IHTMLFiltersCollection *iface,
1784                                     REFIID riid, LPOLESTR *rgszNames, UINT cNames,
1785                                     LCID lcid, DISPID *rgDispId)
1786 {
1787     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1788     return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId);
1789 }
1790
1791 static HRESULT WINAPI HTMLFiltersCollection_Invoke(IHTMLFiltersCollection *iface, DISPID dispIdMember, REFIID riid,
1792                                     LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1793                                     EXCEPINFO *pExcepInfo, UINT *puArgErr)
1794 {
1795     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1796     return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid,
1797             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1798 }
1799
1800 static HRESULT WINAPI HTMLFiltersCollection_get_length(IHTMLFiltersCollection *iface, LONG *p)
1801 {
1802     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1803
1804     FIXME("(%p)->(%p) Always returning 0\n", This, p);
1805
1806         if(!p)
1807                 return E_POINTER;
1808
1809     if(p)
1810         *p = 0;
1811
1812     return S_OK;
1813 }
1814
1815 static HRESULT WINAPI HTMLFiltersCollection_get__newEnum(IHTMLFiltersCollection *iface, IUnknown **p)
1816 {
1817     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1818     FIXME("(%p)->(%p)\n", This, p);
1819     return E_NOTIMPL;
1820 }
1821
1822 static HRESULT WINAPI HTMLFiltersCollection_item(IHTMLFiltersCollection *iface, VARIANT *pvarIndex, VARIANT *pvarResult)
1823 {
1824     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1825     FIXME("(%p)->(%p, %p)\n", This, pvarIndex, pvarResult);
1826     return E_NOTIMPL;
1827 }
1828
1829 static const IHTMLFiltersCollectionVtbl HTMLFiltersCollectionVtbl = {
1830     HTMLFiltersCollection_QueryInterface,
1831     HTMLFiltersCollection_AddRef,
1832     HTMLFiltersCollection_Release,
1833     HTMLFiltersCollection_GetTypeInfoCount,
1834     HTMLFiltersCollection_GetTypeInfo,
1835     HTMLFiltersCollection_GetIDsOfNames,
1836     HTMLFiltersCollection_Invoke,
1837     HTMLFiltersCollection_get_length,
1838     HTMLFiltersCollection_get__newEnum,
1839     HTMLFiltersCollection_item
1840 };
1841
1842 static HRESULT HTMLFiltersCollection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
1843 {
1844     WCHAR *ptr;
1845     int idx = 0;
1846
1847     for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
1848         idx = idx*10 + (*ptr-'0');
1849     if(*ptr)
1850         return DISP_E_UNKNOWNNAME;
1851
1852     *dispid = MSHTML_DISPID_CUSTOM_MIN + idx;
1853     TRACE("ret %x\n", *dispid);
1854     return S_OK;
1855 }
1856
1857 static HRESULT HTMLFiltersCollection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
1858         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
1859 {
1860     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1861
1862     TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei);
1863
1864     V_VT(res) = VT_DISPATCH;
1865     V_DISPATCH(res) = NULL;
1866
1867     FIXME("always returning NULL\n");
1868
1869     return S_OK;
1870 }
1871
1872 static const dispex_static_data_vtbl_t HTMLFiltersCollection_dispex_vtbl = {
1873     NULL,
1874     HTMLFiltersCollection_get_dispid,
1875     HTMLFiltersCollection_invoke
1876 };
1877
1878 static const tid_t HTMLFiltersCollection_iface_tids[] = {
1879     IHTMLFiltersCollection_tid,
1880     0
1881 };
1882 static dispex_static_data_t HTMLFiltersCollection_dispex = {
1883     &HTMLFiltersCollection_dispex_vtbl,
1884     IHTMLFiltersCollection_tid,
1885     NULL,
1886     HTMLFiltersCollection_iface_tids
1887 };
1888
1889 IHTMLFiltersCollection *HTMLFiltersCollection_Create()
1890 {
1891     HTMLFiltersCollection *ret = heap_alloc(sizeof(HTMLFiltersCollection));
1892
1893     ret->lpHTMLFiltersCollectionVtbl = &HTMLFiltersCollectionVtbl;
1894     ret->ref = 1;
1895
1896     init_dispex(&ret->dispex, (IUnknown*)HTMLFILTERSCOLLECTION(ret),  &HTMLFiltersCollection_dispex);
1897
1898     return HTMLFILTERSCOLLECTION(ret);
1899 }