mshtml: Remove const in front of REFIID as that is a macro that already starts with...
[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 static HRESULT WINAPI HTMLElement_QueryInterface(IHTMLElement *iface,
62                                                  REFIID riid, void **ppv)
63 {
64     HTMLElement *This = HTMLELEM_THIS(iface);
65     HRESULT hres;
66
67     if(This->impl)
68         return IUnknown_QueryInterface(This->impl, riid, ppv);
69
70     hres = HTMLElement_QI(This, riid, ppv);
71     if(FAILED(hres))
72         WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
73
74     return hres;
75 }
76
77 static ULONG WINAPI HTMLElement_AddRef(IHTMLElement *iface)
78 {
79     HTMLElement *This = HTMLELEM_THIS(iface);
80
81     if(This->impl)
82         return IUnknown_AddRef(This->impl);
83
84     TRACE("(%p)\n", This);
85     return IHTMLDocument2_AddRef(HTMLDOC(This->node->doc));
86 }
87
88 static ULONG WINAPI HTMLElement_Release(IHTMLElement *iface)
89 {
90     HTMLElement *This = HTMLELEM_THIS(iface);
91
92     if(This->impl)
93         return IUnknown_Release(This->impl);
94
95     TRACE("(%p)\n", This);
96     return IHTMLDocument2_Release(HTMLDOC(This->node->doc));
97 }
98
99 static HRESULT WINAPI HTMLElement_GetTypeInfoCount(IHTMLElement *iface, UINT *pctinfo)
100 {
101     HTMLElement *This = HTMLELEM_THIS(iface);
102     FIXME("(%p)->(%p)\n", This, pctinfo);
103     return E_NOTIMPL;
104 }
105
106 static HRESULT WINAPI HTMLElement_GetTypeInfo(IHTMLElement *iface, UINT iTInfo,
107                                               LCID lcid, ITypeInfo **ppTInfo)
108 {
109     HTMLElement *This = HTMLELEM_THIS(iface);
110     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
111     return E_NOTIMPL;
112 }
113
114 static HRESULT WINAPI HTMLElement_GetIDsOfNames(IHTMLElement *iface, REFIID riid,
115                                                 LPOLESTR *rgszNames, UINT cNames,
116                                                 LCID lcid, DISPID *rgDispId)
117 {
118     HTMLElement *This = HTMLELEM_THIS(iface);
119     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
120                                         lcid, rgDispId);
121     return E_NOTIMPL;
122 }
123
124 static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMember,
125                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
126                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
127 {
128     HTMLElement *This = HTMLELEM_THIS(iface);
129     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
130             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
131     return E_NOTIMPL;
132 }
133
134 static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName,
135                                                VARIANT AttributeValue, LONG lFlags)
136 {
137     HTMLElement *This = HTMLELEM_THIS(iface);
138     nsAString attr_str;
139     nsAString value_str;
140     nsresult nsres;
141     HRESULT hres;
142     VARIANT AttributeValueChanged;
143
144     WARN("(%p)->(%s . %08x)\n", This, debugstr_w(strAttributeName), lFlags);
145
146     VariantInit(&AttributeValueChanged);
147
148     hres = VariantChangeType(&AttributeValueChanged, &AttributeValue, 0, VT_BSTR);
149     if (FAILED(hres)) {
150         WARN("couldn't convert input attribute value %d to VT_BSTR\n", V_VT(&AttributeValue));
151         return hres;
152     }
153
154     nsAString_Init(&attr_str, strAttributeName);
155     nsAString_Init(&value_str, V_BSTR(&AttributeValueChanged));
156
157     TRACE("setting %s to %s\n", debugstr_w(strAttributeName),
158         debugstr_w(V_BSTR(&AttributeValueChanged)));
159
160     nsres = nsIDOMHTMLElement_SetAttribute(This->nselem, &attr_str, &value_str);
161     nsAString_Finish(&attr_str);
162     nsAString_Finish(&value_str);
163
164     if(NS_SUCCEEDED(nsres)) {
165         hres = S_OK;
166     }else {
167         ERR("SetAttribute failed: %08x\n", nsres);
168         hres = E_FAIL;
169     }
170
171     return hres;
172 }
173
174 static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttributeName,
175                                                LONG lFlags, VARIANT *AttributeValue)
176 {
177     HTMLElement *This = HTMLELEM_THIS(iface);
178     nsAString attr_str;
179     nsAString value_str;
180     const PRUnichar *value;
181     nsresult nsres;
182     HRESULT hres = S_OK;
183
184     WARN("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
185
186     VariantInit(AttributeValue);
187
188     nsAString_Init(&attr_str, strAttributeName);
189     nsAString_Init(&value_str, NULL);
190
191     nsres = nsIDOMHTMLElement_GetAttribute(This->nselem, &attr_str, &value_str);
192     nsAString_Finish(&attr_str);
193
194     if(NS_SUCCEEDED(nsres)) {
195         static const WCHAR wszSRC[] = {'s','r','c',0};
196         nsAString_GetData(&value_str, &value, NULL);
197         if(!strcmpiW(strAttributeName, wszSRC))
198         {
199             WCHAR buffer[256];
200             DWORD len;
201             BSTR bstrBaseUrl;
202             hres = IHTMLDocument2_get_URL(HTMLDOC(This->node->doc), &bstrBaseUrl);
203             if(SUCCEEDED(hres)) {
204                 hres = CoInternetCombineUrl(bstrBaseUrl, value,
205                                             URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
206                                             buffer, sizeof(buffer)/sizeof(WCHAR), &len, 0);
207                 SysFreeString(bstrBaseUrl);
208                 if(SUCCEEDED(hres)) {
209                     V_VT(AttributeValue) = VT_BSTR;
210                     V_BSTR(AttributeValue) = SysAllocString(buffer);
211                     TRACE("attr_value=%s\n", debugstr_w(V_BSTR(AttributeValue)));
212                 }
213             }
214         }else {
215             V_VT(AttributeValue) = VT_BSTR;
216             V_BSTR(AttributeValue) = SysAllocString(value);
217             TRACE("attr_value=%s\n", debugstr_w(V_BSTR(AttributeValue)));
218         }
219     }else {
220         ERR("GetAttribute failed: %08x\n", nsres);
221         hres = E_FAIL;
222     }
223
224     nsAString_Finish(&value_str);
225
226     return hres;
227 }
228
229 static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strAttributeName,
230                                                   LONG lFlags, VARIANT_BOOL *pfSuccess)
231 {
232     HTMLElement *This = HTMLELEM_THIS(iface);
233     FIXME("(%p)->()\n", This);
234     return E_NOTIMPL;
235 }
236
237 static HRESULT WINAPI HTMLElement_put_className(IHTMLElement *iface, BSTR v)
238 {
239     HTMLElement *This = HTMLELEM_THIS(iface);
240     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
241     return E_NOTIMPL;
242 }
243
244 static HRESULT WINAPI HTMLElement_get_className(IHTMLElement *iface, BSTR *p)
245 {
246     HTMLElement *This = HTMLELEM_THIS(iface);
247     nsAString class_str;
248     nsresult nsres;
249     HRESULT hres = S_OK;
250
251     TRACE("(%p)->(%p)\n", This, p);
252
253     nsAString_Init(&class_str, NULL);
254     nsres = nsIDOMHTMLElement_GetClassName(This->nselem, &class_str);
255
256     if(NS_SUCCEEDED(nsres)) {
257         const PRUnichar *class;
258         nsAString_GetData(&class_str, &class, NULL);
259         *p = SysAllocString(class);
260     }else {
261         ERR("GetClassName failed: %08x\n", nsres);
262         hres = E_FAIL;
263     }
264
265     nsAString_Finish(&class_str);
266
267     TRACE("className=%s\n", debugstr_w(*p));
268     return hres;
269 }
270
271 static HRESULT WINAPI HTMLElement_put_id(IHTMLElement *iface, BSTR v)
272 {
273     HTMLElement *This = HTMLELEM_THIS(iface);
274     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
275     return E_NOTIMPL;
276 }
277
278 static HRESULT WINAPI HTMLElement_get_id(IHTMLElement *iface, BSTR *p)
279 {
280     HTMLElement *This = HTMLELEM_THIS(iface);
281     FIXME("(%p)->(%p)\n", This, p);
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI HTMLElement_get_tagName(IHTMLElement *iface, BSTR *p)
286 {
287     HTMLElement *This = HTMLELEM_THIS(iface);
288     FIXME("(%p)->(%p)\n", This, p);
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI HTMLElement_get_parentElement(IHTMLElement *iface, IHTMLElement **p)
293 {
294     HTMLElement *This = HTMLELEM_THIS(iface);
295     FIXME("(%p)->(%p)\n", This, p);
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI HTMLElement_get_style(IHTMLElement *iface, IHTMLStyle **p)
300 {
301     HTMLElement *This = HTMLELEM_THIS(iface);
302     nsIDOMElementCSSInlineStyle *nselemstyle;
303     nsIDOMCSSStyleDeclaration *nsstyle;
304     nsresult nsres;
305
306     TRACE("(%p)->(%p)\n", This, p);
307
308     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMElementCSSInlineStyle,
309                                              (void**)&nselemstyle);
310     if(NS_FAILED(nsres)) {
311         ERR("Coud not get nsIDOMCSSStyleDeclaration interface: %08x\n", nsres);
312         return E_FAIL;
313     }
314
315     nsres = nsIDOMElementCSSInlineStyle_GetStyle(nselemstyle, &nsstyle);
316     nsIDOMElementCSSInlineStyle_Release(nselemstyle);
317     if(NS_FAILED(nsres)) {
318         ERR("GetStyle failed: %08x\n", nsres);
319         return E_FAIL;
320     }
321
322     /* FIXME: Store style instead of creating a new instance in each call */
323     *p = HTMLStyle_Create(nsstyle);
324
325     nsIDOMCSSStyleDeclaration_Release(nsstyle);
326     return S_OK;
327 }
328
329 static HRESULT WINAPI HTMLElement_put_onhelp(IHTMLElement *iface, VARIANT v)
330 {
331     HTMLElement *This = HTMLELEM_THIS(iface);
332     FIXME("(%p)->()\n", This);
333     return E_NOTIMPL;
334 }
335
336 static HRESULT WINAPI HTMLElement_get_onhelp(IHTMLElement *iface, VARIANT *p)
337 {
338     HTMLElement *This = HTMLELEM_THIS(iface);
339     FIXME("(%p)->(%p)\n", This, p);
340     return E_NOTIMPL;
341 }
342
343 static HRESULT WINAPI HTMLElement_put_onclick(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_onclick(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_ondblclick(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_ondblclick(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_onkeydown(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_onkeydown(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_onkeyup(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_onkeyup(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_onkeypress(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_onkeypress(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_onmouseout(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_onmouseout(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_onmouseover(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_onmouseover(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_onmousemove(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_onmousemove(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_onmousedown(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_onmousedown(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_onmouseup(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_onmouseup(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_get_document(IHTMLElement *iface, IDispatch **p)
484 {
485     HTMLElement *This = HTMLELEM_THIS(iface);
486     FIXME("(%p)->(%p)\n", This, p);
487     return E_NOTIMPL;
488 }
489
490 static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v)
491 {
492     HTMLElement *This = HTMLELEM_THIS(iface);
493     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
494     return E_NOTIMPL;
495 }
496
497 static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *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_language(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_language(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_onselectstart(IHTMLElement *iface, VARIANT v)
519 {
520     HTMLElement *This = HTMLELEM_THIS(iface);
521     FIXME("(%p)->()\n", This);
522     return E_NOTIMPL;
523 }
524
525 static HRESULT WINAPI HTMLElement_get_onselectstart(IHTMLElement *iface, VARIANT *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_scrollIntoView(IHTMLElement *iface, VARIANT varargStart)
533 {
534     HTMLElement *This = HTMLELEM_THIS(iface);
535     FIXME("(%p)->()\n", This);
536     return E_NOTIMPL;
537 }
538
539 static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pChild,
540                                            VARIANT_BOOL *pfResult)
541 {
542     HTMLElement *This = HTMLELEM_THIS(iface);
543     FIXME("(%p)->(%p %p)\n", This, pChild, pfResult);
544     return E_NOTIMPL;
545 }
546
547 static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, long *p)
548 {
549     HTMLElement *This = HTMLELEM_THIS(iface);
550     FIXME("(%p)->(%p)\n", This, p);
551     return E_NOTIMPL;
552 }
553
554 static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
555 {
556     HTMLElement *This = HTMLELEM_THIS(iface);
557     FIXME("(%p)->(%p)\n", This, p);
558     return E_NOTIMPL;
559 }
560
561 static HRESULT WINAPI HTMLElement_put_lang(IHTMLElement *iface, BSTR v)
562 {
563     HTMLElement *This = HTMLELEM_THIS(iface);
564     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
565     return E_NOTIMPL;
566 }
567
568 static HRESULT WINAPI HTMLElement_get_lang(IHTMLElement *iface, BSTR *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_get_offsetLeft(IHTMLElement *iface, long *p)
576 {
577     HTMLElement *This = HTMLELEM_THIS(iface);
578     FIXME("(%p)->(%p)\n", This, p);
579     return E_NOTIMPL;
580 }
581
582 static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, long *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_offsetWidth(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_offsetHeight(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_offsetParent(IHTMLElement *iface, IHTMLElement **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_put_innerHTML(IHTMLElement *iface, BSTR v)
611 {
612     HTMLElement *This = HTMLELEM_THIS(iface);
613     nsIDOMNSHTMLElement *nselem;
614     nsAString html_str;
615     nsresult nsres;
616
617     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
618
619     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
620     if(NS_FAILED(nsres)) {
621         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
622         return E_FAIL;
623     }
624
625     nsAString_Init(&html_str, v);
626     nsres = nsIDOMNSHTMLElement_SetInnerHTML(nselem, &html_str);
627     nsAString_Finish(&html_str);
628
629     if(NS_FAILED(nsres)) {
630         FIXME("SetInnerHtml failed %08x\n", nsres);
631         return E_FAIL;
632     }
633
634     return S_OK;
635 }
636
637 static HRESULT WINAPI HTMLElement_get_innerHTML(IHTMLElement *iface, BSTR *p)
638 {
639     HTMLElement *This = HTMLELEM_THIS(iface);
640     FIXME("(%p)->(%p)\n", This, p);
641     return E_NOTIMPL;
642 }
643
644 static HRESULT WINAPI HTMLElement_put_innerText(IHTMLElement *iface, BSTR v)
645 {
646     HTMLElement *This = HTMLELEM_THIS(iface);
647     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
648     return E_NOTIMPL;
649 }
650
651 static HRESULT WINAPI HTMLElement_get_innerText(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_outerHTML(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_outerHTML(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_outerText(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_outerText(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 HTMLElement_InsertAdjacentNode(HTMLElement *This, BSTR where, nsIDOMNode *nsnode)
687 {
688     static const WCHAR wszBeforeBegin[] = {'b','e','f','o','r','e','B','e','g','i','n',0};
689     static const WCHAR wszAfterBegin[] = {'a','f','t','e','r','B','e','g','i','n',0};
690     static const WCHAR wszBeforeEnd[] = {'b','e','f','o','r','e','E','n','d',0};
691     static const WCHAR wszAfterEnd[] = {'a','f','t','e','r','E','n','d',0};
692     nsresult nsres;
693
694     if (!strcmpiW(where, wszBeforeBegin))
695     {
696         nsIDOMNode *unused;
697         nsIDOMNode *parent;
698         nsres = nsIDOMNode_GetParentNode(This->nselem, &parent);
699         if (!parent) return E_INVALIDARG;
700         nsres = nsIDOMNode_InsertBefore(parent, nsnode,
701                                         (nsIDOMNode *)This->nselem, &unused);
702         if (unused) nsIDOMNode_Release(unused);
703         nsIDOMNode_Release(parent);
704     }
705     else if (!strcmpiW(where, wszAfterBegin))
706     {
707         nsIDOMNode *unused;
708         nsIDOMNode *first_child;
709         nsIDOMNode_GetFirstChild(This->nselem, &first_child);
710         nsres = nsIDOMNode_InsertBefore(This->nselem, nsnode, first_child, &unused);
711         if (unused) nsIDOMNode_Release(unused);
712         if (first_child) nsIDOMNode_Release(first_child);
713     }
714     else if (!strcmpiW(where, wszBeforeEnd))
715     {
716         nsIDOMNode *unused;
717         nsres = nsIDOMNode_AppendChild(This->nselem, nsnode, &unused);
718         if (unused) nsIDOMNode_Release(unused);
719     }
720     else if (!strcmpiW(where, wszAfterEnd))
721     {
722         nsIDOMNode *unused;
723         nsIDOMNode *next_sibling;
724         nsIDOMNode *parent;
725         nsIDOMNode_GetParentNode(This->nselem, &parent);
726         if (!parent) return E_INVALIDARG;
727
728         nsIDOMNode_GetNextSibling(This->nselem, &next_sibling);
729         if (next_sibling)
730         {
731             nsres = nsIDOMNode_InsertBefore(parent, nsnode, next_sibling, &unused);
732             nsIDOMNode_Release(next_sibling);
733         }
734         else
735             nsres = nsIDOMNode_AppendChild(parent, nsnode, &unused);
736         nsIDOMNode_Release(parent);
737         if (unused) nsIDOMNode_Release(unused);
738     }
739     else
740     {
741         ERR("invalid where: %s\n", debugstr_w(where));
742         return E_INVALIDARG;
743     }
744
745     if (NS_FAILED(nsres))
746         return E_FAIL;
747     else
748         return S_OK;
749 }
750
751 static HRESULT WINAPI HTMLElement_insertAdjacentHTML(IHTMLElement *iface, BSTR where,
752                                                      BSTR html)
753 {
754     HTMLElement *This = HTMLELEM_THIS(iface);
755     nsresult nsres;
756     nsIDOMDocument *nsdoc;
757     nsIDOMDocumentRange *nsdocrange;
758     nsIDOMRange *range;
759     nsIDOMNSRange *nsrange;
760     nsIDOMNode *nsnode;
761     nsAString ns_html;
762     HRESULT hr;
763
764     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(html));
765
766     nsres = nsIWebNavigation_GetDocument(This->node->doc->nscontainer->navigation, &nsdoc);
767     if(NS_FAILED(nsres))
768     {
769         ERR("GetDocument failed: %08x\n", nsres);
770         return E_FAIL;
771     }
772
773     nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMDocumentRange, (void **)&nsdocrange);
774     nsIDOMDocument_Release(nsdoc);
775     if(NS_FAILED(nsres))
776     {
777         ERR("getting nsIDOMDocumentRange failed: %08x\n", nsres);
778         return E_FAIL;
779     }
780     nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &range);
781     nsIDOMDocumentRange_Release(nsdocrange);
782     if(NS_FAILED(nsres))
783     {
784         ERR("CreateRange failed: %08x\n", nsres);
785         return E_FAIL;
786     }
787
788     nsIDOMRange_SetStartBefore(range, (nsIDOMNode *)This->nselem);
789
790     nsIDOMRange_QueryInterface(range, &IID_nsIDOMNSRange, (void **)&nsrange);
791     nsIDOMRange_Release(range);
792     if(NS_FAILED(nsres))
793     {
794         ERR("getting nsIDOMNSRange failed: %08x\n", nsres);
795         return E_FAIL;
796     }
797
798     nsAString_Init(&ns_html, html);
799
800     nsres = nsIDOMNSRange_CreateContextualFragment(nsrange, &ns_html, (nsIDOMDocumentFragment **)&nsnode);
801     nsIDOMNSRange_Release(nsrange);
802     nsAString_Finish(&ns_html);
803
804     if(NS_FAILED(nsres) || !nsnode)
805     {
806         ERR("CreateTextNode failed: %08x\n", nsres);
807         return E_FAIL;
808     }
809
810     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
811     nsIDOMNode_Release(nsnode);
812
813     return hr;
814 }
815
816 static HRESULT WINAPI HTMLElement_insertAdjacentText(IHTMLElement *iface, BSTR where,
817                                                      BSTR text)
818 {
819     HTMLElement *This = HTMLELEM_THIS(iface);
820     nsresult nsres;
821     nsIDOMDocument *nsdoc;
822     nsIDOMNode *nsnode;
823     nsAString ns_text;
824     HRESULT hr;
825
826     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(text));
827
828     nsres = nsIWebNavigation_GetDocument(This->node->doc->nscontainer->navigation, &nsdoc);
829     if(NS_FAILED(nsres) || !nsdoc)
830     {
831         ERR("GetDocument failed: %08x\n", nsres);
832         return E_FAIL;
833     }
834
835     nsAString_Init(&ns_text, text);
836
837     nsres = nsIDOMDocument_CreateTextNode(nsdoc, &ns_text, (nsIDOMText **)&nsnode);
838     nsIDOMDocument_Release(nsdoc);
839     nsAString_Finish(&ns_text);
840
841     if(NS_FAILED(nsres) || !nsnode)
842     {
843         ERR("CreateTextNode failed: %08x\n", nsres);
844         return E_FAIL;
845     }
846
847     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
848     nsIDOMNode_Release(nsnode);
849
850     return hr;
851 }
852
853 static HRESULT WINAPI HTMLElement_get_parentTextEdit(IHTMLElement *iface, IHTMLElement **p)
854 {
855     HTMLElement *This = HTMLELEM_THIS(iface);
856     FIXME("(%p)->(%p)\n", This, p);
857     return E_NOTIMPL;
858 }
859
860 static HRESULT WINAPI HTMLElement_get_isTextEdit(IHTMLElement *iface, VARIANT_BOOL *p)
861 {
862     HTMLElement *This = HTMLELEM_THIS(iface);
863     FIXME("(%p)->(%p)\n", This, p);
864     return E_NOTIMPL;
865 }
866
867 static HRESULT WINAPI HTMLElement_click(IHTMLElement *iface)
868 {
869     HTMLElement *This = HTMLELEM_THIS(iface);
870     FIXME("(%p)\n", This);
871     return E_NOTIMPL;
872 }
873
874 static HRESULT WINAPI HTMLElement_get_filters(IHTMLElement *iface,
875                                               IHTMLFiltersCollection **p)
876 {
877     HTMLElement *This = HTMLELEM_THIS(iface);
878     FIXME("(%p)->(%p)\n", This, p);
879     return E_NOTIMPL;
880 }
881
882 static HRESULT WINAPI HTMLElement_put_ondragstart(IHTMLElement *iface, VARIANT v)
883 {
884     HTMLElement *This = HTMLELEM_THIS(iface);
885     FIXME("(%p)->()\n", This);
886     return E_NOTIMPL;
887 }
888
889 static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *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_toString(IHTMLElement *iface, BSTR *String)
897 {
898     HTMLElement *This = HTMLELEM_THIS(iface);
899     FIXME("(%p)->(%p)\n", This, String);
900     return E_NOTIMPL;
901 }
902
903 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
904 {
905     HTMLElement *This = HTMLELEM_THIS(iface);
906     FIXME("(%p)->()\n", This);
907     return E_NOTIMPL;
908 }
909
910 static HRESULT WINAPI HTMLElement_get_onbeforeupdate(IHTMLElement *iface, VARIANT *p)
911 {
912     HTMLElement *This = HTMLELEM_THIS(iface);
913     FIXME("(%p)->(%p)\n", This, p);
914     return E_NOTIMPL;
915 }
916
917 static HRESULT WINAPI HTMLElement_put_onafterupdate(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_onafterupdate(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_onerrorupdate(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_onerrorupdate(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_onrowexit(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_onrowexit(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_onrowenter(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_onrowenter(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_ondatasetchanged(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_ondatasetchanged(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_ondataavailable(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_ondataavailable(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_ondatasetcomplete(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_ondatasetcomplete(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_onfilterchange(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_onfilterchange(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 void create_child_list(HTMLDocument *doc, HTMLElement *elem, elem_vector *buf)
1030 {
1031     nsIDOMNodeList *nsnode_list;
1032     nsIDOMNode *iter;
1033     PRUint32 list_len = 0, i;
1034     HTMLDOMNode *node;
1035     nsresult nsres;
1036
1037     nsres = nsIDOMNode_GetChildNodes(elem->node->nsnode, &nsnode_list);
1038     if(NS_FAILED(nsres)) {
1039         ERR("GetChildNodes failed: %08x\n", nsres);
1040         return;
1041     }
1042
1043     nsIDOMNodeList_GetLength(nsnode_list, &list_len);
1044     if(!list_len)
1045         return;
1046
1047     buf->size = list_len;
1048     buf->buf = mshtml_alloc(buf->size*sizeof(HTMLElement**));
1049
1050     for(i=0; i<list_len; i++) {
1051         nsres = nsIDOMNodeList_Item(nsnode_list, i, &iter);
1052         if(NS_FAILED(nsres)) {
1053             ERR("Item failed: %08x\n", nsres);
1054             continue;
1055         }
1056
1057         node = get_node(doc, iter);
1058         if(node->node_type != NT_HTMLELEM)
1059             continue;
1060
1061         elem_vector_add(buf, (HTMLElement*)node->impl.elem);
1062     }
1063 }
1064
1065 static HRESULT WINAPI HTMLElement_get_children(IHTMLElement *iface, IDispatch **p)
1066 {
1067     HTMLElement *This = HTMLELEM_THIS(iface);
1068     elem_vector buf = {NULL, 0, 0};
1069
1070     TRACE("(%p)->(%p)\n", This, p);
1071
1072     create_child_list(This->node->doc, This, &buf);
1073
1074     return HTMLElementCollection_Create((IUnknown*)HTMLELEM(This), buf.buf, buf.len, p);
1075 }
1076
1077 static void create_all_list(HTMLDocument *doc, HTMLElement *elem, elem_vector *buf)
1078 {
1079     nsIDOMNodeList *nsnode_list;
1080     nsIDOMNode *iter;
1081     PRUint32 list_len = 0, i;
1082     HTMLDOMNode *node;
1083     nsresult nsres;
1084
1085     nsres = nsIDOMNode_GetChildNodes(elem->node->nsnode, &nsnode_list);
1086     if(NS_FAILED(nsres)) {
1087         ERR("GetChildNodes failed: %08x\n", nsres);
1088         return;
1089     }
1090
1091     nsIDOMNodeList_GetLength(nsnode_list, &list_len);
1092     if(!list_len)
1093         return;
1094
1095     for(i=0; i<list_len; i++) {
1096         nsres = nsIDOMNodeList_Item(nsnode_list, i, &iter);
1097         if(NS_FAILED(nsres)) {
1098             ERR("Item failed: %08x\n", nsres);
1099             continue;
1100         }
1101
1102         node = get_node(doc, iter);
1103         if(node->node_type != NT_HTMLELEM)
1104             continue;
1105
1106         elem_vector_add(buf, (HTMLElement*)node->impl.elem);
1107         create_all_list(doc, (HTMLElement*)node->impl.elem, buf);
1108     }
1109 }
1110
1111 static HRESULT WINAPI HTMLElement_get_all(IHTMLElement *iface, IDispatch **p)
1112 {
1113     HTMLElement *This = HTMLELEM_THIS(iface);
1114     elem_vector buf = {NULL, 0, 8};
1115
1116     TRACE("(%p)->(%p)\n", This, p);
1117
1118     buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement**));
1119
1120     create_all_list(This->node->doc, This, &buf);
1121
1122     if(!buf.len) {
1123         mshtml_free(buf.buf);
1124         buf.buf = NULL;
1125     }else if(buf.size > buf.len) {
1126         buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement**));
1127     }
1128
1129     return HTMLElementCollection_Create((IUnknown*)HTMLELEM(This), buf.buf, buf.len, p);
1130 }
1131
1132 static void HTMLElement_destructor(IUnknown *iface)
1133 {
1134     HTMLElement *This = HTMLELEM_THIS(iface);
1135
1136     if(This->destructor)
1137         This->destructor(This->impl);
1138
1139     if(This->nselem)
1140         nsIDOMHTMLElement_Release(This->nselem);
1141
1142     mshtml_free(This);
1143 }
1144
1145 #undef HTMLELEM_THIS
1146
1147 static const IHTMLElementVtbl HTMLElementVtbl = {
1148     HTMLElement_QueryInterface,
1149     HTMLElement_AddRef,
1150     HTMLElement_Release,
1151     HTMLElement_GetTypeInfoCount,
1152     HTMLElement_GetTypeInfo,
1153     HTMLElement_GetIDsOfNames,
1154     HTMLElement_Invoke,
1155     HTMLElement_setAttribute,
1156     HTMLElement_getAttribute,
1157     HTMLElement_removeAttribute,
1158     HTMLElement_put_className,
1159     HTMLElement_get_className,
1160     HTMLElement_put_id,
1161     HTMLElement_get_id,
1162     HTMLElement_get_tagName,
1163     HTMLElement_get_parentElement,
1164     HTMLElement_get_style,
1165     HTMLElement_put_onhelp,
1166     HTMLElement_get_onhelp,
1167     HTMLElement_put_onclick,
1168     HTMLElement_get_onclick,
1169     HTMLElement_put_ondblclick,
1170     HTMLElement_get_ondblclick,
1171     HTMLElement_put_onkeydown,
1172     HTMLElement_get_onkeydown,
1173     HTMLElement_put_onkeyup,
1174     HTMLElement_get_onkeyup,
1175     HTMLElement_put_onkeypress,
1176     HTMLElement_get_onkeypress,
1177     HTMLElement_put_onmouseout,
1178     HTMLElement_get_onmouseout,
1179     HTMLElement_put_onmouseover,
1180     HTMLElement_get_onmouseover,
1181     HTMLElement_put_onmousemove,
1182     HTMLElement_get_onmousemove,
1183     HTMLElement_put_onmousedown,
1184     HTMLElement_get_onmousedown,
1185     HTMLElement_put_onmouseup,
1186     HTMLElement_get_onmouseup,
1187     HTMLElement_get_document,
1188     HTMLElement_put_title,
1189     HTMLElement_get_title,
1190     HTMLElement_put_language,
1191     HTMLElement_get_language,
1192     HTMLElement_put_onselectstart,
1193     HTMLElement_get_onselectstart,
1194     HTMLElement_scrollIntoView,
1195     HTMLElement_contains,
1196     HTMLElement_get_sourceIndex,
1197     HTMLElement_get_recordNumber,
1198     HTMLElement_put_lang,
1199     HTMLElement_get_lang,
1200     HTMLElement_get_offsetLeft,
1201     HTMLElement_get_offsetTop,
1202     HTMLElement_get_offsetWidth,
1203     HTMLElement_get_offsetHeight,
1204     HTMLElement_get_offsetParent,
1205     HTMLElement_put_innerHTML,
1206     HTMLElement_get_innerHTML,
1207     HTMLElement_put_innerText,
1208     HTMLElement_get_innerText,
1209     HTMLElement_put_outerHTML,
1210     HTMLElement_get_outerHTML,
1211     HTMLElement_put_outerText,
1212     HTMLElement_get_outerText,
1213     HTMLElement_insertAdjacentHTML,
1214     HTMLElement_insertAdjacentText,
1215     HTMLElement_get_parentTextEdit,
1216     HTMLElement_get_isTextEdit,
1217     HTMLElement_click,
1218     HTMLElement_get_filters,
1219     HTMLElement_put_ondragstart,
1220     HTMLElement_get_ondragstart,
1221     HTMLElement_toString,
1222     HTMLElement_put_onbeforeupdate,
1223     HTMLElement_get_onbeforeupdate,
1224     HTMLElement_put_onafterupdate,
1225     HTMLElement_get_onafterupdate,
1226     HTMLElement_put_onerrorupdate,
1227     HTMLElement_get_onerrorupdate,
1228     HTMLElement_put_onrowexit,
1229     HTMLElement_get_onrowexit,
1230     HTMLElement_put_onrowenter,
1231     HTMLElement_get_onrowenter,
1232     HTMLElement_put_ondatasetchanged,
1233     HTMLElement_get_ondatasetchanged,
1234     HTMLElement_put_ondataavailable,
1235     HTMLElement_get_ondataavailable,
1236     HTMLElement_put_ondatasetcomplete,
1237     HTMLElement_get_ondatasetcomplete,
1238     HTMLElement_put_onfilterchange,
1239     HTMLElement_get_onfilterchange,
1240     HTMLElement_get_children,
1241     HTMLElement_get_all
1242 };
1243
1244 HRESULT HTMLElement_QI(HTMLElement *This, REFIID riid, void **ppv)
1245 {
1246     *ppv =  NULL;
1247
1248     if(IsEqualGUID(&IID_IUnknown, riid)) {
1249         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1250         *ppv = HTMLELEM(This);
1251     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1252         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1253         *ppv = HTMLELEM(This);
1254     }else if(IsEqualGUID(&IID_IHTMLElement, riid)) {
1255         TRACE("(%p)->(IID_IHTMLElement %p)\n", This, ppv);
1256         *ppv = HTMLELEM(This);
1257     }else if(IsEqualGUID(&IID_IHTMLElement2, riid)) {
1258         TRACE("(%p)->(IID_IHTMLElement2 %p)\n", This, ppv);
1259         *ppv = HTMLELEM2(This);
1260     }
1261
1262     if(*ppv) {
1263         IHTMLElement_AddRef(HTMLELEM(This));
1264         return S_OK;
1265     }
1266
1267     return HTMLDOMNode_QI(This->node, riid, ppv);
1268 }
1269
1270 void HTMLElement_Create(HTMLDOMNode *node)
1271 {
1272     HTMLElement *ret;
1273     nsAString class_name_str;
1274     const PRUnichar *class_name;
1275     nsresult nsres;
1276
1277     static const WCHAR wszBODY[]     = {'B','O','D','Y',0};
1278     static const WCHAR wszINPUT[]    = {'I','N','P','U','T',0};
1279     static const WCHAR wszSELECT[]   = {'S','E','L','E','C','T',0};
1280     static const WCHAR wszTEXTAREA[] = {'T','E','X','T','A','R','E','A',0};
1281
1282     ret = mshtml_alloc(sizeof(HTMLElement));
1283     ret->lpHTMLElementVtbl = &HTMLElementVtbl;
1284     ret->node = node;
1285     ret->impl = NULL;
1286     ret->destructor = NULL;
1287
1288     node->node_type = NT_HTMLELEM;
1289     node->impl.elem = HTMLELEM(ret);
1290     node->destructor = HTMLElement_destructor;
1291
1292     HTMLElement2_Init(ret);
1293
1294     nsres = nsIDOMNode_QueryInterface(node->nsnode, &IID_nsIDOMHTMLElement, (void**)&ret->nselem);
1295     if(NS_FAILED(nsres))
1296         return;
1297
1298     nsAString_Init(&class_name_str, NULL);
1299     nsIDOMHTMLElement_GetTagName(ret->nselem, &class_name_str);
1300
1301     nsAString_GetData(&class_name_str, &class_name, NULL);
1302
1303     if(!strcmpW(class_name, wszBODY))
1304         HTMLBodyElement_Create(ret);
1305     else if(!strcmpW(class_name, wszINPUT))
1306         HTMLInputElement_Create(ret);
1307     else if(!strcmpW(class_name, wszSELECT))
1308         HTMLSelectElement_Create(ret);
1309     else if(!strcmpW(class_name, wszTEXTAREA))
1310         HTMLTextAreaElement_Create(ret);
1311
1312     nsAString_Finish(&class_name_str);
1313 }
1314
1315 typedef struct {
1316     const IHTMLElementCollectionVtbl *lpHTMLElementCollectionVtbl;
1317
1318     IUnknown *ref_unk;
1319     HTMLElement **elems;
1320     DWORD len;
1321
1322     LONG ref;
1323 } HTMLElementCollection;
1324
1325 #define HTMLELEMCOL(x)  ((IHTMLElementCollection*) &(x)->lpHTMLElementCollectionVtbl)
1326
1327 #define ELEMCOL_THIS(iface) DEFINE_THIS(HTMLElementCollection, HTMLElementCollection, iface)
1328
1329 static HRESULT WINAPI HTMLElementCollection_QueryInterface(IHTMLElementCollection *iface,
1330                                                            REFIID riid, void **ppv)
1331 {
1332     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1333
1334     *ppv = NULL;
1335
1336     if(IsEqualGUID(&IID_IUnknown, riid)) {
1337         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1338         *ppv = HTMLELEMCOL(This);
1339     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1340         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1341         *ppv = HTMLELEMCOL(This);
1342     }else if(IsEqualGUID(&IID_IHTMLElementCollection, riid)) {
1343         TRACE("(%p)->(IID_IHTMLElementCollection %p)\n", This, ppv);
1344         *ppv = HTMLELEMCOL(This);
1345     }
1346
1347     if(*ppv) {
1348         IHTMLElementCollection_AddRef(HTMLELEMCOL(This));
1349         return S_OK;
1350     }
1351
1352     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1353     return E_NOINTERFACE;
1354 }
1355
1356 static ULONG WINAPI HTMLElementCollection_AddRef(IHTMLElementCollection *iface)
1357 {
1358     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1359     LONG ref = InterlockedIncrement(&This->ref);
1360
1361     TRACE("(%p) ref=%d\n", This, ref);
1362
1363     return ref;
1364 }
1365
1366 static ULONG WINAPI HTMLElementCollection_Release(IHTMLElementCollection *iface)
1367 {
1368     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1369     LONG ref = InterlockedDecrement(&This->ref);
1370
1371     TRACE("(%p) ref=%d\n", This, ref);
1372
1373     if(!ref) {
1374         IUnknown_Release(This->ref_unk);
1375         mshtml_free(This->elems);
1376         mshtml_free(This);
1377     }
1378
1379     return ref;
1380 }
1381
1382 static HRESULT WINAPI HTMLElementCollection_GetTypeInfoCount(IHTMLElementCollection *iface,
1383                                                              UINT *pctinfo)
1384 {
1385     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1386     FIXME("(%p)->(%p)\n", This, pctinfo);
1387     return E_NOTIMPL;
1388 }
1389
1390 static HRESULT WINAPI HTMLElementCollection_GetTypeInfo(IHTMLElementCollection *iface,
1391         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1392 {
1393     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1394     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1395     return E_NOTIMPL;
1396 }
1397
1398 static HRESULT WINAPI HTMLElementCollection_GetIDsOfNames(IHTMLElementCollection *iface,
1399         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1400 {
1401     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1402     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1403                                         lcid, rgDispId);
1404     return E_NOTIMPL;
1405 }
1406
1407 static HRESULT WINAPI HTMLElementCollection_Invoke(IHTMLElementCollection *iface,
1408         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1409         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1410 {
1411     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1412     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1413             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1414     return E_NOTIMPL;
1415 }
1416
1417 static HRESULT WINAPI HTMLElementCollection_toString(IHTMLElementCollection *iface,
1418                                                      BSTR *String)
1419 {
1420     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1421     FIXME("(%p)->(%p)\n", This, String);
1422     return E_NOTIMPL;
1423 }
1424
1425 static HRESULT WINAPI HTMLElementCollection_put_length(IHTMLElementCollection *iface,
1426                                                        long v)
1427 {
1428     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1429     FIXME("(%p)->(%ld)\n", This, v);
1430     return E_NOTIMPL;
1431 }
1432
1433 static HRESULT WINAPI HTMLElementCollection_get_length(IHTMLElementCollection *iface,
1434                                                        long *p)
1435 {
1436     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1437
1438     TRACE("(%p)->(%p)\n", This, p);
1439
1440     *p = This->len;
1441     return S_OK;
1442 }
1443
1444 static HRESULT WINAPI HTMLElementCollection_get__newEnum(IHTMLElementCollection *iface,
1445                                                          IUnknown **p)
1446 {
1447     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1448     FIXME("(%p)->(%p)\n", This, p);
1449     return E_NOTIMPL;
1450 }
1451
1452 static HRESULT WINAPI HTMLElementCollection_item(IHTMLElementCollection *iface,
1453         VARIANT name, VARIANT index, IDispatch **pdisp)
1454 {
1455     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1456
1457     TRACE("(%p)->(v(%d) v(%d) %p)\n", This, V_VT(&name), V_VT(&index), pdisp);
1458
1459     if(V_VT(&name) == VT_I4) {
1460         TRACE("name is VT_I4: %d\n", V_I4(&name));
1461         if(V_I4(&name) < 0 || V_I4(&name) >= This->len) {
1462             ERR("Invalid name! name=%d\n", V_I4(&name));
1463             return E_INVALIDARG;
1464         }
1465
1466         *pdisp = (IDispatch*)This->elems[V_I4(&name)];
1467         IDispatch_AddRef(*pdisp);
1468         TRACE("Returning pdisp=%p\n", pdisp);
1469         return S_OK;
1470     }
1471
1472     if(V_VT(&name) == VT_BSTR) {
1473         DWORD i;
1474         nsAString tag_str;
1475         const PRUnichar *tag;
1476         elem_vector buf = {NULL, 0, 8};
1477
1478         TRACE("name is VT_BSTR: %s\n", debugstr_w(V_BSTR(&name)));
1479
1480         nsAString_Init(&tag_str, NULL);
1481         buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement*));
1482
1483         for(i=0; i<This->len; i++) {
1484             if(!This->elems[i]->nselem) continue;
1485
1486             nsIDOMHTMLElement_GetId(This->elems[i]->nselem, &tag_str);
1487             nsAString_GetData(&tag_str, &tag, NULL);
1488
1489             if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, tag, -1,
1490                                 V_BSTR(&name), -1) == CSTR_EQUAL) {
1491                 TRACE("Found name. elem=%d\n", i);
1492                 if (V_VT(&index) == VT_I4)
1493                     if (buf.len == V_I4(&index)) {
1494                         nsAString_Finish(&tag_str);
1495                         mshtml_free(buf.buf);
1496                         buf.buf = NULL;
1497                         *pdisp = (IDispatch*)This->elems[i];
1498                         TRACE("Returning element %d pdisp=%p\n", i, pdisp);
1499                         IDispatch_AddRef(*pdisp);
1500                         return S_OK;
1501                     }
1502                 elem_vector_add(&buf, This->elems[i]);
1503             }
1504         }
1505         nsAString_Finish(&tag_str);
1506         if (V_VT(&index) == VT_I4) {
1507             mshtml_free(buf.buf);
1508             buf.buf = NULL;
1509             ERR("Invalid index. index=%d >= buf.len=%d\n",V_I4(&index), buf.len);
1510             return E_INVALIDARG;
1511         }
1512         if(!buf.len) {
1513             mshtml_free(buf.buf);
1514             buf.buf = NULL;
1515         } else if(buf.size > buf.len) {
1516             buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement*));
1517         }
1518         TRACE("Returning %d element(s).\n", buf.len);
1519         return HTMLElementCollection_Create(This->ref_unk, buf.buf, buf.len, pdisp);
1520     }
1521
1522     FIXME("unsupported arguments\n");
1523     return E_INVALIDARG;
1524 }
1525
1526 static HRESULT WINAPI HTMLElementCollection_tags(IHTMLElementCollection *iface,
1527                                                  VARIANT tagName, IDispatch **pdisp)
1528 {
1529     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1530     DWORD i;
1531     nsAString tag_str;
1532     const PRUnichar *tag;
1533     elem_vector buf = {NULL, 0, 8};
1534
1535     if(V_VT(&tagName) != VT_BSTR) {
1536         WARN("Invalid arg\n");
1537         return DISP_E_MEMBERNOTFOUND;
1538     }
1539
1540     TRACE("(%p)->(%s %p)\n", This, debugstr_w(V_BSTR(&tagName)), pdisp);
1541
1542     buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement*));
1543
1544     nsAString_Init(&tag_str, NULL);
1545
1546     for(i=0; i<This->len; i++) {
1547         if(!This->elems[i]->nselem)
1548             continue;
1549
1550         nsIDOMElement_GetTagName(This->elems[i]->nselem, &tag_str);
1551         nsAString_GetData(&tag_str, &tag, NULL);
1552
1553         if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, tag, -1,
1554                           V_BSTR(&tagName), -1) == CSTR_EQUAL)
1555             elem_vector_add(&buf, This->elems[i]);
1556     }
1557
1558     nsAString_Finish(&tag_str);
1559
1560     TRACE("fount %d tags\n", buf.len);
1561
1562     if(!buf.len) {
1563         mshtml_free(buf.buf);
1564         buf.buf = NULL;
1565     }else if(buf.size > buf.len) {
1566         buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement*));
1567     }
1568
1569     return HTMLElementCollection_Create(This->ref_unk, buf.buf, buf.len, pdisp);
1570 }
1571
1572 #undef ELEMCOL_THIS
1573
1574 static const IHTMLElementCollectionVtbl HTMLElementCollectionVtbl = {
1575     HTMLElementCollection_QueryInterface,
1576     HTMLElementCollection_AddRef,
1577     HTMLElementCollection_Release,
1578     HTMLElementCollection_GetTypeInfoCount,
1579     HTMLElementCollection_GetTypeInfo,
1580     HTMLElementCollection_GetIDsOfNames,
1581     HTMLElementCollection_Invoke,
1582     HTMLElementCollection_toString,
1583     HTMLElementCollection_put_length,
1584     HTMLElementCollection_get_length,
1585     HTMLElementCollection_get__newEnum,
1586     HTMLElementCollection_item,
1587     HTMLElementCollection_tags
1588 };
1589
1590 static HRESULT HTMLElementCollection_Create(IUnknown *ref_unk, HTMLElement **elems, DWORD len,
1591                                             IDispatch **p)
1592 {
1593     HTMLElementCollection *ret = mshtml_alloc(sizeof(HTMLElementCollection));
1594
1595     ret->lpHTMLElementCollectionVtbl = &HTMLElementCollectionVtbl;
1596     ret->ref = 1;
1597     ret->elems = elems;
1598     ret->len = len;
1599
1600     IUnknown_AddRef(ref_unk);
1601     ret->ref_unk = ref_unk;
1602
1603     TRACE("ret=%p len=%d\n", ret, len);
1604
1605     *p = (IDispatch*)ret;
1606     return S_OK;
1607 }