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