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