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