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