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