mshtml: Added IDispatchEx support to HTMLInputElement.
[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     NULL,
1287     DispHTMLUnknownElement_tid,
1288     NULL,
1289     {
1290         IHTMLDOMNode_tid,
1291         IHTMLDOMNode2_tid,
1292         IHTMLElement_tid,
1293         IHTMLElement2_tid,
1294         0
1295     }
1296 };
1297
1298 void HTMLElement_Init(HTMLElement *This)
1299 {
1300     This->node.vtbl = &HTMLElementImplVtbl;
1301     This->lpHTMLElementVtbl = &HTMLElementVtbl;
1302
1303     ConnectionPointContainer_Init(&This->cp_container, (IUnknown*)HTMLELEM(This));
1304
1305     HTMLElement2_Init(This);
1306 }
1307
1308 HTMLElement *HTMLElement_Create(nsIDOMNode *nsnode)
1309 {
1310     nsIDOMHTMLElement *nselem;
1311     HTMLElement *ret = NULL;
1312     nsAString class_name_str;
1313     const PRUnichar *class_name;
1314     nsresult nsres;
1315
1316     static const WCHAR wszA[]        = {'A',0};
1317     static const WCHAR wszBODY[]     = {'B','O','D','Y',0};
1318     static const WCHAR wszINPUT[]    = {'I','N','P','U','T',0};
1319     static const WCHAR wszOPTION[]   = {'O','P','T','I','O','N',0};
1320     static const WCHAR wszSCRIPT[]   = {'S','C','R','I','P','T',0};
1321     static const WCHAR wszSELECT[]   = {'S','E','L','E','C','T',0};
1322     static const WCHAR wszTABLE[]    = {'T','A','B','L','E',0};
1323     static const WCHAR wszTEXTAREA[] = {'T','E','X','T','A','R','E','A',0};
1324
1325     nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMHTMLElement, (void**)&nselem);
1326     if(NS_FAILED(nsres))
1327         return NULL;
1328
1329     nsAString_Init(&class_name_str, NULL);
1330     nsIDOMHTMLElement_GetTagName(nselem, &class_name_str);
1331
1332     nsAString_GetData(&class_name_str, &class_name);
1333
1334     if(!strcmpW(class_name, wszA))
1335         ret = HTMLAnchorElement_Create(nselem);
1336     else if(!strcmpW(class_name, wszBODY))
1337         ret = HTMLBodyElement_Create(nselem);
1338     else if(!strcmpW(class_name, wszINPUT))
1339         ret = HTMLInputElement_Create(nselem);
1340     else if(!strcmpW(class_name, wszOPTION))
1341         ret = HTMLOptionElement_Create(nselem);
1342     else if(!strcmpW(class_name, wszSCRIPT))
1343         ret = HTMLScriptElement_Create(nselem);
1344     else if(!strcmpW(class_name, wszSELECT))
1345         ret = HTMLSelectElement_Create(nselem);
1346     else if(!strcmpW(class_name, wszTABLE))
1347         ret = HTMLTable_Create(nselem);
1348     else if(!strcmpW(class_name, wszTEXTAREA))
1349         ret = HTMLTextAreaElement_Create(nselem);
1350
1351     if(!ret) {
1352         ret = heap_alloc_zero(sizeof(HTMLElement));
1353         HTMLElement_Init(ret);
1354     }
1355
1356     nsAString_Finish(&class_name_str);
1357
1358     ret->nselem = nselem;
1359
1360     if(!ret->node.dispex.data)
1361         init_dispex(&ret->node.dispex, (IUnknown*)HTMLELEM(ret), &HTMLElement_dispex);
1362
1363     return ret;
1364 }
1365
1366 typedef struct {
1367     DispatchEx dispex;
1368     const IHTMLElementCollectionVtbl *lpHTMLElementCollectionVtbl;
1369
1370     IUnknown *ref_unk;
1371     HTMLElement **elems;
1372     DWORD len;
1373
1374     LONG ref;
1375 } HTMLElementCollection;
1376
1377 #define HTMLELEMCOL(x)  ((IHTMLElementCollection*) &(x)->lpHTMLElementCollectionVtbl)
1378
1379 #define ELEMCOL_THIS(iface) DEFINE_THIS(HTMLElementCollection, HTMLElementCollection, iface)
1380
1381 static HRESULT WINAPI HTMLElementCollection_QueryInterface(IHTMLElementCollection *iface,
1382                                                            REFIID riid, void **ppv)
1383 {
1384     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1385
1386     *ppv = NULL;
1387
1388     if(IsEqualGUID(&IID_IUnknown, riid)) {
1389         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1390         *ppv = HTMLELEMCOL(This);
1391     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1392         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1393         *ppv = HTMLELEMCOL(This);
1394     }else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
1395         TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
1396         *ppv = DISPATCHEX(&This->dispex);
1397     }else if(IsEqualGUID(&IID_IHTMLElementCollection, riid)) {
1398         TRACE("(%p)->(IID_IHTMLElementCollection %p)\n", This, ppv);
1399         *ppv = HTMLELEMCOL(This);
1400     }
1401
1402     if(*ppv) {
1403         IHTMLElementCollection_AddRef(HTMLELEMCOL(This));
1404         return S_OK;
1405     }
1406
1407     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1408     return E_NOINTERFACE;
1409 }
1410
1411 static ULONG WINAPI HTMLElementCollection_AddRef(IHTMLElementCollection *iface)
1412 {
1413     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1414     LONG ref = InterlockedIncrement(&This->ref);
1415
1416     TRACE("(%p) ref=%d\n", This, ref);
1417
1418     return ref;
1419 }
1420
1421 static ULONG WINAPI HTMLElementCollection_Release(IHTMLElementCollection *iface)
1422 {
1423     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1424     LONG ref = InterlockedDecrement(&This->ref);
1425
1426     TRACE("(%p) ref=%d\n", This, ref);
1427
1428     if(!ref) {
1429         IUnknown_Release(This->ref_unk);
1430         heap_free(This->elems);
1431         heap_free(This);
1432     }
1433
1434     return ref;
1435 }
1436
1437 static HRESULT WINAPI HTMLElementCollection_GetTypeInfoCount(IHTMLElementCollection *iface,
1438                                                              UINT *pctinfo)
1439 {
1440     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1441     FIXME("(%p)->(%p)\n", This, pctinfo);
1442     return E_NOTIMPL;
1443 }
1444
1445 static HRESULT WINAPI HTMLElementCollection_GetTypeInfo(IHTMLElementCollection *iface,
1446         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1447 {
1448     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1449     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1450     return E_NOTIMPL;
1451 }
1452
1453 static HRESULT WINAPI HTMLElementCollection_GetIDsOfNames(IHTMLElementCollection *iface,
1454         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1455 {
1456     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1457     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1458                                         lcid, rgDispId);
1459     return E_NOTIMPL;
1460 }
1461
1462 static HRESULT WINAPI HTMLElementCollection_Invoke(IHTMLElementCollection *iface,
1463         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1464         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1465 {
1466     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1467     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1468             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1469     return E_NOTIMPL;
1470 }
1471
1472 static HRESULT WINAPI HTMLElementCollection_toString(IHTMLElementCollection *iface,
1473                                                      BSTR *String)
1474 {
1475     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1476     FIXME("(%p)->(%p)\n", This, String);
1477     return E_NOTIMPL;
1478 }
1479
1480 static HRESULT WINAPI HTMLElementCollection_put_length(IHTMLElementCollection *iface,
1481                                                        long v)
1482 {
1483     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1484     FIXME("(%p)->(%ld)\n", This, v);
1485     return E_NOTIMPL;
1486 }
1487
1488 static HRESULT WINAPI HTMLElementCollection_get_length(IHTMLElementCollection *iface,
1489                                                        long *p)
1490 {
1491     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1492
1493     TRACE("(%p)->(%p)\n", This, p);
1494
1495     *p = This->len;
1496     return S_OK;
1497 }
1498
1499 static HRESULT WINAPI HTMLElementCollection_get__newEnum(IHTMLElementCollection *iface,
1500                                                          IUnknown **p)
1501 {
1502     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1503     FIXME("(%p)->(%p)\n", This, p);
1504     return E_NOTIMPL;
1505 }
1506
1507 static BOOL is_elem_name(HTMLElement *elem, LPCWSTR name)
1508 {
1509     const PRUnichar *str;
1510     nsAString nsstr, nsname;
1511     BOOL ret = FALSE;
1512     nsresult nsres;
1513
1514     static const PRUnichar nameW[] = {'n','a','m','e',0};
1515
1516     nsAString_Init(&nsstr, NULL);
1517     nsIDOMHTMLElement_GetId(elem->nselem, &nsstr);
1518     nsAString_GetData(&nsstr, &str);
1519     if(!strcmpiW(str, name)) {
1520         nsAString_Finish(&nsstr);
1521         return TRUE;
1522     }
1523
1524     nsAString_Init(&nsname, nameW);
1525     nsres =  nsIDOMHTMLElement_GetAttribute(elem->nselem, &nsname, &nsstr);
1526     nsAString_Finish(&nsname);
1527     if(NS_SUCCEEDED(nsres)) {
1528         nsAString_GetData(&nsstr, &str);
1529         ret = !strcmpiW(str, name);
1530     }
1531
1532     nsAString_Finish(&nsstr);
1533     return ret;
1534 }
1535
1536 static HRESULT WINAPI HTMLElementCollection_item(IHTMLElementCollection *iface,
1537         VARIANT name, VARIANT index, IDispatch **pdisp)
1538 {
1539     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1540
1541     TRACE("(%p)->(v(%d) v(%d) %p)\n", This, V_VT(&name), V_VT(&index), pdisp);
1542
1543     *pdisp = NULL;
1544
1545     if(V_VT(&name) == VT_I4) {
1546         TRACE("name is VT_I4: %d\n", V_I4(&name));
1547
1548         if(V_I4(&name) < 0)
1549             return E_INVALIDARG;
1550         if(V_I4(&name) >= This->len)
1551             return S_OK;
1552
1553         *pdisp = (IDispatch*)This->elems[V_I4(&name)];
1554         IDispatch_AddRef(*pdisp);
1555         TRACE("Returning pdisp=%p\n", pdisp);
1556         return S_OK;
1557     }
1558
1559     if(V_VT(&name) == VT_BSTR) {
1560         DWORD i;
1561
1562         TRACE("name is VT_BSTR: %s\n", debugstr_w(V_BSTR(&name)));
1563
1564         if(V_VT(&index) == VT_I4) {
1565             LONG idx = V_I4(&index);
1566
1567             TRACE("index = %d\n", idx);
1568
1569             if(idx < 0)
1570                 return E_INVALIDARG;
1571
1572             for(i=0; i<This->len; i++) {
1573                 if(is_elem_name(This->elems[i], V_BSTR(&name)) && !idx--)
1574                     break;
1575             }
1576
1577             if(i != This->len) {
1578                 *pdisp = (IDispatch*)HTMLELEM(This->elems[i]);
1579                 IDispatch_AddRef(*pdisp);
1580             }
1581
1582             return S_OK;
1583         }else {
1584             elem_vector buf = {NULL, 0, 8};
1585
1586             buf.buf = heap_alloc(buf.size*sizeof(HTMLElement*));
1587
1588             for(i=0; i<This->len; i++) {
1589                 if(is_elem_name(This->elems[i], V_BSTR(&name)))
1590                     elem_vector_add(&buf, This->elems[i]);
1591             }
1592
1593             if(buf.len > 1) {
1594                 elem_vector_normalize(&buf);
1595                 *pdisp = (IDispatch*)HTMLElementCollection_Create(This->ref_unk, buf.buf, buf.len);
1596             }else {
1597                 if(buf.len == 1) {
1598                     *pdisp = (IDispatch*)HTMLELEM(buf.buf[0]);
1599                     IDispatch_AddRef(*pdisp);
1600                 }
1601
1602                 heap_free(buf.buf);
1603             }
1604
1605             return S_OK;
1606         }
1607     }
1608
1609     FIXME("unsupported arguments\n");
1610     return E_INVALIDARG;
1611 }
1612
1613 static HRESULT WINAPI HTMLElementCollection_tags(IHTMLElementCollection *iface,
1614                                                  VARIANT tagName, IDispatch **pdisp)
1615 {
1616     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1617     DWORD i;
1618     nsAString tag_str;
1619     const PRUnichar *tag;
1620     elem_vector buf = {NULL, 0, 8};
1621
1622     if(V_VT(&tagName) != VT_BSTR) {
1623         WARN("Invalid arg\n");
1624         return DISP_E_MEMBERNOTFOUND;
1625     }
1626
1627     TRACE("(%p)->(%s %p)\n", This, debugstr_w(V_BSTR(&tagName)), pdisp);
1628
1629     buf.buf = heap_alloc(buf.size*sizeof(HTMLElement*));
1630
1631     nsAString_Init(&tag_str, NULL);
1632
1633     for(i=0; i<This->len; i++) {
1634         if(!This->elems[i]->nselem)
1635             continue;
1636
1637         nsIDOMElement_GetTagName(This->elems[i]->nselem, &tag_str);
1638         nsAString_GetData(&tag_str, &tag);
1639
1640         if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, tag, -1,
1641                           V_BSTR(&tagName), -1) == CSTR_EQUAL)
1642             elem_vector_add(&buf, This->elems[i]);
1643     }
1644
1645     nsAString_Finish(&tag_str);
1646     elem_vector_normalize(&buf);
1647
1648     TRACE("fount %d tags\n", buf.len);
1649
1650     *pdisp = (IDispatch*)HTMLElementCollection_Create(This->ref_unk, buf.buf, buf.len);
1651     return S_OK;
1652 }
1653
1654 #define DISPID_ELEMCOL_0 MSHTML_DISPID_CUSTOM_MIN
1655
1656 static HRESULT HTMLElementCollection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
1657 {
1658     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1659     WCHAR *ptr;
1660     DWORD idx=0;
1661
1662     for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
1663         idx = idx*10 + (*ptr-'0');
1664
1665     if(*ptr || idx >= This->len)
1666         return DISP_E_UNKNOWNNAME;
1667
1668     *dispid = DISPID_ELEMCOL_0 + idx;
1669     TRACE("ret %x\n", *dispid);
1670     return S_OK;
1671 }
1672
1673 static HRESULT HTMLElementCollection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
1674         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
1675 {
1676     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1677     DWORD idx;
1678
1679     TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
1680
1681     idx = id - DISPID_ELEMCOL_0;
1682     if(idx >= This->len)
1683         return DISP_E_UNKNOWNNAME;
1684
1685     switch(flags) {
1686     case INVOKE_PROPERTYGET:
1687         V_VT(res) = VT_DISPATCH;
1688         V_DISPATCH(res) = (IDispatch*)HTMLELEM(This->elems[idx]);
1689         IHTMLElement_AddRef(HTMLELEM(This->elems[idx]));
1690         break;
1691     default:
1692         FIXME("unimplemented flags %x\n", flags);
1693         return E_NOTIMPL;
1694     }
1695
1696     return S_OK;
1697 }
1698
1699 #undef ELEMCOL_THIS
1700
1701 static const IHTMLElementCollectionVtbl HTMLElementCollectionVtbl = {
1702     HTMLElementCollection_QueryInterface,
1703     HTMLElementCollection_AddRef,
1704     HTMLElementCollection_Release,
1705     HTMLElementCollection_GetTypeInfoCount,
1706     HTMLElementCollection_GetTypeInfo,
1707     HTMLElementCollection_GetIDsOfNames,
1708     HTMLElementCollection_Invoke,
1709     HTMLElementCollection_toString,
1710     HTMLElementCollection_put_length,
1711     HTMLElementCollection_get_length,
1712     HTMLElementCollection_get__newEnum,
1713     HTMLElementCollection_item,
1714     HTMLElementCollection_tags
1715 };
1716
1717 static const dispex_static_data_vtbl_t HTMLElementColection_dispex_vtbl = {
1718     HTMLElementCollection_get_dispid,
1719     HTMLElementCollection_invoke
1720 };
1721
1722 static dispex_static_data_t HTMLElementCollection_dispex = {
1723     &HTMLElementColection_dispex_vtbl,
1724     DispHTMLElementCollection_tid,
1725     NULL,
1726     {
1727         IHTMLElementCollection_tid,
1728         0
1729     }
1730 };
1731
1732 IHTMLElementCollection *create_all_collection(HTMLDOMNode *node)
1733 {
1734     elem_vector buf = {NULL, 0, 8};
1735
1736     buf.buf = heap_alloc(buf.size*sizeof(HTMLElement**));
1737
1738     elem_vector_add(&buf, HTMLELEM_NODE_THIS(node));
1739     create_all_list(node->doc, node, &buf);
1740     elem_vector_normalize(&buf);
1741
1742     return HTMLElementCollection_Create((IUnknown*)HTMLDOMNODE(node), buf.buf, buf.len);
1743 }
1744
1745 static IHTMLElementCollection *HTMLElementCollection_Create(IUnknown *ref_unk,
1746             HTMLElement **elems, DWORD len)
1747 {
1748     HTMLElementCollection *ret = heap_alloc(sizeof(HTMLElementCollection));
1749
1750     ret->lpHTMLElementCollectionVtbl = &HTMLElementCollectionVtbl;
1751     ret->ref = 1;
1752     ret->elems = elems;
1753     ret->len = len;
1754
1755     init_dispex(&ret->dispex, (IUnknown*)HTMLELEMCOL(ret), &HTMLElementCollection_dispex);
1756
1757     IUnknown_AddRef(ref_unk);
1758     ret->ref_unk = ref_unk;
1759
1760     TRACE("ret=%p len=%d\n", ret, len);
1761
1762     return HTMLELEMCOL(ret);
1763 }