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