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