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