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