comctl32/imagelist: Use proper color format for merged image lists.
[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 #include <stdarg.h>
20 #include <assert.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 labelW[]    = {'L','A','B','E','L',0};
49 static const WCHAR linkW[]     = {'L','I','N','K',0};
50 static const WCHAR metaW[]     = {'M','E','T','A',0};
51 static const WCHAR objectW[]   = {'O','B','J','E','C','T',0};
52 static const WCHAR optionW[]   = {'O','P','T','I','O','N',0};
53 static const WCHAR scriptW[]   = {'S','C','R','I','P','T',0};
54 static const WCHAR selectW[]   = {'S','E','L','E','C','T',0};
55 static const WCHAR styleW[]    = {'S','T','Y','L','E',0};
56 static const WCHAR tableW[]    = {'T','A','B','L','E',0};
57 static const WCHAR tdW[]       = {'T','D',0};
58 static const WCHAR textareaW[] = {'T','E','X','T','A','R','E','A',0};
59 static const WCHAR title_tagW[]= {'T','I','T','L','E',0};
60 static const WCHAR trW[]       = {'T','R',0};
61
62 typedef struct {
63     const WCHAR *name;
64     HRESULT (*constructor)(HTMLDocumentNode*,nsIDOMHTMLElement*,HTMLElement**);
65 } tag_desc_t;
66
67 static const tag_desc_t tag_descs[] = {
68     {aW,         HTMLAnchorElement_Create},
69     {bodyW,      HTMLBodyElement_Create},
70     {embedW,     HTMLEmbedElement_Create},
71     {formW,      HTMLFormElement_Create},
72     {frameW,     HTMLFrameElement_Create},
73     {headW,      HTMLHeadElement_Create},
74     {iframeW,    HTMLIFrame_Create},
75     {imgW,       HTMLImgElement_Create},
76     {inputW,     HTMLInputElement_Create},
77     {labelW,     HTMLLabelElement_Create},
78     {linkW,      HTMLLinkElement_Create},
79     {metaW,      HTMLMetaElement_Create},
80     {objectW,    HTMLObjectElement_Create},
81     {optionW,    HTMLOptionElement_Create},
82     {scriptW,    HTMLScriptElement_Create},
83     {selectW,    HTMLSelectElement_Create},
84     {styleW,     HTMLStyleElement_Create},
85     {tableW,     HTMLTable_Create},
86     {tdW,        HTMLTableCell_Create},
87     {textareaW,  HTMLTextAreaElement_Create},
88     {title_tagW, HTMLTitleElement_Create},
89     {trW,        HTMLTableRow_Create}
90 };
91
92 static const tag_desc_t *get_tag_desc(const WCHAR *tag_name)
93 {
94     DWORD min=0, max=sizeof(tag_descs)/sizeof(*tag_descs)-1, i;
95     int r;
96
97     while(min <= max) {
98         i = (min+max)/2;
99         r = strcmpW(tag_name, tag_descs[i].name);
100         if(!r)
101             return tag_descs+i;
102
103         if(r < 0)
104             max = i-1;
105         else
106             min = i+1;
107     }
108
109     return NULL;
110 }
111
112 HRESULT replace_node_by_html(nsIDOMHTMLDocument *nsdoc, nsIDOMNode *nsnode, const WCHAR *html)
113 {
114     nsIDOMDocumentFragment *nsfragment;
115     nsIDOMNode *nsparent;
116     nsIDOMRange *range;
117     nsAString html_str;
118     nsresult nsres;
119     HRESULT hres = S_OK;
120
121     nsres = nsIDOMHTMLDocument_CreateRange(nsdoc, &range);
122     if(NS_FAILED(nsres)) {
123         ERR("CreateRange failed: %08x\n", nsres);
124         return E_FAIL;
125     }
126
127     nsAString_InitDepend(&html_str, html);
128     nsIDOMRange_CreateContextualFragment(range, &html_str, &nsfragment);
129     nsIDOMRange_Release(range);
130     nsAString_Finish(&html_str);
131     if(NS_FAILED(nsres)) {
132         ERR("CreateContextualFragment failed: %08x\n", nsres);
133         return E_FAIL;
134     }
135
136     nsres = nsIDOMNode_GetParentNode(nsnode, &nsparent);
137     if(NS_SUCCEEDED(nsres) && nsparent) {
138         nsIDOMNode *nstmp;
139
140         nsres = nsIDOMNode_ReplaceChild(nsparent, (nsIDOMNode*)nsfragment, nsnode, &nstmp);
141         nsIDOMNode_Release(nsparent);
142         if(NS_FAILED(nsres)) {
143             ERR("ReplaceChild failed: %08x\n", nsres);
144             hres = E_FAIL;
145         }else if(nstmp) {
146             nsIDOMNode_Release(nstmp);
147         }
148     }else {
149         ERR("GetParentNode failed: %08x\n", nsres);
150         hres = E_FAIL;
151     }
152
153     nsIDOMDocumentFragment_Release(nsfragment);
154     return hres;
155 }
156
157 typedef struct
158 {
159     DispatchEx dispex;
160     IHTMLFiltersCollection IHTMLFiltersCollection_iface;
161
162     LONG ref;
163 } HTMLFiltersCollection;
164
165 static inline HTMLFiltersCollection *impl_from_IHTMLFiltersCollection(IHTMLFiltersCollection *iface)
166 {
167     return CONTAINING_RECORD(iface, HTMLFiltersCollection, IHTMLFiltersCollection_iface);
168 }
169
170 static IHTMLFiltersCollection *HTMLFiltersCollection_Create(void);
171
172 static inline HTMLElement *impl_from_IHTMLElement(IHTMLElement *iface)
173 {
174     return CONTAINING_RECORD(iface, HTMLElement, IHTMLElement_iface);
175 }
176
177 HRESULT create_nselem(HTMLDocumentNode *doc, const WCHAR *tag, nsIDOMHTMLElement **ret)
178 {
179     nsIDOMElement *nselem;
180     nsAString tag_str;
181     nsresult nsres;
182
183     if(!doc->nsdoc) {
184         WARN("NULL nsdoc\n");
185         return E_UNEXPECTED;
186     }
187
188     nsAString_InitDepend(&tag_str, tag);
189     nsres = nsIDOMHTMLDocument_CreateElement(doc->nsdoc, &tag_str, &nselem);
190     nsAString_Finish(&tag_str);
191     if(NS_FAILED(nsres)) {
192         ERR("CreateElement failed: %08x\n", nsres);
193         return E_FAIL;
194     }
195
196     nsres = nsIDOMElement_QueryInterface(nselem, &IID_nsIDOMHTMLElement, (void**)ret);
197     nsIDOMElement_Release(nselem);
198     if(NS_FAILED(nsres)) {
199         ERR("Could not get nsIDOMHTMLElement iface: %08x\n", nsres);
200         return E_FAIL;
201     }
202
203     return S_OK;
204 }
205
206 HRESULT create_element(HTMLDocumentNode *doc, const WCHAR *tag, HTMLElement **ret)
207 {
208     nsIDOMHTMLElement *nselem;
209     HRESULT hres;
210
211     /* Use owner doc if called on document fragment */
212     if(!doc->nsdoc)
213         doc = doc->node.doc;
214
215     hres = create_nselem(doc, tag, &nselem);
216     if(FAILED(hres))
217         return hres;
218
219     hres = HTMLElement_Create(doc, (nsIDOMNode*)nselem, TRUE, ret);
220     nsIDOMHTMLElement_Release(nselem);
221     return hres;
222 }
223
224 static HRESULT WINAPI HTMLElement_QueryInterface(IHTMLElement *iface,
225                                                  REFIID riid, void **ppv)
226 {
227     HTMLElement *This = impl_from_IHTMLElement(iface);
228
229     return IHTMLDOMNode_QueryInterface(&This->node.IHTMLDOMNode_iface, riid, ppv);
230 }
231
232 static ULONG WINAPI HTMLElement_AddRef(IHTMLElement *iface)
233 {
234     HTMLElement *This = impl_from_IHTMLElement(iface);
235
236     return IHTMLDOMNode_AddRef(&This->node.IHTMLDOMNode_iface);
237 }
238
239 static ULONG WINAPI HTMLElement_Release(IHTMLElement *iface)
240 {
241     HTMLElement *This = impl_from_IHTMLElement(iface);
242
243     return IHTMLDOMNode_Release(&This->node.IHTMLDOMNode_iface);
244 }
245
246 static HRESULT WINAPI HTMLElement_GetTypeInfoCount(IHTMLElement *iface, UINT *pctinfo)
247 {
248     HTMLElement *This = impl_from_IHTMLElement(iface);
249     return IDispatchEx_GetTypeInfoCount(&This->node.dispex.IDispatchEx_iface, pctinfo);
250 }
251
252 static HRESULT WINAPI HTMLElement_GetTypeInfo(IHTMLElement *iface, UINT iTInfo,
253                                               LCID lcid, ITypeInfo **ppTInfo)
254 {
255     HTMLElement *This = impl_from_IHTMLElement(iface);
256     return IDispatchEx_GetTypeInfo(&This->node.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
257 }
258
259 static HRESULT WINAPI HTMLElement_GetIDsOfNames(IHTMLElement *iface, REFIID riid,
260                                                 LPOLESTR *rgszNames, UINT cNames,
261                                                 LCID lcid, DISPID *rgDispId)
262 {
263     HTMLElement *This = impl_from_IHTMLElement(iface);
264     return IDispatchEx_GetIDsOfNames(&This->node.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
265             lcid, rgDispId);
266 }
267
268 static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMember,
269                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
270                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
271 {
272     HTMLElement *This = impl_from_IHTMLElement(iface);
273     return IDispatchEx_Invoke(&This->node.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
274             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
275 }
276
277 static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName,
278                                                VARIANT AttributeValue, LONG lFlags)
279 {
280     HTMLElement *This = impl_from_IHTMLElement(iface);
281     HRESULT hres;
282     DISPID dispid, dispidNamed = DISPID_PROPERTYPUT;
283     DISPPARAMS dispParams;
284     EXCEPINFO excep;
285
286     TRACE("(%p)->(%s %s %08x)\n", This, debugstr_w(strAttributeName), debugstr_variant(&AttributeValue), lFlags);
287
288     hres = IDispatchEx_GetDispID(&This->node.dispex.IDispatchEx_iface, strAttributeName,
289             fdexNameCaseInsensitive | fdexNameEnsure, &dispid);
290     if(FAILED(hres))
291         return hres;
292
293     dispParams.cArgs = 1;
294     dispParams.cNamedArgs = 1;
295     dispParams.rgdispidNamedArgs = &dispidNamed;
296     dispParams.rgvarg = &AttributeValue;
297
298     hres = IDispatchEx_InvokeEx(&This->node.dispex.IDispatchEx_iface, dispid,
299             LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispParams, NULL, &excep, NULL);
300     return hres;
301 }
302
303 static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttributeName,
304                                                LONG lFlags, VARIANT *AttributeValue)
305 {
306     HTMLElement *This = impl_from_IHTMLElement(iface);
307     DISPID dispid;
308     HRESULT hres;
309     DISPPARAMS dispParams = {NULL, NULL, 0, 0};
310     EXCEPINFO excep;
311
312     TRACE("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
313
314     hres = IDispatchEx_GetDispID(&This->node.dispex.IDispatchEx_iface, strAttributeName,
315             fdexNameCaseInsensitive, &dispid);
316     if(hres == DISP_E_UNKNOWNNAME) {
317         V_VT(AttributeValue) = VT_NULL;
318         return S_OK;
319     }
320
321     if(FAILED(hres)) {
322         V_VT(AttributeValue) = VT_NULL;
323         return hres;
324     }
325
326     hres = IDispatchEx_InvokeEx(&This->node.dispex.IDispatchEx_iface, dispid, LOCALE_SYSTEM_DEFAULT,
327             DISPATCH_PROPERTYGET, &dispParams, AttributeValue, &excep, NULL);
328
329     return hres;
330 }
331
332 static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strAttributeName,
333                                                   LONG lFlags, VARIANT_BOOL *pfSuccess)
334 {
335     HTMLElement *This = impl_from_IHTMLElement(iface);
336
337     TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(strAttributeName), lFlags, pfSuccess);
338
339     return remove_prop(&This->node.dispex, strAttributeName, pfSuccess);
340 }
341
342 static HRESULT WINAPI HTMLElement_put_className(IHTMLElement *iface, BSTR v)
343 {
344     HTMLElement *This = impl_from_IHTMLElement(iface);
345     nsAString classname_str;
346     nsresult nsres;
347
348     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
349
350     if(!This->nselem) {
351         FIXME("NULL nselem\n");
352         return E_NOTIMPL;
353     }
354
355     nsAString_InitDepend(&classname_str, v);
356     nsres = nsIDOMHTMLElement_SetClassName(This->nselem, &classname_str);
357     nsAString_Finish(&classname_str);
358     if(NS_FAILED(nsres))
359         ERR("SetClassName failed: %08x\n", nsres);
360
361     return S_OK;
362 }
363
364 static HRESULT WINAPI HTMLElement_get_className(IHTMLElement *iface, BSTR *p)
365 {
366     HTMLElement *This = impl_from_IHTMLElement(iface);
367     nsAString class_str;
368     nsresult nsres;
369
370     TRACE("(%p)->(%p)\n", This, p);
371
372     if(!This->nselem) {
373         FIXME("NULL nselem\n");
374         return E_NOTIMPL;
375     }
376
377     nsAString_Init(&class_str, NULL);
378     nsres = nsIDOMHTMLElement_GetClassName(This->nselem, &class_str);
379     return return_nsstr(nsres, &class_str, p);
380 }
381
382 static HRESULT WINAPI HTMLElement_put_id(IHTMLElement *iface, BSTR v)
383 {
384     HTMLElement *This = impl_from_IHTMLElement(iface);
385     nsAString id_str;
386     nsresult nsres;
387
388     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
389
390     if(!This->nselem) {
391         FIXME("nselem == NULL\n");
392         return S_OK;
393     }
394
395     nsAString_InitDepend(&id_str, v);
396     nsres = nsIDOMHTMLElement_SetId(This->nselem, &id_str);
397     nsAString_Finish(&id_str);
398     if(NS_FAILED(nsres))
399         ERR("SetId failed: %08x\n", nsres);
400
401     return S_OK;
402 }
403
404 static HRESULT WINAPI HTMLElement_get_id(IHTMLElement *iface, BSTR *p)
405 {
406     HTMLElement *This = impl_from_IHTMLElement(iface);
407     nsAString id_str;
408     nsresult nsres;
409
410     TRACE("(%p)->(%p)\n", This, p);
411
412     if(!This->nselem) {
413         *p = NULL;
414         return S_OK;
415     }
416
417     nsAString_Init(&id_str, NULL);
418     nsres = nsIDOMHTMLElement_GetId(This->nselem, &id_str);
419     return return_nsstr(nsres, &id_str, p);
420 }
421
422 static HRESULT WINAPI HTMLElement_get_tagName(IHTMLElement *iface, BSTR *p)
423 {
424     HTMLElement *This = impl_from_IHTMLElement(iface);
425     nsAString tag_str;
426     nsresult nsres;
427
428     TRACE("(%p)->(%p)\n", This, p);
429
430     if(!This->nselem) {
431         static const WCHAR comment_tagW[] = {'!',0};
432
433         WARN("NULL nselem, assuming comment\n");
434
435         *p = SysAllocString(comment_tagW);
436         return *p ? S_OK : E_OUTOFMEMORY;
437     }
438
439     nsAString_Init(&tag_str, NULL);
440     nsres = nsIDOMHTMLElement_GetTagName(This->nselem, &tag_str);
441     return return_nsstr(nsres, &tag_str, p);
442 }
443
444 static HRESULT WINAPI HTMLElement_get_parentElement(IHTMLElement *iface, IHTMLElement **p)
445 {
446     HTMLElement *This = impl_from_IHTMLElement(iface);
447     IHTMLDOMNode *node;
448     HRESULT hres;
449
450     TRACE("(%p)->(%p)\n", This, p);
451
452     hres = IHTMLDOMNode_get_parentNode(&This->node.IHTMLDOMNode_iface, &node);
453     if(FAILED(hres))
454         return hres;
455
456     hres = IHTMLDOMNode_QueryInterface(node, &IID_IHTMLElement, (void**)p);
457     IHTMLDOMNode_Release(node);
458     if(FAILED(hres))
459         *p = NULL;
460
461     return S_OK;
462 }
463
464 static HRESULT WINAPI HTMLElement_get_style(IHTMLElement *iface, IHTMLStyle **p)
465 {
466     HTMLElement *This = impl_from_IHTMLElement(iface);
467
468     TRACE("(%p)->(%p)\n", This, p);
469
470     if(!This->style) {
471         HRESULT hres;
472
473         hres = HTMLStyle_Create(This, &This->style);
474         if(FAILED(hres))
475             return hres;
476     }
477
478     *p = &This->style->IHTMLStyle_iface;
479     IHTMLStyle_AddRef(*p);
480     return S_OK;
481 }
482
483 static HRESULT WINAPI HTMLElement_put_onhelp(IHTMLElement *iface, VARIANT v)
484 {
485     HTMLElement *This = impl_from_IHTMLElement(iface);
486     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
487     return E_NOTIMPL;
488 }
489
490 static HRESULT WINAPI HTMLElement_get_onhelp(IHTMLElement *iface, VARIANT *p)
491 {
492     HTMLElement *This = impl_from_IHTMLElement(iface);
493     FIXME("(%p)->(%p)\n", This, p);
494     return E_NOTIMPL;
495 }
496
497 static HRESULT WINAPI HTMLElement_put_onclick(IHTMLElement *iface, VARIANT v)
498 {
499     HTMLElement *This = impl_from_IHTMLElement(iface);
500
501     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
502
503     return set_node_event(&This->node, EVENTID_CLICK, &v);
504 }
505
506 static HRESULT WINAPI HTMLElement_get_onclick(IHTMLElement *iface, VARIANT *p)
507 {
508     HTMLElement *This = impl_from_IHTMLElement(iface);
509
510     TRACE("(%p)->(%p)\n", This, p);
511
512     return get_node_event(&This->node, EVENTID_CLICK, p);
513 }
514
515 static HRESULT WINAPI HTMLElement_put_ondblclick(IHTMLElement *iface, VARIANT v)
516 {
517     HTMLElement *This = impl_from_IHTMLElement(iface);
518
519     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
520
521     return set_node_event(&This->node, EVENTID_DBLCLICK, &v);
522 }
523
524 static HRESULT WINAPI HTMLElement_get_ondblclick(IHTMLElement *iface, VARIANT *p)
525 {
526     HTMLElement *This = impl_from_IHTMLElement(iface);
527
528     TRACE("(%p)->(%p)\n", This, p);
529
530     return get_node_event(&This->node, EVENTID_DBLCLICK, p);
531 }
532
533 static HRESULT WINAPI HTMLElement_put_onkeydown(IHTMLElement *iface, VARIANT v)
534 {
535     HTMLElement *This = impl_from_IHTMLElement(iface);
536
537     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
538
539     return set_node_event(&This->node, EVENTID_KEYDOWN, &v);
540 }
541
542 static HRESULT WINAPI HTMLElement_get_onkeydown(IHTMLElement *iface, VARIANT *p)
543 {
544     HTMLElement *This = impl_from_IHTMLElement(iface);
545
546     TRACE("(%p)->(%p)\n", This, p);
547
548     return get_node_event(&This->node, EVENTID_KEYDOWN, p);
549 }
550
551 static HRESULT WINAPI HTMLElement_put_onkeyup(IHTMLElement *iface, VARIANT v)
552 {
553     HTMLElement *This = impl_from_IHTMLElement(iface);
554
555     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
556
557     return set_node_event(&This->node, EVENTID_KEYUP, &v);
558 }
559
560 static HRESULT WINAPI HTMLElement_get_onkeyup(IHTMLElement *iface, VARIANT *p)
561 {
562     HTMLElement *This = impl_from_IHTMLElement(iface);
563     FIXME("(%p)->(%p)\n", This, p);
564     return E_NOTIMPL;
565 }
566
567 static HRESULT WINAPI HTMLElement_put_onkeypress(IHTMLElement *iface, VARIANT v)
568 {
569     HTMLElement *This = impl_from_IHTMLElement(iface);
570
571     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
572
573     return set_node_event(&This->node, EVENTID_KEYPRESS, &v);
574 }
575
576 static HRESULT WINAPI HTMLElement_get_onkeypress(IHTMLElement *iface, VARIANT *p)
577 {
578     HTMLElement *This = impl_from_IHTMLElement(iface);
579
580     TRACE("(%p)->(%p)\n", This, p);
581
582     return get_node_event(&This->node, EVENTID_KEYPRESS, p);
583 }
584
585 static HRESULT WINAPI HTMLElement_put_onmouseout(IHTMLElement *iface, VARIANT v)
586 {
587     HTMLElement *This = impl_from_IHTMLElement(iface);
588
589     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
590
591     return set_node_event(&This->node, EVENTID_MOUSEOUT, &v);
592 }
593
594 static HRESULT WINAPI HTMLElement_get_onmouseout(IHTMLElement *iface, VARIANT *p)
595 {
596     HTMLElement *This = impl_from_IHTMLElement(iface);
597
598     TRACE("(%p)->(%p)\n", This, p);
599
600     return get_node_event(&This->node, EVENTID_MOUSEOUT, p);
601 }
602
603 static HRESULT WINAPI HTMLElement_put_onmouseover(IHTMLElement *iface, VARIANT v)
604 {
605     HTMLElement *This = impl_from_IHTMLElement(iface);
606
607     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
608
609     return set_node_event(&This->node, EVENTID_MOUSEOVER, &v);
610 }
611
612 static HRESULT WINAPI HTMLElement_get_onmouseover(IHTMLElement *iface, VARIANT *p)
613 {
614     HTMLElement *This = impl_from_IHTMLElement(iface);
615
616     TRACE("(%p)->(%p)\n", This, p);
617
618     return get_node_event(&This->node, EVENTID_MOUSEOVER, p);
619 }
620
621 static HRESULT WINAPI HTMLElement_put_onmousemove(IHTMLElement *iface, VARIANT v)
622 {
623     HTMLElement *This = impl_from_IHTMLElement(iface);
624
625     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
626
627     return set_node_event(&This->node, EVENTID_MOUSEMOVE, &v);
628 }
629
630 static HRESULT WINAPI HTMLElement_get_onmousemove(IHTMLElement *iface, VARIANT *p)
631 {
632     HTMLElement *This = impl_from_IHTMLElement(iface);
633
634     TRACE("(%p)->(%p)\n", This, p);
635
636     return get_node_event(&This->node, EVENTID_MOUSEMOVE, p);
637 }
638
639 static HRESULT WINAPI HTMLElement_put_onmousedown(IHTMLElement *iface, VARIANT v)
640 {
641     HTMLElement *This = impl_from_IHTMLElement(iface);
642
643     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
644
645     return set_node_event(&This->node, EVENTID_MOUSEDOWN, &v);
646 }
647
648 static HRESULT WINAPI HTMLElement_get_onmousedown(IHTMLElement *iface, VARIANT *p)
649 {
650     HTMLElement *This = impl_from_IHTMLElement(iface);
651
652     TRACE("(%p)->(%p)\n", This, p);
653
654     return get_node_event(&This->node, EVENTID_MOUSEDOWN, p);
655 }
656
657 static HRESULT WINAPI HTMLElement_put_onmouseup(IHTMLElement *iface, VARIANT v)
658 {
659     HTMLElement *This = impl_from_IHTMLElement(iface);
660
661     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
662
663     return set_node_event(&This->node, EVENTID_MOUSEUP, &v);
664 }
665
666 static HRESULT WINAPI HTMLElement_get_onmouseup(IHTMLElement *iface, VARIANT *p)
667 {
668     HTMLElement *This = impl_from_IHTMLElement(iface);
669
670     TRACE("(%p)->(%p)\n", This, p);
671
672     return get_node_event(&This->node, EVENTID_MOUSEUP, p);
673 }
674
675 static HRESULT WINAPI HTMLElement_get_document(IHTMLElement *iface, IDispatch **p)
676 {
677     HTMLElement *This = impl_from_IHTMLElement(iface);
678
679     TRACE("(%p)->(%p)\n", This, p);
680
681     if(!p)
682         return E_POINTER;
683
684     if(This->node.vtbl->get_document)
685         return This->node.vtbl->get_document(&This->node, p);
686
687     *p = (IDispatch*)&This->node.doc->basedoc.IHTMLDocument2_iface;
688     IDispatch_AddRef(*p);
689     return S_OK;
690 }
691
692 static const WCHAR titleW[] = {'t','i','t','l','e',0};
693
694 static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v)
695 {
696     HTMLElement *This = impl_from_IHTMLElement(iface);
697     nsAString title_str;
698     nsresult nsres;
699
700     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
701
702     if(!This->nselem) {
703         VARIANT *var;
704         HRESULT hres;
705
706         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, TRUE, &var);
707         if(FAILED(hres))
708             return hres;
709
710         VariantClear(var);
711         V_VT(var) = VT_BSTR;
712         V_BSTR(var) = v ? SysAllocString(v) : NULL;
713         return S_OK;
714     }
715
716     nsAString_InitDepend(&title_str, v);
717     nsres = nsIDOMHTMLElement_SetTitle(This->nselem, &title_str);
718     nsAString_Finish(&title_str);
719     if(NS_FAILED(nsres))
720         ERR("SetTitle failed: %08x\n", nsres);
721
722     return S_OK;
723 }
724
725 static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *p)
726 {
727     HTMLElement *This = impl_from_IHTMLElement(iface);
728     nsAString title_str;
729     nsresult nsres;
730
731     TRACE("(%p)->(%p)\n", This, p);
732
733     if(!This->nselem) {
734         VARIANT *var;
735         HRESULT hres;
736
737         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, FALSE, &var);
738         if(hres == DISP_E_UNKNOWNNAME) {
739             *p = NULL;
740         }else if(V_VT(var) != VT_BSTR) {
741             FIXME("title = %s\n", debugstr_variant(var));
742             return E_FAIL;
743         }else {
744             *p = V_BSTR(var) ? SysAllocString(V_BSTR(var)) : NULL;
745         }
746
747         return S_OK;
748     }
749
750     nsAString_Init(&title_str, NULL);
751     nsres = nsIDOMHTMLElement_GetTitle(This->nselem, &title_str);
752     return return_nsstr(nsres, &title_str, p);
753 }
754
755 static HRESULT WINAPI HTMLElement_put_language(IHTMLElement *iface, BSTR v)
756 {
757     HTMLElement *This = impl_from_IHTMLElement(iface);
758     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
759     return E_NOTIMPL;
760 }
761
762 static HRESULT WINAPI HTMLElement_get_language(IHTMLElement *iface, BSTR *p)
763 {
764     HTMLElement *This = impl_from_IHTMLElement(iface);
765     FIXME("(%p)->(%p)\n", This, p);
766     return E_NOTIMPL;
767 }
768
769 static HRESULT WINAPI HTMLElement_put_onselectstart(IHTMLElement *iface, VARIANT v)
770 {
771     HTMLElement *This = impl_from_IHTMLElement(iface);
772
773     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
774
775     return set_node_event(&This->node, EVENTID_SELECTSTART, &v);
776 }
777
778 static HRESULT WINAPI HTMLElement_get_onselectstart(IHTMLElement *iface, VARIANT *p)
779 {
780     HTMLElement *This = impl_from_IHTMLElement(iface);
781
782     TRACE("(%p)->(%p)\n", This, p);
783
784     return get_node_event(&This->node, EVENTID_SELECTSTART, p);
785 }
786
787 static HRESULT WINAPI HTMLElement_scrollIntoView(IHTMLElement *iface, VARIANT varargStart)
788 {
789     HTMLElement *This = impl_from_IHTMLElement(iface);
790     FIXME("(%p)->(%s)\n", This, debugstr_variant(&varargStart));
791     return E_NOTIMPL;
792 }
793
794 static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pChild,
795                                            VARIANT_BOOL *pfResult)
796 {
797     HTMLElement *This = impl_from_IHTMLElement(iface);
798     HTMLElement *child;
799     cpp_bool result;
800     nsresult nsres;
801
802     TRACE("(%p)->(%p %p)\n", This, pChild, pfResult);
803
804     child = unsafe_impl_from_IHTMLElement(pChild);
805     if(!child) {
806         ERR("not our element\n");
807         return E_FAIL;
808     }
809
810     nsres = nsIDOMNode_Contains(This->node.nsnode, child->node.nsnode, &result);
811     if(NS_FAILED(nsres)) {
812         ERR("failed\n");
813         return E_FAIL;
814     }
815
816     *pfResult = result ? VARIANT_TRUE : VARIANT_FALSE;
817     return S_OK;
818 }
819
820 static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, LONG *p)
821 {
822     HTMLElement *This = impl_from_IHTMLElement(iface);
823     FIXME("(%p)->(%p)\n", This, p);
824     return E_NOTIMPL;
825 }
826
827 static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
828 {
829     HTMLElement *This = impl_from_IHTMLElement(iface);
830     FIXME("(%p)->(%p)\n", This, p);
831     return E_NOTIMPL;
832 }
833
834 static HRESULT WINAPI HTMLElement_put_lang(IHTMLElement *iface, BSTR v)
835 {
836     HTMLElement *This = impl_from_IHTMLElement(iface);
837     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
838     return E_NOTIMPL;
839 }
840
841 static HRESULT WINAPI HTMLElement_get_lang(IHTMLElement *iface, BSTR *p)
842 {
843     HTMLElement *This = impl_from_IHTMLElement(iface);
844     FIXME("(%p)->(%p)\n", This, p);
845     return E_NOTIMPL;
846 }
847
848 static HRESULT WINAPI HTMLElement_get_offsetLeft(IHTMLElement *iface, LONG *p)
849 {
850     HTMLElement *This = impl_from_IHTMLElement(iface);
851     nsresult nsres;
852
853     TRACE("(%p)->(%p)\n", This, p);
854
855     nsres = nsIDOMHTMLElement_GetOffsetLeft(This->nselem, p);
856     if(NS_FAILED(nsres)) {
857         ERR("GetOffsetLeft failed: %08x\n", nsres);
858         return E_FAIL;
859     }
860
861     return S_OK;
862 }
863
864 static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, LONG *p)
865 {
866     HTMLElement *This = impl_from_IHTMLElement(iface);
867     nsresult nsres;
868
869     TRACE("(%p)->(%p)\n", This, p);
870
871     nsres = nsIDOMHTMLElement_GetOffsetTop(This->nselem, p);
872     if(NS_FAILED(nsres)) {
873         ERR("GetOffsetTop failed: %08x\n", nsres);
874         return E_FAIL;
875     }
876
877     return S_OK;
878 }
879
880 static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, LONG *p)
881 {
882     HTMLElement *This = impl_from_IHTMLElement(iface);
883     nsresult nsres;
884
885     TRACE("(%p)->(%p)\n", This, p);
886
887     nsres = nsIDOMHTMLElement_GetOffsetWidth(This->nselem, p);
888     if(NS_FAILED(nsres)) {
889         ERR("GetOffsetWidth failed: %08x\n", nsres);
890         return E_FAIL;
891     }
892
893     return S_OK;
894 }
895
896 static HRESULT WINAPI HTMLElement_get_offsetHeight(IHTMLElement *iface, LONG *p)
897 {
898     HTMLElement *This = impl_from_IHTMLElement(iface);
899     nsresult nsres;
900
901     TRACE("(%p)->(%p)\n", This, p);
902
903     nsres = nsIDOMHTMLElement_GetOffsetHeight(This->nselem, p);
904     if(NS_FAILED(nsres)) {
905         ERR("GetOffsetHeight failed: %08x\n", nsres);
906         return E_FAIL;
907     }
908
909     return S_OK;
910 }
911
912 static HRESULT WINAPI HTMLElement_get_offsetParent(IHTMLElement *iface, IHTMLElement **p)
913 {
914     HTMLElement *This = impl_from_IHTMLElement(iface);
915     nsIDOMElement *nsparent;
916     nsresult nsres;
917     HRESULT hres;
918
919     TRACE("(%p)->(%p)\n", This, p);
920
921     nsres = nsIDOMHTMLElement_GetOffsetParent(This->nselem, &nsparent);
922     if(NS_FAILED(nsres)) {
923         ERR("GetOffsetParent failed: %08x\n", nsres);
924         return E_FAIL;
925     }
926
927     if(nsparent) {
928         HTMLDOMNode *node;
929
930         hres = get_node(This->node.doc, (nsIDOMNode*)nsparent, TRUE, &node);
931         nsIDOMElement_Release(nsparent);
932         if(FAILED(hres))
933             return hres;
934
935         hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_IHTMLElement, (void**)p);
936         node_release(node);
937     }else {
938         *p = NULL;
939         hres = S_OK;
940     }
941
942     return hres;
943 }
944
945 static HRESULT WINAPI HTMLElement_put_innerHTML(IHTMLElement *iface, BSTR v)
946 {
947     HTMLElement *This = impl_from_IHTMLElement(iface);
948     nsAString html_str;
949     nsresult nsres;
950
951     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
952
953     if(!This->nselem) {
954         FIXME("NULL nselem\n");
955         return E_NOTIMPL;
956     }
957
958     nsAString_InitDepend(&html_str, v);
959     nsres = nsIDOMHTMLElement_SetInnerHTML(This->nselem, &html_str);
960     nsAString_Finish(&html_str);
961     if(NS_FAILED(nsres)) {
962         FIXME("SetInnerHtml failed %08x\n", nsres);
963         return E_FAIL;
964     }
965
966     return S_OK;
967 }
968
969 static HRESULT WINAPI HTMLElement_get_innerHTML(IHTMLElement *iface, BSTR *p)
970 {
971     HTMLElement *This = impl_from_IHTMLElement(iface);
972     nsAString html_str;
973     nsresult nsres;
974
975     TRACE("(%p)->(%p)\n", This, p);
976
977     if(!This->nselem) {
978         FIXME("NULL nselem\n");
979         return E_NOTIMPL;
980     }
981
982     nsAString_Init(&html_str, NULL);
983     nsres = nsIDOMHTMLElement_GetInnerHTML(This->nselem, &html_str);
984     return return_nsstr(nsres, &html_str, p);
985 }
986
987 static HRESULT WINAPI HTMLElement_put_innerText(IHTMLElement *iface, BSTR v)
988 {
989     HTMLElement *This = impl_from_IHTMLElement(iface);
990     nsIDOMNode *nschild, *tmp;
991     nsIDOMText *text_node;
992     nsAString text_str;
993     nsresult nsres;
994
995     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
996
997     while(1) {
998         nsres = nsIDOMHTMLElement_GetLastChild(This->nselem, &nschild);
999         if(NS_FAILED(nsres)) {
1000             ERR("GetLastChild failed: %08x\n", nsres);
1001             return E_FAIL;
1002         }
1003         if(!nschild)
1004             break;
1005
1006         nsres = nsIDOMHTMLElement_RemoveChild(This->nselem, nschild, &tmp);
1007         nsIDOMNode_Release(nschild);
1008         if(NS_FAILED(nsres)) {
1009             ERR("RemoveChild failed: %08x\n", nsres);
1010             return E_FAIL;
1011         }
1012         nsIDOMNode_Release(tmp);
1013     }
1014
1015     nsAString_InitDepend(&text_str, v);
1016     nsres = nsIDOMHTMLDocument_CreateTextNode(This->node.doc->nsdoc, &text_str, &text_node);
1017     nsAString_Finish(&text_str);
1018     if(NS_FAILED(nsres)) {
1019         ERR("CreateTextNode failed: %08x\n", nsres);
1020         return E_FAIL;
1021     }
1022
1023     nsres = nsIDOMHTMLElement_AppendChild(This->nselem, (nsIDOMNode*)text_node, &tmp);
1024     if(NS_FAILED(nsres)) {
1025         ERR("AppendChild failed: %08x\n", nsres);
1026         return E_FAIL;
1027     }
1028
1029     nsIDOMNode_Release(tmp);
1030     return S_OK;
1031 }
1032
1033 static HRESULT WINAPI HTMLElement_get_innerText(IHTMLElement *iface, BSTR *p)
1034 {
1035     HTMLElement *This = impl_from_IHTMLElement(iface);
1036
1037     TRACE("(%p)->(%p)\n", This, p);
1038
1039     return get_node_text(&This->node, p);
1040 }
1041
1042 static HRESULT WINAPI HTMLElement_put_outerHTML(IHTMLElement *iface, BSTR v)
1043 {
1044     HTMLElement *This = impl_from_IHTMLElement(iface);
1045
1046     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
1047
1048     return replace_node_by_html(This->node.doc->nsdoc, This->node.nsnode, v);
1049 }
1050
1051 static HRESULT WINAPI HTMLElement_get_outerHTML(IHTMLElement *iface, BSTR *p)
1052 {
1053     HTMLElement *This = impl_from_IHTMLElement(iface);
1054     nsAString html_str;
1055     HRESULT hres;
1056
1057     WARN("(%p)->(%p) semi-stub\n", This, p);
1058
1059     nsAString_Init(&html_str, NULL);
1060     hres = nsnode_to_nsstring(This->node.nsnode, &html_str);
1061     if(SUCCEEDED(hres)) {
1062         const PRUnichar *html;
1063
1064         nsAString_GetData(&html_str, &html);
1065         *p = SysAllocString(html);
1066         if(!*p)
1067             hres = E_OUTOFMEMORY;
1068     }
1069
1070     nsAString_Finish(&html_str);
1071
1072     TRACE("ret %s\n", debugstr_w(*p));
1073     return hres;
1074 }
1075
1076 static HRESULT WINAPI HTMLElement_put_outerText(IHTMLElement *iface, BSTR v)
1077 {
1078     HTMLElement *This = impl_from_IHTMLElement(iface);
1079     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
1080     return E_NOTIMPL;
1081 }
1082
1083 static HRESULT WINAPI HTMLElement_get_outerText(IHTMLElement *iface, BSTR *p)
1084 {
1085     HTMLElement *This = impl_from_IHTMLElement(iface);
1086     FIXME("(%p)->(%p)\n", This, p);
1087     return E_NOTIMPL;
1088 }
1089
1090 HRESULT insert_adjacent_node(HTMLElement *This, const WCHAR *where, nsIDOMNode *nsnode, HTMLDOMNode **ret_node)
1091 {
1092     nsIDOMNode *ret_nsnode;
1093     nsresult nsres;
1094     HRESULT hres = S_OK;
1095
1096     static const WCHAR beforebeginW[] = {'b','e','f','o','r','e','b','e','g','i','n',0};
1097     static const WCHAR afterbeginW[] = {'a','f','t','e','r','b','e','g','i','n',0};
1098     static const WCHAR beforeendW[] = {'b','e','f','o','r','e','e','n','d',0};
1099     static const WCHAR afterendW[] = {'a','f','t','e','r','e','n','d',0};
1100
1101     if (!strcmpiW(where, beforebeginW)) {
1102         nsIDOMNode *parent;
1103
1104         nsres = nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1105         if(NS_FAILED(nsres))
1106             return E_FAIL;
1107
1108         if(!parent)
1109             return E_INVALIDARG;
1110
1111         nsres = nsIDOMNode_InsertBefore(parent, nsnode, This->node.nsnode, &ret_nsnode);
1112         nsIDOMNode_Release(parent);
1113     }else if(!strcmpiW(where, afterbeginW)) {
1114         nsIDOMNode *first_child;
1115
1116         nsres = nsIDOMNode_GetFirstChild(This->node.nsnode, &first_child);
1117         if(NS_FAILED(nsres))
1118             return E_FAIL;
1119
1120         nsres = nsIDOMNode_InsertBefore(This->node.nsnode, nsnode, first_child, &ret_nsnode);
1121         if(NS_FAILED(nsres))
1122             return E_FAIL;
1123
1124         if (first_child)
1125             nsIDOMNode_Release(first_child);
1126     }else if (!strcmpiW(where, beforeendW)) {
1127         nsres = nsIDOMNode_AppendChild(This->node.nsnode, nsnode, &ret_nsnode);
1128     }else if (!strcmpiW(where, afterendW)) {
1129         nsIDOMNode *next_sibling, *parent;
1130
1131         nsres = nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1132         if(NS_FAILED(nsres))
1133             return E_FAIL;
1134         if(!parent)
1135             return E_INVALIDARG;
1136
1137         nsres = nsIDOMNode_GetNextSibling(This->node.nsnode, &next_sibling);
1138         if(NS_SUCCEEDED(nsres)) {
1139             if(next_sibling) {
1140                 nsres = nsIDOMNode_InsertBefore(parent, nsnode, next_sibling, &ret_nsnode);
1141                 nsIDOMNode_Release(next_sibling);
1142             }else {
1143                 nsres = nsIDOMNode_AppendChild(parent, nsnode, &ret_nsnode);
1144             }
1145         }
1146
1147         nsIDOMNode_Release(parent);
1148     }else {
1149         ERR("invalid where: %s\n", debugstr_w(where));
1150         return E_INVALIDARG;
1151     }
1152
1153     if (NS_FAILED(nsres))
1154         return E_FAIL;
1155
1156     if(ret_node)
1157         hres = get_node(This->node.doc, ret_nsnode, TRUE, ret_node);
1158     nsIDOMNode_Release(ret_nsnode);
1159     return hres;
1160 }
1161
1162 static HRESULT WINAPI HTMLElement_insertAdjacentHTML(IHTMLElement *iface, BSTR where,
1163                                                      BSTR html)
1164 {
1165     HTMLElement *This = impl_from_IHTMLElement(iface);
1166     nsIDOMRange *range;
1167     nsIDOMNode *nsnode;
1168     nsAString ns_html;
1169     nsresult nsres;
1170     HRESULT hr;
1171
1172     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(html));
1173
1174     if(!This->node.doc->nsdoc) {
1175         WARN("NULL nsdoc\n");
1176         return E_UNEXPECTED;
1177     }
1178
1179     nsres = nsIDOMHTMLDocument_CreateRange(This->node.doc->nsdoc, &range);
1180     if(NS_FAILED(nsres))
1181     {
1182         ERR("CreateRange failed: %08x\n", nsres);
1183         return E_FAIL;
1184     }
1185
1186     nsIDOMRange_SetStartBefore(range, This->node.nsnode);
1187
1188     nsAString_InitDepend(&ns_html, html);
1189     nsres = nsIDOMRange_CreateContextualFragment(range, &ns_html, (nsIDOMDocumentFragment **)&nsnode);
1190     nsAString_Finish(&ns_html);
1191     nsIDOMRange_Release(range);
1192
1193     if(NS_FAILED(nsres) || !nsnode)
1194     {
1195         ERR("CreateTextNode failed: %08x\n", nsres);
1196         return E_FAIL;
1197     }
1198
1199     hr = insert_adjacent_node(This, where, nsnode, NULL);
1200     nsIDOMNode_Release(nsnode);
1201     return hr;
1202 }
1203
1204 static HRESULT WINAPI HTMLElement_insertAdjacentText(IHTMLElement *iface, BSTR where,
1205                                                      BSTR text)
1206 {
1207     HTMLElement *This = impl_from_IHTMLElement(iface);
1208     nsIDOMNode *nsnode;
1209     nsAString ns_text;
1210     nsresult nsres;
1211     HRESULT hr;
1212
1213     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(text));
1214
1215     if(!This->node.doc->nsdoc) {
1216         WARN("NULL nsdoc\n");
1217         return E_UNEXPECTED;
1218     }
1219
1220
1221     nsAString_InitDepend(&ns_text, text);
1222     nsres = nsIDOMHTMLDocument_CreateTextNode(This->node.doc->nsdoc, &ns_text, (nsIDOMText **)&nsnode);
1223     nsAString_Finish(&ns_text);
1224
1225     if(NS_FAILED(nsres) || !nsnode)
1226     {
1227         ERR("CreateTextNode failed: %08x\n", nsres);
1228         return E_FAIL;
1229     }
1230
1231     hr = insert_adjacent_node(This, where, nsnode, NULL);
1232     nsIDOMNode_Release(nsnode);
1233
1234     return hr;
1235 }
1236
1237 static HRESULT WINAPI HTMLElement_get_parentTextEdit(IHTMLElement *iface, IHTMLElement **p)
1238 {
1239     HTMLElement *This = impl_from_IHTMLElement(iface);
1240     FIXME("(%p)->(%p)\n", This, p);
1241     return E_NOTIMPL;
1242 }
1243
1244 static HRESULT WINAPI HTMLElement_get_isTextEdit(IHTMLElement *iface, VARIANT_BOOL *p)
1245 {
1246     HTMLElement *This = impl_from_IHTMLElement(iface);
1247     FIXME("(%p)->(%p)\n", This, p);
1248     return E_NOTIMPL;
1249 }
1250
1251 static HRESULT WINAPI HTMLElement_click(IHTMLElement *iface)
1252 {
1253     HTMLElement *This = impl_from_IHTMLElement(iface);
1254
1255     TRACE("(%p)\n", This);
1256
1257     return call_fire_event(&This->node, EVENTID_CLICK);
1258 }
1259
1260 static HRESULT WINAPI HTMLElement_get_filters(IHTMLElement *iface,
1261                                               IHTMLFiltersCollection **p)
1262 {
1263     HTMLElement *This = impl_from_IHTMLElement(iface);
1264     TRACE("(%p)->(%p)\n", This, p);
1265
1266     if(!p)
1267         return E_POINTER;
1268
1269     *p = HTMLFiltersCollection_Create();
1270
1271     return S_OK;
1272 }
1273
1274 static HRESULT WINAPI HTMLElement_put_ondragstart(IHTMLElement *iface, VARIANT v)
1275 {
1276     HTMLElement *This = impl_from_IHTMLElement(iface);
1277     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1278     return E_NOTIMPL;
1279 }
1280
1281 static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *p)
1282 {
1283     HTMLElement *This = impl_from_IHTMLElement(iface);
1284     FIXME("(%p)->(%p)\n", This, p);
1285     return E_NOTIMPL;
1286 }
1287
1288 static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
1289 {
1290     HTMLElement *This = impl_from_IHTMLElement(iface);
1291     FIXME("(%p)->(%p)\n", This, String);
1292     return E_NOTIMPL;
1293 }
1294
1295 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
1296 {
1297     HTMLElement *This = impl_from_IHTMLElement(iface);
1298     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1299     return E_NOTIMPL;
1300 }
1301
1302 static HRESULT WINAPI HTMLElement_get_onbeforeupdate(IHTMLElement *iface, VARIANT *p)
1303 {
1304     HTMLElement *This = impl_from_IHTMLElement(iface);
1305     FIXME("(%p)->(%p)\n", This, p);
1306     return E_NOTIMPL;
1307 }
1308
1309 static HRESULT WINAPI HTMLElement_put_onafterupdate(IHTMLElement *iface, VARIANT v)
1310 {
1311     HTMLElement *This = impl_from_IHTMLElement(iface);
1312     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1313     return E_NOTIMPL;
1314 }
1315
1316 static HRESULT WINAPI HTMLElement_get_onafterupdate(IHTMLElement *iface, VARIANT *p)
1317 {
1318     HTMLElement *This = impl_from_IHTMLElement(iface);
1319     FIXME("(%p)->(%p)\n", This, p);
1320     return E_NOTIMPL;
1321 }
1322
1323 static HRESULT WINAPI HTMLElement_put_onerrorupdate(IHTMLElement *iface, VARIANT v)
1324 {
1325     HTMLElement *This = impl_from_IHTMLElement(iface);
1326     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1327     return E_NOTIMPL;
1328 }
1329
1330 static HRESULT WINAPI HTMLElement_get_onerrorupdate(IHTMLElement *iface, VARIANT *p)
1331 {
1332     HTMLElement *This = impl_from_IHTMLElement(iface);
1333     FIXME("(%p)->(%p)\n", This, p);
1334     return E_NOTIMPL;
1335 }
1336
1337 static HRESULT WINAPI HTMLElement_put_onrowexit(IHTMLElement *iface, VARIANT v)
1338 {
1339     HTMLElement *This = impl_from_IHTMLElement(iface);
1340     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1341     return E_NOTIMPL;
1342 }
1343
1344 static HRESULT WINAPI HTMLElement_get_onrowexit(IHTMLElement *iface, VARIANT *p)
1345 {
1346     HTMLElement *This = impl_from_IHTMLElement(iface);
1347     FIXME("(%p)->(%p)\n", This, p);
1348     return E_NOTIMPL;
1349 }
1350
1351 static HRESULT WINAPI HTMLElement_put_onrowenter(IHTMLElement *iface, VARIANT v)
1352 {
1353     HTMLElement *This = impl_from_IHTMLElement(iface);
1354     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1355     return E_NOTIMPL;
1356 }
1357
1358 static HRESULT WINAPI HTMLElement_get_onrowenter(IHTMLElement *iface, VARIANT *p)
1359 {
1360     HTMLElement *This = impl_from_IHTMLElement(iface);
1361     FIXME("(%p)->(%p)\n", This, p);
1362     return E_NOTIMPL;
1363 }
1364
1365 static HRESULT WINAPI HTMLElement_put_ondatasetchanged(IHTMLElement *iface, VARIANT v)
1366 {
1367     HTMLElement *This = impl_from_IHTMLElement(iface);
1368     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1369     return E_NOTIMPL;
1370 }
1371
1372 static HRESULT WINAPI HTMLElement_get_ondatasetchanged(IHTMLElement *iface, VARIANT *p)
1373 {
1374     HTMLElement *This = impl_from_IHTMLElement(iface);
1375     FIXME("(%p)->(%p)\n", This, p);
1376     return E_NOTIMPL;
1377 }
1378
1379 static HRESULT WINAPI HTMLElement_put_ondataavailable(IHTMLElement *iface, VARIANT v)
1380 {
1381     HTMLElement *This = impl_from_IHTMLElement(iface);
1382
1383     FIXME("(%p)->(%s) semi-stub\n", This, debugstr_variant(&v));
1384
1385     return set_node_event(&This->node, EVENTID_DATAAVAILABLE, &v);
1386 }
1387
1388 static HRESULT WINAPI HTMLElement_get_ondataavailable(IHTMLElement *iface, VARIANT *p)
1389 {
1390     HTMLElement *This = impl_from_IHTMLElement(iface);
1391
1392     TRACE("(%p)->(%p)\n", This, p);
1393
1394     return get_node_event(&This->node, EVENTID_DATAAVAILABLE, p);
1395 }
1396
1397 static HRESULT WINAPI HTMLElement_put_ondatasetcomplete(IHTMLElement *iface, VARIANT v)
1398 {
1399     HTMLElement *This = impl_from_IHTMLElement(iface);
1400     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1401     return E_NOTIMPL;
1402 }
1403
1404 static HRESULT WINAPI HTMLElement_get_ondatasetcomplete(IHTMLElement *iface, VARIANT *p)
1405 {
1406     HTMLElement *This = impl_from_IHTMLElement(iface);
1407     FIXME("(%p)->(%p)\n", This, p);
1408     return E_NOTIMPL;
1409 }
1410
1411 static HRESULT WINAPI HTMLElement_put_onfilterchange(IHTMLElement *iface, VARIANT v)
1412 {
1413     HTMLElement *This = impl_from_IHTMLElement(iface);
1414     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1415     return E_NOTIMPL;
1416 }
1417
1418 static HRESULT WINAPI HTMLElement_get_onfilterchange(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_get_children(IHTMLElement *iface, IDispatch **p)
1426 {
1427     HTMLElement *This = impl_from_IHTMLElement(iface);
1428     nsIDOMNodeList *nsnode_list;
1429     nsresult nsres;
1430
1431     TRACE("(%p)->(%p)\n", This, p);
1432
1433     nsres = nsIDOMNode_GetChildNodes(This->node.nsnode, &nsnode_list);
1434     if(NS_FAILED(nsres)) {
1435         ERR("GetChildNodes failed: %08x\n", nsres);
1436         return E_FAIL;
1437     }
1438
1439     *p = (IDispatch*)create_collection_from_nodelist(This->node.doc, nsnode_list);
1440
1441     nsIDOMNodeList_Release(nsnode_list);
1442     return S_OK;
1443 }
1444
1445 static HRESULT WINAPI HTMLElement_get_all(IHTMLElement *iface, IDispatch **p)
1446 {
1447     HTMLElement *This = impl_from_IHTMLElement(iface);
1448
1449     TRACE("(%p)->(%p)\n", This, p);
1450
1451     *p = (IDispatch*)create_all_collection(&This->node, FALSE);
1452     return S_OK;
1453 }
1454
1455 static const IHTMLElementVtbl HTMLElementVtbl = {
1456     HTMLElement_QueryInterface,
1457     HTMLElement_AddRef,
1458     HTMLElement_Release,
1459     HTMLElement_GetTypeInfoCount,
1460     HTMLElement_GetTypeInfo,
1461     HTMLElement_GetIDsOfNames,
1462     HTMLElement_Invoke,
1463     HTMLElement_setAttribute,
1464     HTMLElement_getAttribute,
1465     HTMLElement_removeAttribute,
1466     HTMLElement_put_className,
1467     HTMLElement_get_className,
1468     HTMLElement_put_id,
1469     HTMLElement_get_id,
1470     HTMLElement_get_tagName,
1471     HTMLElement_get_parentElement,
1472     HTMLElement_get_style,
1473     HTMLElement_put_onhelp,
1474     HTMLElement_get_onhelp,
1475     HTMLElement_put_onclick,
1476     HTMLElement_get_onclick,
1477     HTMLElement_put_ondblclick,
1478     HTMLElement_get_ondblclick,
1479     HTMLElement_put_onkeydown,
1480     HTMLElement_get_onkeydown,
1481     HTMLElement_put_onkeyup,
1482     HTMLElement_get_onkeyup,
1483     HTMLElement_put_onkeypress,
1484     HTMLElement_get_onkeypress,
1485     HTMLElement_put_onmouseout,
1486     HTMLElement_get_onmouseout,
1487     HTMLElement_put_onmouseover,
1488     HTMLElement_get_onmouseover,
1489     HTMLElement_put_onmousemove,
1490     HTMLElement_get_onmousemove,
1491     HTMLElement_put_onmousedown,
1492     HTMLElement_get_onmousedown,
1493     HTMLElement_put_onmouseup,
1494     HTMLElement_get_onmouseup,
1495     HTMLElement_get_document,
1496     HTMLElement_put_title,
1497     HTMLElement_get_title,
1498     HTMLElement_put_language,
1499     HTMLElement_get_language,
1500     HTMLElement_put_onselectstart,
1501     HTMLElement_get_onselectstart,
1502     HTMLElement_scrollIntoView,
1503     HTMLElement_contains,
1504     HTMLElement_get_sourceIndex,
1505     HTMLElement_get_recordNumber,
1506     HTMLElement_put_lang,
1507     HTMLElement_get_lang,
1508     HTMLElement_get_offsetLeft,
1509     HTMLElement_get_offsetTop,
1510     HTMLElement_get_offsetWidth,
1511     HTMLElement_get_offsetHeight,
1512     HTMLElement_get_offsetParent,
1513     HTMLElement_put_innerHTML,
1514     HTMLElement_get_innerHTML,
1515     HTMLElement_put_innerText,
1516     HTMLElement_get_innerText,
1517     HTMLElement_put_outerHTML,
1518     HTMLElement_get_outerHTML,
1519     HTMLElement_put_outerText,
1520     HTMLElement_get_outerText,
1521     HTMLElement_insertAdjacentHTML,
1522     HTMLElement_insertAdjacentText,
1523     HTMLElement_get_parentTextEdit,
1524     HTMLElement_get_isTextEdit,
1525     HTMLElement_click,
1526     HTMLElement_get_filters,
1527     HTMLElement_put_ondragstart,
1528     HTMLElement_get_ondragstart,
1529     HTMLElement_toString,
1530     HTMLElement_put_onbeforeupdate,
1531     HTMLElement_get_onbeforeupdate,
1532     HTMLElement_put_onafterupdate,
1533     HTMLElement_get_onafterupdate,
1534     HTMLElement_put_onerrorupdate,
1535     HTMLElement_get_onerrorupdate,
1536     HTMLElement_put_onrowexit,
1537     HTMLElement_get_onrowexit,
1538     HTMLElement_put_onrowenter,
1539     HTMLElement_get_onrowenter,
1540     HTMLElement_put_ondatasetchanged,
1541     HTMLElement_get_ondatasetchanged,
1542     HTMLElement_put_ondataavailable,
1543     HTMLElement_get_ondataavailable,
1544     HTMLElement_put_ondatasetcomplete,
1545     HTMLElement_get_ondatasetcomplete,
1546     HTMLElement_put_onfilterchange,
1547     HTMLElement_get_onfilterchange,
1548     HTMLElement_get_children,
1549     HTMLElement_get_all
1550 };
1551
1552 HTMLElement *unsafe_impl_from_IHTMLElement(IHTMLElement *iface)
1553 {
1554     return iface->lpVtbl == &HTMLElementVtbl ? impl_from_IHTMLElement(iface) : NULL;
1555 }
1556
1557 static inline HTMLElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
1558 {
1559     return CONTAINING_RECORD(iface, HTMLElement, node);
1560 }
1561
1562 HRESULT HTMLElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
1563 {
1564     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1565
1566     *ppv =  NULL;
1567
1568     if(IsEqualGUID(&IID_IUnknown, riid)) {
1569         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1570         *ppv = &This->IHTMLElement_iface;
1571     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1572         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1573         *ppv = &This->IHTMLElement_iface;
1574     }else if(IsEqualGUID(&IID_IHTMLElement, riid)) {
1575         TRACE("(%p)->(IID_IHTMLElement %p)\n", This, ppv);
1576         *ppv = &This->IHTMLElement_iface;
1577     }else if(IsEqualGUID(&IID_IHTMLElement2, riid)) {
1578         TRACE("(%p)->(IID_IHTMLElement2 %p)\n", This, ppv);
1579         *ppv = &This->IHTMLElement2_iface;
1580     }else if(IsEqualGUID(&IID_IHTMLElement3, riid)) {
1581         TRACE("(%p)->(IID_IHTMLElement3 %p)\n", This, ppv);
1582         *ppv = &This->IHTMLElement3_iface;
1583     }else if(IsEqualGUID(&IID_IHTMLElement4, riid)) {
1584         TRACE("(%p)->(IID_IHTMLElement4 %p)\n", This, ppv);
1585         *ppv = &This->IHTMLElement4_iface;
1586     }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) {
1587         TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv);
1588         *ppv = &This->cp_container.IConnectionPointContainer_iface;
1589     }
1590
1591     if(*ppv) {
1592         IHTMLElement_AddRef(&This->IHTMLElement_iface);
1593         return S_OK;
1594     }
1595
1596     return HTMLDOMNode_QI(&This->node, riid, ppv);
1597 }
1598
1599 void HTMLElement_destructor(HTMLDOMNode *iface)
1600 {
1601     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1602
1603     ConnectionPointContainer_Destroy(&This->cp_container);
1604
1605     if(This->style) {
1606         This->style->elem = NULL;
1607         IHTMLStyle_Release(&This->style->IHTMLStyle_iface);
1608     }
1609     if(This->runtime_style) {
1610         This->runtime_style->elem = NULL;
1611         IHTMLStyle_Release(&This->runtime_style->IHTMLStyle_iface);
1612     }
1613     if(This->attrs) {
1614         HTMLDOMAttribute *attr;
1615
1616         LIST_FOR_EACH_ENTRY(attr, &This->attrs->attrs, HTMLDOMAttribute, entry)
1617             attr->elem = NULL;
1618
1619         This->attrs->elem = NULL;
1620         IHTMLAttributeCollection_Release(&This->attrs->IHTMLAttributeCollection_iface);
1621     }
1622
1623     heap_free(This->filter);
1624
1625     HTMLDOMNode_destructor(&This->node);
1626 }
1627
1628 HRESULT HTMLElement_clone(HTMLDOMNode *iface, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1629 {
1630     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1631     HTMLElement *new_elem;
1632     HRESULT hres;
1633
1634     hres = HTMLElement_Create(This->node.doc, nsnode, FALSE, &new_elem);
1635     if(FAILED(hres))
1636         return hres;
1637
1638     if(This->filter) {
1639         new_elem->filter = heap_strdupW(This->filter);
1640         if(!new_elem->filter) {
1641             IHTMLElement_Release(&This->IHTMLElement_iface);
1642             return E_OUTOFMEMORY;
1643         }
1644     }
1645
1646     *ret = &new_elem->node;
1647     return S_OK;
1648 }
1649
1650 HRESULT HTMLElement_handle_event(HTMLDOMNode *iface, DWORD eid, nsIDOMEvent *event, BOOL *prevent_default)
1651 {
1652     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1653
1654     switch(eid) {
1655     case EVENTID_KEYDOWN: {
1656         nsIDOMKeyEvent *key_event;
1657         nsresult nsres;
1658
1659         nsres = nsIDOMEvent_QueryInterface(event, &IID_nsIDOMKeyEvent, (void**)&key_event);
1660         if(NS_SUCCEEDED(nsres)) {
1661             UINT32 code = 0;
1662
1663             nsIDOMKeyEvent_GetKeyCode(key_event, &code);
1664
1665             switch(code) {
1666             case VK_F1: /* DOM_VK_F1 */
1667                 TRACE("F1 pressed\n");
1668                 fire_event(This->node.doc, EVENTID_HELP, TRUE, This->node.nsnode, NULL, NULL);
1669                 *prevent_default = TRUE;
1670             }
1671
1672             nsIDOMKeyEvent_Release(key_event);
1673         }
1674     }
1675     }
1676
1677     return S_OK;
1678 }
1679
1680 static const NodeImplVtbl HTMLElementImplVtbl = {
1681     HTMLElement_QI,
1682     HTMLElement_destructor,
1683     HTMLElement_clone,
1684     HTMLElement_handle_event,
1685     HTMLElement_get_attr_col
1686 };
1687
1688 static inline HTMLElement *impl_from_DispatchEx(DispatchEx *iface)
1689 {
1690     return CONTAINING_RECORD(iface, HTMLElement, node.dispex);
1691 }
1692
1693 static HRESULT HTMLElement_get_dispid(DispatchEx *dispex, BSTR name,
1694         DWORD grfdex, DISPID *pid)
1695 {
1696     HTMLElement *This = impl_from_DispatchEx(dispex);
1697
1698     if(This->node.vtbl->get_dispid)
1699         return This->node.vtbl->get_dispid(&This->node, name, grfdex, pid);
1700
1701     return DISP_E_UNKNOWNNAME;
1702 }
1703
1704 static HRESULT HTMLElement_invoke(DispatchEx *dispex, DISPID id, LCID lcid,
1705         WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei,
1706         IServiceProvider *caller)
1707 {
1708     HTMLElement *This = impl_from_DispatchEx(dispex);
1709
1710     if(This->node.vtbl->invoke)
1711         return This->node.vtbl->invoke(&This->node, id, lcid, flags,
1712                 params, res, ei, caller);
1713
1714     ERR("(%p): element has no invoke method\n", This);
1715     return E_NOTIMPL;
1716 }
1717
1718 static HRESULT HTMLElement_populate_props(DispatchEx *dispex)
1719 {
1720     HTMLElement *This = impl_from_DispatchEx(dispex);
1721     nsIDOMNamedNodeMap *attrs;
1722     nsIDOMNode *node;
1723     nsAString nsstr;
1724     const PRUnichar *str;
1725     BSTR name;
1726     VARIANT value;
1727     unsigned i;
1728     UINT32 len;
1729     DISPID id;
1730     nsresult nsres;
1731     HRESULT hres;
1732
1733     if(!This->nselem)
1734         return S_FALSE;
1735
1736     nsres = nsIDOMHTMLElement_GetAttributes(This->nselem, &attrs);
1737     if(NS_FAILED(nsres))
1738         return E_FAIL;
1739
1740     nsres = nsIDOMNamedNodeMap_GetLength(attrs, &len);
1741     if(NS_FAILED(nsres)) {
1742         nsIDOMNamedNodeMap_Release(attrs);
1743         return E_FAIL;
1744     }
1745
1746     nsAString_Init(&nsstr, NULL);
1747     for(i=0; i<len; i++) {
1748         nsres = nsIDOMNamedNodeMap_Item(attrs, i, &node);
1749         if(NS_FAILED(nsres))
1750             continue;
1751
1752         nsres = nsIDOMNode_GetNodeName(node, &nsstr);
1753         if(NS_FAILED(nsres)) {
1754             nsIDOMNode_Release(node);
1755             continue;
1756         }
1757
1758         nsAString_GetData(&nsstr, &str);
1759         name = SysAllocString(str);
1760         if(!name) {
1761             nsIDOMNode_Release(node);
1762             continue;
1763         }
1764
1765         hres = IDispatchEx_GetDispID(&dispex->IDispatchEx_iface, name, fdexNameCaseInsensitive, &id);
1766         if(hres != DISP_E_UNKNOWNNAME) {
1767             nsIDOMNode_Release(node);
1768             SysFreeString(name);
1769             continue;
1770         }
1771
1772         nsres = nsIDOMNode_GetNodeValue(node, &nsstr);
1773         nsIDOMNode_Release(node);
1774         if(NS_FAILED(nsres)) {
1775             SysFreeString(name);
1776             continue;
1777         }
1778
1779         nsAString_GetData(&nsstr, &str);
1780         V_VT(&value) = VT_BSTR;
1781         if(*str) {
1782             V_BSTR(&value) = SysAllocString(str);
1783             if(!V_BSTR(&value)) {
1784                 SysFreeString(name);
1785                 continue;
1786             }
1787         } else
1788             V_BSTR(&value) = NULL;
1789
1790         IHTMLElement_setAttribute(&This->IHTMLElement_iface, name, value, 0);
1791         SysFreeString(name);
1792         VariantClear(&value);
1793     }
1794     nsAString_Finish(&nsstr);
1795
1796     nsIDOMNamedNodeMap_Release(attrs);
1797     return S_OK;
1798 }
1799
1800 static const tid_t HTMLElement_iface_tids[] = {
1801     HTMLELEMENT_TIDS,
1802     0
1803 };
1804
1805 static dispex_static_data_vtbl_t HTMLElement_dispex_vtbl = {
1806     NULL,
1807     HTMLElement_get_dispid,
1808     HTMLElement_invoke,
1809     HTMLElement_populate_props
1810 };
1811
1812 static dispex_static_data_t HTMLElement_dispex = {
1813     &HTMLElement_dispex_vtbl,
1814     DispHTMLUnknownElement_tid,
1815     NULL,
1816     HTMLElement_iface_tids
1817 };
1818
1819 void HTMLElement_Init(HTMLElement *This, HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, dispex_static_data_t *dispex_data)
1820 {
1821     This->IHTMLElement_iface.lpVtbl = &HTMLElementVtbl;
1822
1823     HTMLElement2_Init(This);
1824     HTMLElement3_Init(This);
1825
1826     if(dispex_data && !dispex_data->vtbl)
1827         dispex_data->vtbl = &HTMLElement_dispex_vtbl;
1828     init_dispex(&This->node.dispex, (IUnknown*)&This->IHTMLElement_iface,
1829             dispex_data ? dispex_data : &HTMLElement_dispex);
1830
1831     if(nselem) {
1832         HTMLDOMNode_Init(doc, &This->node, (nsIDOMNode*)nselem);
1833
1834         /* No AddRef, share reference with HTMLDOMNode */
1835         assert((nsIDOMNode*)nselem == This->node.nsnode);
1836         This->nselem = nselem;
1837     }
1838
1839     ConnectionPointContainer_Init(&This->cp_container, (IUnknown*)&This->IHTMLElement_iface);
1840 }
1841
1842 HRESULT HTMLElement_Create(HTMLDocumentNode *doc, nsIDOMNode *nsnode, BOOL use_generic, HTMLElement **ret)
1843 {
1844     nsIDOMHTMLElement *nselem;
1845     nsAString class_name_str;
1846     const PRUnichar *class_name;
1847     const tag_desc_t *tag;
1848     HTMLElement *elem;
1849     nsresult nsres;
1850     HRESULT hres;
1851
1852     nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMHTMLElement, (void**)&nselem);
1853     if(NS_FAILED(nsres))
1854         return E_FAIL;
1855
1856     nsAString_Init(&class_name_str, NULL);
1857     nsIDOMHTMLElement_GetTagName(nselem, &class_name_str);
1858
1859     nsAString_GetData(&class_name_str, &class_name);
1860
1861     tag = get_tag_desc(class_name);
1862     if(tag) {
1863         hres = tag->constructor(doc, nselem, &elem);
1864     }else if(use_generic) {
1865         hres = HTMLGenericElement_Create(doc, nselem, &elem);
1866     }else {
1867         elem = heap_alloc_zero(sizeof(HTMLElement));
1868         if(elem) {
1869             HTMLElement_Init(elem, doc, nselem, &HTMLElement_dispex);
1870             elem->node.vtbl = &HTMLElementImplVtbl;
1871             hres = S_OK;
1872         }else {
1873             hres = E_OUTOFMEMORY;
1874         }
1875     }
1876
1877     TRACE("%s ret %p\n", debugstr_w(class_name), elem);
1878
1879     nsIDOMHTMLElement_Release(nselem);
1880     nsAString_Finish(&class_name_str);
1881     if(FAILED(hres))
1882         return hres;
1883
1884     *ret = elem;
1885     return S_OK;
1886 }
1887
1888 HRESULT get_elem(HTMLDocumentNode *doc, nsIDOMElement *nselem, HTMLElement **ret)
1889 {
1890     HTMLDOMNode *node;
1891     HRESULT hres;
1892
1893     hres = get_node(doc, (nsIDOMNode*)nselem, TRUE, &node);
1894     if(FAILED(hres))
1895         return hres;
1896
1897     *ret = impl_from_HTMLDOMNode(node);
1898     return S_OK;
1899 }
1900
1901 /* interface IHTMLFiltersCollection */
1902 static HRESULT WINAPI HTMLFiltersCollection_QueryInterface(IHTMLFiltersCollection *iface, REFIID riid, void **ppv)
1903 {
1904     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1905
1906     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppv );
1907
1908     if(IsEqualGUID(&IID_IUnknown, riid)) {
1909         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1910         *ppv = &This->IHTMLFiltersCollection_iface;
1911     }else if(IsEqualGUID(&IID_IHTMLFiltersCollection, riid)) {
1912         TRACE("(%p)->(IID_IHTMLFiltersCollection %p)\n", This, ppv);
1913         *ppv = &This->IHTMLFiltersCollection_iface;
1914     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1915         return *ppv ? S_OK : E_NOINTERFACE;
1916     }
1917
1918     if(*ppv) {
1919         IUnknown_AddRef((IUnknown*)*ppv);
1920         return S_OK;
1921     }
1922
1923     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1924     return E_NOINTERFACE;
1925 }
1926
1927 static ULONG WINAPI HTMLFiltersCollection_AddRef(IHTMLFiltersCollection *iface)
1928 {
1929     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1930     LONG ref = InterlockedIncrement(&This->ref);
1931
1932     TRACE("(%p) ref=%d\n", This, ref);
1933
1934     return ref;
1935 }
1936
1937 static ULONG WINAPI HTMLFiltersCollection_Release(IHTMLFiltersCollection *iface)
1938 {
1939     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1940     LONG ref = InterlockedDecrement(&This->ref);
1941
1942     TRACE("(%p) ref=%d\n", This, ref);
1943
1944     if(!ref)
1945     {
1946         heap_free(This);
1947     }
1948
1949     return ref;
1950 }
1951
1952 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfoCount(IHTMLFiltersCollection *iface, UINT *pctinfo)
1953 {
1954     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1955     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1956 }
1957
1958 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfo(IHTMLFiltersCollection *iface,
1959                                     UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1960 {
1961     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1962     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1963 }
1964
1965 static HRESULT WINAPI HTMLFiltersCollection_GetIDsOfNames(IHTMLFiltersCollection *iface,
1966                                     REFIID riid, LPOLESTR *rgszNames, UINT cNames,
1967                                     LCID lcid, DISPID *rgDispId)
1968 {
1969     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1970     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1971             lcid, rgDispId);
1972 }
1973
1974 static HRESULT WINAPI HTMLFiltersCollection_Invoke(IHTMLFiltersCollection *iface, DISPID dispIdMember, REFIID riid,
1975                                     LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1976                                     EXCEPINFO *pExcepInfo, UINT *puArgErr)
1977 {
1978     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1979     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1980             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1981 }
1982
1983 static HRESULT WINAPI HTMLFiltersCollection_get_length(IHTMLFiltersCollection *iface, LONG *p)
1984 {
1985     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1986
1987     if(!p)
1988         return E_POINTER;
1989
1990     FIXME("(%p)->(%p) Always returning 0\n", This, p);
1991     *p = 0;
1992
1993     return S_OK;
1994 }
1995
1996 static HRESULT WINAPI HTMLFiltersCollection_get__newEnum(IHTMLFiltersCollection *iface, IUnknown **p)
1997 {
1998     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1999     FIXME("(%p)->(%p)\n", This, p);
2000     return E_NOTIMPL;
2001 }
2002
2003 static HRESULT WINAPI HTMLFiltersCollection_item(IHTMLFiltersCollection *iface, VARIANT *pvarIndex, VARIANT *pvarResult)
2004 {
2005     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
2006     FIXME("(%p)->(%p, %p)\n", This, pvarIndex, pvarResult);
2007     return E_NOTIMPL;
2008 }
2009
2010 static const IHTMLFiltersCollectionVtbl HTMLFiltersCollectionVtbl = {
2011     HTMLFiltersCollection_QueryInterface,
2012     HTMLFiltersCollection_AddRef,
2013     HTMLFiltersCollection_Release,
2014     HTMLFiltersCollection_GetTypeInfoCount,
2015     HTMLFiltersCollection_GetTypeInfo,
2016     HTMLFiltersCollection_GetIDsOfNames,
2017     HTMLFiltersCollection_Invoke,
2018     HTMLFiltersCollection_get_length,
2019     HTMLFiltersCollection_get__newEnum,
2020     HTMLFiltersCollection_item
2021 };
2022
2023 static HRESULT HTMLFiltersCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
2024 {
2025     WCHAR *ptr;
2026     int idx = 0;
2027
2028     for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
2029         idx = idx*10 + (*ptr-'0');
2030     if(*ptr)
2031         return DISP_E_UNKNOWNNAME;
2032
2033     *dispid = MSHTML_DISPID_CUSTOM_MIN + idx;
2034     TRACE("ret %x\n", *dispid);
2035     return S_OK;
2036 }
2037
2038 static HRESULT HTMLFiltersCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
2039         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
2040 {
2041     TRACE("(%p)->(%x %x %x %p %p %p)\n", dispex, id, lcid, flags, params, res, ei);
2042
2043     V_VT(res) = VT_DISPATCH;
2044     V_DISPATCH(res) = NULL;
2045
2046     FIXME("always returning NULL\n");
2047
2048     return S_OK;
2049 }
2050
2051 static const dispex_static_data_vtbl_t HTMLFiltersCollection_dispex_vtbl = {
2052     NULL,
2053     HTMLFiltersCollection_get_dispid,
2054     HTMLFiltersCollection_invoke,
2055     NULL
2056 };
2057
2058 static const tid_t HTMLFiltersCollection_iface_tids[] = {
2059     IHTMLFiltersCollection_tid,
2060     0
2061 };
2062 static dispex_static_data_t HTMLFiltersCollection_dispex = {
2063     &HTMLFiltersCollection_dispex_vtbl,
2064     IHTMLFiltersCollection_tid,
2065     NULL,
2066     HTMLFiltersCollection_iface_tids
2067 };
2068
2069 static IHTMLFiltersCollection *HTMLFiltersCollection_Create(void)
2070 {
2071     HTMLFiltersCollection *ret = heap_alloc(sizeof(HTMLFiltersCollection));
2072
2073     ret->IHTMLFiltersCollection_iface.lpVtbl = &HTMLFiltersCollectionVtbl;
2074     ret->ref = 1;
2075
2076     init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLFiltersCollection_iface,
2077             &HTMLFiltersCollection_dispex);
2078
2079     return &ret->IHTMLFiltersCollection_iface;
2080 }
2081
2082 /* interface IHTMLAttributeCollection */
2083 static inline HTMLAttributeCollection *impl_from_IHTMLAttributeCollection(IHTMLAttributeCollection *iface)
2084 {
2085     return CONTAINING_RECORD(iface, HTMLAttributeCollection, IHTMLAttributeCollection_iface);
2086 }
2087
2088 static HRESULT WINAPI HTMLAttributeCollection_QueryInterface(IHTMLAttributeCollection *iface, REFIID riid, void **ppv)
2089 {
2090     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2091
2092     *ppv = NULL;
2093
2094     if(IsEqualGUID(&IID_IUnknown, riid)) {
2095         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
2096         *ppv = &This->IHTMLAttributeCollection_iface;
2097     }else if(IsEqualGUID(&IID_IHTMLAttributeCollection, riid)) {
2098         TRACE("(%p)->(IID_IHTMLAttributeCollection %p)\n", This, ppv);
2099         *ppv = &This->IHTMLAttributeCollection_iface;
2100     }else if(IsEqualGUID(&IID_IHTMLAttributeCollection2, riid)) {
2101         TRACE("(%p)->(IID_IHTMLAttributeCollection2 %p)\n", This, ppv);
2102         *ppv = &This->IHTMLAttributeCollection2_iface;
2103     }else if(IsEqualGUID(&IID_IHTMLAttributeCollection3, riid)) {
2104         TRACE("(%p)->(IID_IHTMLAttributeCollection3 %p)\n", This, ppv);
2105         *ppv = &This->IHTMLAttributeCollection3_iface;
2106     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
2107         return *ppv ? S_OK : E_NOINTERFACE;
2108     }
2109
2110     if(*ppv) {
2111         IUnknown_AddRef((IUnknown*)*ppv);
2112         return S_OK;
2113     }
2114
2115     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2116     return E_NOINTERFACE;
2117 }
2118
2119 static ULONG WINAPI HTMLAttributeCollection_AddRef(IHTMLAttributeCollection *iface)
2120 {
2121     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2122     LONG ref = InterlockedIncrement(&This->ref);
2123
2124     TRACE("(%p) ref=%d\n", This, ref);
2125
2126     return ref;
2127 }
2128
2129 static ULONG WINAPI HTMLAttributeCollection_Release(IHTMLAttributeCollection *iface)
2130 {
2131     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2132     LONG ref = InterlockedDecrement(&This->ref);
2133
2134     TRACE("(%p) ref=%d\n", This, ref);
2135
2136     if(!ref) {
2137         while(!list_empty(&This->attrs)) {
2138             HTMLDOMAttribute *attr = LIST_ENTRY(list_head(&This->attrs), HTMLDOMAttribute, entry);
2139
2140             list_remove(&attr->entry);
2141             attr->elem = NULL;
2142             IHTMLDOMAttribute_Release(&attr->IHTMLDOMAttribute_iface);
2143         }
2144
2145         heap_free(This);
2146     }
2147
2148     return ref;
2149 }
2150
2151 static HRESULT WINAPI HTMLAttributeCollection_GetTypeInfoCount(IHTMLAttributeCollection *iface, UINT *pctinfo)
2152 {
2153     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2154     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2155 }
2156
2157 static HRESULT WINAPI HTMLAttributeCollection_GetTypeInfo(IHTMLAttributeCollection *iface, UINT iTInfo,
2158         LCID lcid, ITypeInfo **ppTInfo)
2159 {
2160     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2161     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2162 }
2163
2164 static HRESULT WINAPI HTMLAttributeCollection_GetIDsOfNames(IHTMLAttributeCollection *iface, REFIID riid,
2165         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2166 {
2167     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2168     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2169             lcid, rgDispId);
2170 }
2171
2172 static HRESULT WINAPI HTMLAttributeCollection_Invoke(IHTMLAttributeCollection *iface, DISPID dispIdMember,
2173         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
2174         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
2175 {
2176     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2177     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2178             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2179 }
2180
2181 static HRESULT get_attr_dispid_by_idx(HTMLAttributeCollection *This, LONG *idx, DISPID *dispid)
2182 {
2183     IDispatchEx *dispex = &This->elem->node.dispex.IDispatchEx_iface;
2184     DISPID id = DISPID_STARTENUM;
2185     LONG len = -1;
2186     HRESULT hres;
2187
2188     FIXME("filter non-enumerable attributes out\n");
2189
2190     while(1) {
2191         hres = IDispatchEx_GetNextDispID(dispex, fdexEnumAll, id, &id);
2192         if(FAILED(hres))
2193             return hres;
2194         else if(hres == S_FALSE)
2195             break;
2196
2197         len++;
2198         if(len == *idx)
2199             break;
2200     }
2201
2202     if(dispid) {
2203         *dispid = id;
2204         return *idx==len ? S_OK : DISP_E_UNKNOWNNAME;
2205     }
2206
2207     *idx = len+1;
2208     return S_OK;
2209 }
2210
2211 static inline HRESULT get_attr_dispid_by_name(HTMLAttributeCollection *This, BSTR name, DISPID *id)
2212 {
2213     HRESULT hres;
2214
2215     if(name[0]>='0' && name[0]<='9') {
2216         WCHAR *end_ptr;
2217         LONG idx;
2218
2219         idx = strtoulW(name, &end_ptr, 10);
2220         if(!*end_ptr) {
2221             hres = get_attr_dispid_by_idx(This, &idx, id);
2222             if(SUCCEEDED(hres))
2223                 return hres;
2224         }
2225     }
2226
2227     if(!This->elem) {
2228         WARN("NULL elem\n");
2229         return E_UNEXPECTED;
2230     }
2231
2232     hres = IDispatchEx_GetDispID(&This->elem->node.dispex.IDispatchEx_iface,
2233             name, fdexNameCaseInsensitive, id);
2234     return hres;
2235 }
2236
2237 static inline HRESULT get_domattr(HTMLAttributeCollection *This, DISPID id, LONG *list_pos, HTMLDOMAttribute **attr)
2238 {
2239     HTMLDOMAttribute *iter;
2240     LONG pos = 0;
2241     HRESULT hres;
2242
2243     *attr = NULL;
2244     LIST_FOR_EACH_ENTRY(iter, &This->attrs, HTMLDOMAttribute, entry) {
2245         if(iter->dispid == id) {
2246             *attr = iter;
2247             break;
2248         }
2249         pos++;
2250     }
2251
2252     if(!*attr) {
2253         if(!This->elem) {
2254             WARN("NULL elem\n");
2255             return E_UNEXPECTED;
2256         }
2257
2258         hres = HTMLDOMAttribute_Create(NULL, This->elem, id, attr);
2259         if(FAILED(hres))
2260             return hres;
2261     }
2262
2263     IHTMLDOMAttribute_AddRef(&(*attr)->IHTMLDOMAttribute_iface);
2264     if(list_pos)
2265         *list_pos = pos;
2266     return S_OK;
2267 }
2268
2269 static HRESULT WINAPI HTMLAttributeCollection_get_length(IHTMLAttributeCollection *iface, LONG *p)
2270 {
2271     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2272     HRESULT hres;
2273
2274     TRACE("(%p)->(%p)\n", This, p);
2275
2276     *p = -1;
2277     hres = get_attr_dispid_by_idx(This, p, NULL);
2278     return hres;
2279 }
2280
2281 static HRESULT WINAPI HTMLAttributeCollection__newEnum(IHTMLAttributeCollection *iface, IUnknown **p)
2282 {
2283     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2284     FIXME("(%p)->(%p)\n", This, p);
2285     return E_NOTIMPL;
2286 }
2287
2288 static HRESULT WINAPI HTMLAttributeCollection_item(IHTMLAttributeCollection *iface, VARIANT *name, IDispatch **ppItem)
2289 {
2290     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2291     HTMLDOMAttribute *attr;
2292     DISPID id;
2293     HRESULT hres;
2294
2295     TRACE("(%p)->(%s %p)\n", This, debugstr_variant(name), ppItem);
2296
2297     switch(V_VT(name)) {
2298     case VT_I4:
2299         hres = get_attr_dispid_by_idx(This, &V_I4(name), &id);
2300         break;
2301     case VT_BSTR:
2302         hres = get_attr_dispid_by_name(This, V_BSTR(name), &id);
2303         break;
2304     default:
2305         FIXME("unsupported name %s\n", debugstr_variant(name));
2306         hres = E_NOTIMPL;
2307     }
2308     if(hres == DISP_E_UNKNOWNNAME)
2309         return E_INVALIDARG;
2310     if(FAILED(hres))
2311         return hres;
2312
2313     hres = get_domattr(This, id, NULL, &attr);
2314     if(FAILED(hres))
2315         return hres;
2316
2317     *ppItem = (IDispatch*)&attr->IHTMLDOMAttribute_iface;
2318     return S_OK;
2319 }
2320
2321 static const IHTMLAttributeCollectionVtbl HTMLAttributeCollectionVtbl = {
2322     HTMLAttributeCollection_QueryInterface,
2323     HTMLAttributeCollection_AddRef,
2324     HTMLAttributeCollection_Release,
2325     HTMLAttributeCollection_GetTypeInfoCount,
2326     HTMLAttributeCollection_GetTypeInfo,
2327     HTMLAttributeCollection_GetIDsOfNames,
2328     HTMLAttributeCollection_Invoke,
2329     HTMLAttributeCollection_get_length,
2330     HTMLAttributeCollection__newEnum,
2331     HTMLAttributeCollection_item
2332 };
2333
2334 static inline HTMLAttributeCollection *impl_from_IHTMLAttributeCollection2(IHTMLAttributeCollection2 *iface)
2335 {
2336     return CONTAINING_RECORD(iface, HTMLAttributeCollection, IHTMLAttributeCollection2_iface);
2337 }
2338
2339 static HRESULT WINAPI HTMLAttributeCollection2_QueryInterface(IHTMLAttributeCollection2 *iface, REFIID riid, void **ppv)
2340 {
2341     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2342     return IHTMLAttributeCollection_QueryInterface(&This->IHTMLAttributeCollection_iface, riid, ppv);
2343 }
2344
2345 static ULONG WINAPI HTMLAttributeCollection2_AddRef(IHTMLAttributeCollection2 *iface)
2346 {
2347     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2348     return IHTMLAttributeCollection_AddRef(&This->IHTMLAttributeCollection_iface);
2349 }
2350
2351 static ULONG WINAPI HTMLAttributeCollection2_Release(IHTMLAttributeCollection2 *iface)
2352 {
2353     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2354     return IHTMLAttributeCollection_Release(&This->IHTMLAttributeCollection_iface);
2355 }
2356
2357 static HRESULT WINAPI HTMLAttributeCollection2_GetTypeInfoCount(IHTMLAttributeCollection2 *iface, UINT *pctinfo)
2358 {
2359     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2360     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2361 }
2362
2363 static HRESULT WINAPI HTMLAttributeCollection2_GetTypeInfo(IHTMLAttributeCollection2 *iface, UINT iTInfo,
2364         LCID lcid, ITypeInfo **ppTInfo)
2365 {
2366     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2367     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2368 }
2369
2370 static HRESULT WINAPI HTMLAttributeCollection2_GetIDsOfNames(IHTMLAttributeCollection2 *iface, REFIID riid,
2371         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2372 {
2373     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2374     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2375             lcid, rgDispId);
2376 }
2377
2378 static HRESULT WINAPI HTMLAttributeCollection2_Invoke(IHTMLAttributeCollection2 *iface, DISPID dispIdMember,
2379         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
2380         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
2381 {
2382     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2383     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2384             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2385 }
2386
2387 static HRESULT WINAPI HTMLAttributeCollection2_getNamedItem(IHTMLAttributeCollection2 *iface, BSTR bstrName,
2388         IHTMLDOMAttribute **newretNode)
2389 {
2390     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2391     HTMLDOMAttribute *attr;
2392     DISPID id;
2393     HRESULT hres;
2394
2395     TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrName), newretNode);
2396
2397     hres = get_attr_dispid_by_name(This, bstrName, &id);
2398     if(hres == DISP_E_UNKNOWNNAME) {
2399         *newretNode = NULL;
2400         return S_OK;
2401     } else if(FAILED(hres)) {
2402         return hres;
2403     }
2404
2405     hres = get_domattr(This, id, NULL, &attr);
2406     if(FAILED(hres))
2407         return hres;
2408
2409     *newretNode = &attr->IHTMLDOMAttribute_iface;
2410     return S_OK;
2411 }
2412
2413 static HRESULT WINAPI HTMLAttributeCollection2_setNamedItem(IHTMLAttributeCollection2 *iface,
2414         IHTMLDOMAttribute *ppNode, IHTMLDOMAttribute **newretNode)
2415 {
2416     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2417     FIXME("(%p)->(%p %p)\n", This, ppNode, newretNode);
2418     return E_NOTIMPL;
2419 }
2420
2421 static HRESULT WINAPI HTMLAttributeCollection2_removeNamedItem(IHTMLAttributeCollection2 *iface,
2422         BSTR bstrName, IHTMLDOMAttribute **newretNode)
2423 {
2424     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2425     FIXME("(%p)->(%s %p)\n", This, debugstr_w(bstrName), newretNode);
2426     return E_NOTIMPL;
2427 }
2428
2429 static const IHTMLAttributeCollection2Vtbl HTMLAttributeCollection2Vtbl = {
2430     HTMLAttributeCollection2_QueryInterface,
2431     HTMLAttributeCollection2_AddRef,
2432     HTMLAttributeCollection2_Release,
2433     HTMLAttributeCollection2_GetTypeInfoCount,
2434     HTMLAttributeCollection2_GetTypeInfo,
2435     HTMLAttributeCollection2_GetIDsOfNames,
2436     HTMLAttributeCollection2_Invoke,
2437     HTMLAttributeCollection2_getNamedItem,
2438     HTMLAttributeCollection2_setNamedItem,
2439     HTMLAttributeCollection2_removeNamedItem
2440 };
2441
2442 static inline HTMLAttributeCollection *impl_from_IHTMLAttributeCollection3(IHTMLAttributeCollection3 *iface)
2443 {
2444     return CONTAINING_RECORD(iface, HTMLAttributeCollection, IHTMLAttributeCollection3_iface);
2445 }
2446
2447 static HRESULT WINAPI HTMLAttributeCollection3_QueryInterface(IHTMLAttributeCollection3 *iface, REFIID riid, void **ppv)
2448 {
2449     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2450     return IHTMLAttributeCollection_QueryInterface(&This->IHTMLAttributeCollection_iface, riid, ppv);
2451 }
2452
2453 static ULONG WINAPI HTMLAttributeCollection3_AddRef(IHTMLAttributeCollection3 *iface)
2454 {
2455     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2456     return IHTMLAttributeCollection_AddRef(&This->IHTMLAttributeCollection_iface);
2457 }
2458
2459 static ULONG WINAPI HTMLAttributeCollection3_Release(IHTMLAttributeCollection3 *iface)
2460 {
2461     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2462     return IHTMLAttributeCollection_Release(&This->IHTMLAttributeCollection_iface);
2463 }
2464
2465 static HRESULT WINAPI HTMLAttributeCollection3_GetTypeInfoCount(IHTMLAttributeCollection3 *iface, UINT *pctinfo)
2466 {
2467     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2468     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2469 }
2470
2471 static HRESULT WINAPI HTMLAttributeCollection3_GetTypeInfo(IHTMLAttributeCollection3 *iface, UINT iTInfo,
2472         LCID lcid, ITypeInfo **ppTInfo)
2473 {
2474     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2475     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2476 }
2477
2478 static HRESULT WINAPI HTMLAttributeCollection3_GetIDsOfNames(IHTMLAttributeCollection3 *iface, REFIID riid,
2479         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2480 {
2481     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2482     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2483             lcid, rgDispId);
2484 }
2485
2486 static HRESULT WINAPI HTMLAttributeCollection3_Invoke(IHTMLAttributeCollection3 *iface, DISPID dispIdMember,
2487         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
2488         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
2489 {
2490     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2491     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2492             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2493 }
2494
2495 static HRESULT WINAPI HTMLAttributeCollection3_getNamedItem(IHTMLAttributeCollection3 *iface, BSTR bstrName,
2496         IHTMLDOMAttribute **ppNodeOut)
2497 {
2498     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2499     return IHTMLAttributeCollection2_getNamedItem(&This->IHTMLAttributeCollection2_iface, bstrName, ppNodeOut);
2500 }
2501
2502 static HRESULT WINAPI HTMLAttributeCollection3_setNamedItem(IHTMLAttributeCollection3 *iface,
2503         IHTMLDOMAttribute *pNodeIn, IHTMLDOMAttribute **ppNodeOut)
2504 {
2505     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2506     FIXME("(%p)->(%p %p)\n", This, pNodeIn, ppNodeOut);
2507     return E_NOTIMPL;
2508 }
2509
2510 static HRESULT WINAPI HTMLAttributeCollection3_removeNamedItem(IHTMLAttributeCollection3 *iface,
2511         BSTR bstrName, IHTMLDOMAttribute **ppNodeOut)
2512 {
2513     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2514     FIXME("(%p)->(%s %p)\n", This, debugstr_w(bstrName), ppNodeOut);
2515     return E_NOTIMPL;
2516 }
2517
2518 static HRESULT WINAPI HTMLAttributeCollection3_item(IHTMLAttributeCollection3 *iface, LONG index, IHTMLDOMAttribute **ppNodeOut)
2519 {
2520     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2521     HTMLDOMAttribute *attr;
2522     DISPID id;
2523     HRESULT hres;
2524
2525     TRACE("(%p)->(%d %p)\n", This, index, ppNodeOut);
2526
2527     hres = get_attr_dispid_by_idx(This, &index, &id);
2528     if(hres == DISP_E_UNKNOWNNAME)
2529         return E_INVALIDARG;
2530     if(FAILED(hres))
2531         return hres;
2532
2533     hres = get_domattr(This, id, NULL, &attr);
2534     if(FAILED(hres))
2535         return hres;
2536
2537     *ppNodeOut = &attr->IHTMLDOMAttribute_iface;
2538     return S_OK;
2539 }
2540
2541 static HRESULT WINAPI HTMLAttributeCollection3_get_length(IHTMLAttributeCollection3 *iface, LONG *p)
2542 {
2543     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2544     return IHTMLAttributeCollection_get_length(&This->IHTMLAttributeCollection_iface, p);
2545 }
2546
2547 static const IHTMLAttributeCollection3Vtbl HTMLAttributeCollection3Vtbl = {
2548     HTMLAttributeCollection3_QueryInterface,
2549     HTMLAttributeCollection3_AddRef,
2550     HTMLAttributeCollection3_Release,
2551     HTMLAttributeCollection3_GetTypeInfoCount,
2552     HTMLAttributeCollection3_GetTypeInfo,
2553     HTMLAttributeCollection3_GetIDsOfNames,
2554     HTMLAttributeCollection3_Invoke,
2555     HTMLAttributeCollection3_getNamedItem,
2556     HTMLAttributeCollection3_setNamedItem,
2557     HTMLAttributeCollection3_removeNamedItem,
2558     HTMLAttributeCollection3_item,
2559     HTMLAttributeCollection3_get_length
2560 };
2561
2562 static inline HTMLAttributeCollection *HTMLAttributeCollection_from_DispatchEx(DispatchEx *iface)
2563 {
2564     return CONTAINING_RECORD(iface, HTMLAttributeCollection, dispex);
2565 }
2566
2567 static HRESULT HTMLAttributeCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
2568 {
2569     HTMLAttributeCollection *This = HTMLAttributeCollection_from_DispatchEx(dispex);
2570     HTMLDOMAttribute *attr;
2571     LONG pos;
2572     HRESULT hres;
2573
2574     TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(name), flags, dispid);
2575
2576     hres = get_attr_dispid_by_name(This, name, dispid);
2577     if(FAILED(hres))
2578         return hres;
2579
2580     hres = get_domattr(This, *dispid, &pos, &attr);
2581     if(FAILED(hres))
2582         return hres;
2583     IHTMLDOMAttribute_Release(&attr->IHTMLDOMAttribute_iface);
2584
2585     *dispid = MSHTML_DISPID_CUSTOM_MIN+pos;
2586     return S_OK;
2587 }
2588
2589 static HRESULT HTMLAttributeCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid,
2590         WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
2591 {
2592     HTMLAttributeCollection *This = HTMLAttributeCollection_from_DispatchEx(dispex);
2593
2594     TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
2595
2596     switch(flags) {
2597     case DISPATCH_PROPERTYGET: {
2598         HTMLDOMAttribute *iter;
2599         DWORD pos;
2600
2601         pos = id-MSHTML_DISPID_CUSTOM_MIN;
2602
2603         LIST_FOR_EACH_ENTRY(iter, &This->attrs, HTMLDOMAttribute, entry) {
2604             if(!pos) {
2605                 IHTMLDOMAttribute_AddRef(&iter->IHTMLDOMAttribute_iface);
2606                 V_VT(res) = VT_DISPATCH;
2607                 V_DISPATCH(res) = (IDispatch*)&iter->IHTMLDOMAttribute_iface;
2608                 return S_OK;
2609             }
2610             pos--;
2611         }
2612
2613         WARN("invalid arg\n");
2614         return E_INVALIDARG;
2615     }
2616
2617     default:
2618         FIXME("unimplemented flags %x\n", flags);
2619         return E_NOTIMPL;
2620     }
2621 }
2622
2623 static const dispex_static_data_vtbl_t HTMLAttributeCollection_dispex_vtbl = {
2624     NULL,
2625     HTMLAttributeCollection_get_dispid,
2626     HTMLAttributeCollection_invoke,
2627     NULL
2628 };
2629
2630 static const tid_t HTMLAttributeCollection_iface_tids[] = {
2631     IHTMLAttributeCollection_tid,
2632     IHTMLAttributeCollection2_tid,
2633     IHTMLAttributeCollection3_tid,
2634     0
2635 };
2636
2637 static dispex_static_data_t HTMLAttributeCollection_dispex = {
2638     &HTMLAttributeCollection_dispex_vtbl,
2639     DispHTMLAttributeCollection_tid,
2640     NULL,
2641     HTMLAttributeCollection_iface_tids
2642 };
2643
2644 HRESULT HTMLElement_get_attr_col(HTMLDOMNode *iface, HTMLAttributeCollection **ac)
2645 {
2646     HTMLElement *This = impl_from_HTMLDOMNode(iface);
2647
2648     if(This->attrs) {
2649         IHTMLAttributeCollection_AddRef(&This->attrs->IHTMLAttributeCollection_iface);
2650         *ac = This->attrs;
2651         return S_OK;
2652     }
2653
2654     This->attrs = heap_alloc_zero(sizeof(HTMLAttributeCollection));
2655     if(!This->attrs)
2656         return E_OUTOFMEMORY;
2657
2658     This->attrs->IHTMLAttributeCollection_iface.lpVtbl = &HTMLAttributeCollectionVtbl;
2659     This->attrs->IHTMLAttributeCollection2_iface.lpVtbl = &HTMLAttributeCollection2Vtbl;
2660     This->attrs->IHTMLAttributeCollection3_iface.lpVtbl = &HTMLAttributeCollection3Vtbl;
2661     This->attrs->ref = 2;
2662
2663     This->attrs->elem = This;
2664     list_init(&This->attrs->attrs);
2665     init_dispex(&This->attrs->dispex, (IUnknown*)&This->attrs->IHTMLAttributeCollection_iface,
2666             &HTMLAttributeCollection_dispex);
2667
2668     *ac = This->attrs;
2669     return S_OK;
2670 }