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