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