jscript: Added '|' expression implementation.
[wine] / dlls / mshtml / htmlbody.c
1 /*
2  * Copyright 2006 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <stdarg.h>
20 #include <stdio.h>
21
22 #define COBJMACROS
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
28
29 #include "wine/debug.h"
30
31 #include "mshtml_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
34
35 typedef struct {
36     HTMLTextContainer textcont;
37
38     const IHTMLBodyElementVtbl *lpHTMLBodyElementVtbl;
39
40     ConnectionPoint cp_propnotif;
41
42     nsIDOMHTMLBodyElement *nsbody;
43 } HTMLBodyElement;
44
45 #define HTMLBODY(x)  ((IHTMLBodyElement*)  &(x)->lpHTMLBodyElementVtbl)
46
47 static BOOL variant_to_nscolor(const VARIANT *v, nsAString *nsstr)
48 {
49     switch(V_VT(v)) {
50     case VT_BSTR:
51         nsAString_Init(nsstr, V_BSTR(v));
52         return TRUE;
53
54     case VT_I4: {
55         PRUnichar buf[10];
56         static const WCHAR formatW[] = {'#','%','x',0};
57
58         wsprintfW(buf, formatW, V_I4(v));
59         nsAString_Init(nsstr, buf);
60         return TRUE;
61     }
62
63     default:
64         FIXME("invalid vt=%d\n", V_VT(v));
65     }
66
67     return FALSE;
68
69 }
70
71 static void nscolor_to_variant(const nsAString *nsstr, VARIANT *p)
72 {
73     const PRUnichar *color;
74
75     nsAString_GetData(nsstr, &color);
76
77     if(*color == '#') {
78         V_VT(p) = VT_I4;
79         V_I4(p) = strtolW(color+1, NULL, 16);
80     }else {
81         V_VT(p) = VT_BSTR;
82         V_BSTR(p) = SysAllocString(color);
83     }
84 }
85
86 #define HTMLBODY_THIS(iface) DEFINE_THIS(HTMLBodyElement, HTMLBodyElement, iface)
87
88 static HRESULT WINAPI HTMLBodyElement_QueryInterface(IHTMLBodyElement *iface,
89                                                      REFIID riid, void **ppv)
90 {
91     HTMLBodyElement *This = HTMLBODY_THIS(iface);
92
93     return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(&This->textcont.element.node), riid, ppv);
94 }
95
96 static ULONG WINAPI HTMLBodyElement_AddRef(IHTMLBodyElement *iface)
97 {
98     HTMLBodyElement *This = HTMLBODY_THIS(iface);
99
100     return IHTMLDOMNode_AddRef(HTMLDOMNODE(&This->textcont.element.node));
101 }
102
103 static ULONG WINAPI HTMLBodyElement_Release(IHTMLBodyElement *iface)
104 {
105     HTMLBodyElement *This = HTMLBODY_THIS(iface);
106
107     return IHTMLDOMNode_Release(HTMLDOMNODE(&This->textcont.element.node));
108 }
109
110 static HRESULT WINAPI HTMLBodyElement_GetTypeInfoCount(IHTMLBodyElement *iface, UINT *pctinfo)
111 {
112     HTMLBodyElement *This = HTMLBODY_THIS(iface);
113     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->textcont.element.node.dispex), pctinfo);
114 }
115
116 static HRESULT WINAPI HTMLBodyElement_GetTypeInfo(IHTMLBodyElement *iface, UINT iTInfo,
117                                               LCID lcid, ITypeInfo **ppTInfo)
118 {
119     HTMLBodyElement *This = HTMLBODY_THIS(iface);
120     return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->textcont.element.node.dispex), iTInfo, lcid, ppTInfo);
121 }
122
123 static HRESULT WINAPI HTMLBodyElement_GetIDsOfNames(IHTMLBodyElement *iface, REFIID riid,
124                                                 LPOLESTR *rgszNames, UINT cNames,
125                                                 LCID lcid, DISPID *rgDispId)
126 {
127     HTMLBodyElement *This = HTMLBODY_THIS(iface);
128     return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->textcont.element.node.dispex), riid, rgszNames, cNames, lcid, rgDispId);
129 }
130
131 static HRESULT WINAPI HTMLBodyElement_Invoke(IHTMLBodyElement *iface, DISPID dispIdMember,
132                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
133                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
134 {
135     HTMLBodyElement *This = HTMLBODY_THIS(iface);
136     return IDispatchEx_Invoke(DISPATCHEX(&This->textcont.element.node.dispex), dispIdMember, riid, lcid,
137             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
138 }
139
140 static HRESULT WINAPI HTMLBodyElement_put_background(IHTMLBodyElement *iface, BSTR v)
141 {
142     HTMLBodyElement *This = HTMLBODY_THIS(iface);
143     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
144     return E_NOTIMPL;
145 }
146
147 static HRESULT WINAPI HTMLBodyElement_get_background(IHTMLBodyElement *iface, BSTR *p)
148 {
149     HTMLBodyElement *This = HTMLBODY_THIS(iface);
150     nsAString background_str;
151     nsresult nsres;
152
153     TRACE("(%p)->(%p)\n", This, p);
154
155     nsAString_Init(&background_str, NULL);
156
157     nsres = nsIDOMHTMLBodyElement_GetBackground(This->nsbody, &background_str);
158     if(NS_SUCCEEDED(nsres)) {
159         const PRUnichar *background;
160         nsAString_GetData(&background_str, &background);
161         *p = *background ? SysAllocString(background) : NULL;
162     }else {
163         ERR("GetBackground failed: %08x\n", nsres);
164         *p = NULL;
165     }
166
167     nsAString_Finish(&background_str);
168
169     TRACE("*p = %s\n", debugstr_w(*p));
170     return S_OK;
171 }
172
173 static HRESULT WINAPI HTMLBodyElement_put_bgProperties(IHTMLBodyElement *iface, BSTR v)
174 {
175     HTMLBodyElement *This = HTMLBODY_THIS(iface);
176     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
177     return E_NOTIMPL;
178 }
179
180 static HRESULT WINAPI HTMLBodyElement_get_bgProperties(IHTMLBodyElement *iface, BSTR *p)
181 {
182     HTMLBodyElement *This = HTMLBODY_THIS(iface);
183     FIXME("(%p)->(%p)\n", This, p);
184     return E_NOTIMPL;
185 }
186
187 static HRESULT WINAPI HTMLBodyElement_put_leftMargin(IHTMLBodyElement *iface, VARIANT v)
188 {
189     HTMLBodyElement *This = HTMLBODY_THIS(iface);
190     FIXME("(%p)->()\n", This);
191     return E_NOTIMPL;
192 }
193
194 static HRESULT WINAPI HTMLBodyElement_get_leftMargin(IHTMLBodyElement *iface, VARIANT *p)
195 {
196     HTMLBodyElement *This = HTMLBODY_THIS(iface);
197     FIXME("(%p)->(%p)\n", This, p);
198     return E_NOTIMPL;
199 }
200
201 static HRESULT WINAPI HTMLBodyElement_put_topMargin(IHTMLBodyElement *iface, VARIANT v)
202 {
203     HTMLBodyElement *This = HTMLBODY_THIS(iface);
204     FIXME("(%p)->()\n", This);
205     return E_NOTIMPL;
206 }
207
208 static HRESULT WINAPI HTMLBodyElement_get_topMargin(IHTMLBodyElement *iface, VARIANT *p)
209 {
210     HTMLBodyElement *This = HTMLBODY_THIS(iface);
211     FIXME("(%p)->(%p)\n", This, p);
212     return E_NOTIMPL;
213 }
214
215 static HRESULT WINAPI HTMLBodyElement_put_rightMargin(IHTMLBodyElement *iface, VARIANT v)
216 {
217     HTMLBodyElement *This = HTMLBODY_THIS(iface);
218     FIXME("(%p)->()\n", This);
219     return E_NOTIMPL;
220 }
221
222 static HRESULT WINAPI HTMLBodyElement_get_rightMargin(IHTMLBodyElement *iface, VARIANT *p)
223 {
224     HTMLBodyElement *This = HTMLBODY_THIS(iface);
225     FIXME("(%p)->(%p)\n", This, p);
226     return E_NOTIMPL;
227 }
228
229 static HRESULT WINAPI HTMLBodyElement_put_bottomMargin(IHTMLBodyElement *iface, VARIANT v)
230 {
231     HTMLBodyElement *This = HTMLBODY_THIS(iface);
232     FIXME("(%p)->()\n", This);
233     return E_NOTIMPL;
234 }
235
236 static HRESULT WINAPI HTMLBodyElement_get_bottomMargin(IHTMLBodyElement *iface, VARIANT *p)
237 {
238     HTMLBodyElement *This = HTMLBODY_THIS(iface);
239     FIXME("(%p)->(%p)\n", This, p);
240     return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI HTMLBodyElement_put_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL v)
244 {
245     HTMLBodyElement *This = HTMLBODY_THIS(iface);
246     FIXME("(%p)->(%x)\n", This, v);
247     return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI HTMLBodyElement_get_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL *p)
251 {
252     HTMLBodyElement *This = HTMLBODY_THIS(iface);
253     FIXME("(%p)->(%p)\n", This, p);
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI HTMLBodyElement_put_bgColor(IHTMLBodyElement *iface, VARIANT v)
258 {
259     HTMLBodyElement *This = HTMLBODY_THIS(iface);
260     nsAString strColor;
261     nsresult nsres;
262
263     TRACE("(%p)->()\n", This);
264
265     if(!variant_to_nscolor(&v, &strColor))
266         return S_OK;
267
268     nsres = nsIDOMHTMLBodyElement_SetBgColor(This->nsbody, &strColor);
269     nsAString_Finish(&strColor);
270     if(NS_FAILED(nsres))
271         ERR("SetBgColor failed: %08x\n", nsres);
272
273     return S_OK;
274 }
275
276 static HRESULT WINAPI HTMLBodyElement_get_bgColor(IHTMLBodyElement *iface, VARIANT *p)
277 {
278     HTMLBodyElement *This = HTMLBODY_THIS(iface);
279     nsAString strColor;
280     nsresult nsres;
281     const PRUnichar *color;
282
283     TRACE("(%p)->(%p)\n", This, p);
284
285     nsAString_Init(&strColor, NULL);
286     nsres = nsIDOMHTMLBodyElement_GetBgColor(This->nsbody, &strColor);
287     if(NS_FAILED(nsres))
288         ERR("SetBgColor failed: %08x\n", nsres);
289
290     nsAString_GetData(&strColor, &color);
291
292     V_VT(p) = VT_BSTR;
293     V_BSTR(p) = SysAllocString(color);
294
295     nsAString_Finish(&strColor);
296
297     return S_OK;
298 }
299
300 static HRESULT WINAPI HTMLBodyElement_put_text(IHTMLBodyElement *iface, VARIANT v)
301 {
302     HTMLBodyElement *This = HTMLBODY_THIS(iface);
303     FIXME("(%p)->()\n", This);
304     return E_NOTIMPL;
305 }
306
307 static HRESULT WINAPI HTMLBodyElement_get_text(IHTMLBodyElement *iface, VARIANT *p)
308 {
309     HTMLBodyElement *This = HTMLBODY_THIS(iface);
310     FIXME("(%p)->(%p)\n", This, p);
311     return E_NOTIMPL;
312 }
313
314 static HRESULT WINAPI HTMLBodyElement_put_link(IHTMLBodyElement *iface, VARIANT v)
315 {
316     HTMLBodyElement *This = HTMLBODY_THIS(iface);
317     nsAString link_str;
318     nsresult nsres;
319
320     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
321
322     if(!variant_to_nscolor(&v, &link_str))
323         return S_OK;
324
325     nsres = nsIDOMHTMLBodyElement_SetLink(This->nsbody, &link_str);
326     nsAString_Finish(&link_str);
327     if(NS_FAILED(nsres))
328         ERR("SetLink failed: %08x\n", nsres);
329
330     return S_OK;
331 }
332
333 static HRESULT WINAPI HTMLBodyElement_get_link(IHTMLBodyElement *iface, VARIANT *p)
334 {
335     HTMLBodyElement *This = HTMLBODY_THIS(iface);
336     nsAString link_str;
337     nsresult nsres;
338
339     TRACE("(%p)->(%p)\n", This, p);
340
341     nsAString_Init(&link_str, NULL);
342     nsres = nsIDOMHTMLBodyElement_GetLink(This->nsbody, &link_str);
343     if(NS_FAILED(nsres))
344         ERR("GetLink failed: %08x\n", nsres);
345
346     nscolor_to_variant(&link_str, p);
347     nsAString_Finish(&link_str);
348
349     return S_OK;
350 }
351
352 static HRESULT WINAPI HTMLBodyElement_put_vLink(IHTMLBodyElement *iface, VARIANT v)
353 {
354     HTMLBodyElement *This = HTMLBODY_THIS(iface);
355     nsAString vlink_str;
356     nsresult nsres;
357
358     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
359
360     if(!variant_to_nscolor(&v, &vlink_str))
361         return S_OK;
362
363     nsres = nsIDOMHTMLBodyElement_SetVLink(This->nsbody, &vlink_str);
364     nsAString_Finish(&vlink_str);
365     if(NS_FAILED(nsres))
366         ERR("SetLink failed: %08x\n", nsres);
367
368     return S_OK;
369 }
370
371 static HRESULT WINAPI HTMLBodyElement_get_vLink(IHTMLBodyElement *iface, VARIANT *p)
372 {
373     HTMLBodyElement *This = HTMLBODY_THIS(iface);
374     nsAString vlink_str;
375     nsresult nsres;
376
377     TRACE("(%p)->(%p)\n", This, p);
378
379     nsAString_Init(&vlink_str, NULL);
380     nsres = nsIDOMHTMLBodyElement_GetVLink(This->nsbody, &vlink_str);
381     if(NS_FAILED(nsres))
382         ERR("GetLink failed: %08x\n", nsres);
383
384     nscolor_to_variant(&vlink_str, p);
385     nsAString_Finish(&vlink_str);
386
387     return S_OK;
388 }
389
390 static HRESULT WINAPI HTMLBodyElement_put_aLink(IHTMLBodyElement *iface, VARIANT v)
391 {
392     HTMLBodyElement *This = HTMLBODY_THIS(iface);
393     nsAString alink_str;
394     nsresult nsres;
395
396     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
397
398     if(!variant_to_nscolor(&v, &alink_str))
399         return S_OK;
400
401     nsres = nsIDOMHTMLBodyElement_SetALink(This->nsbody, &alink_str);
402     nsAString_Finish(&alink_str);
403     if(NS_FAILED(nsres))
404         ERR("SetALink failed: %08x\n", nsres);
405
406     return S_OK;
407 }
408
409 static HRESULT WINAPI HTMLBodyElement_get_aLink(IHTMLBodyElement *iface, VARIANT *p)
410 {
411     HTMLBodyElement *This = HTMLBODY_THIS(iface);
412     nsAString alink_str;
413     nsresult nsres;
414
415     TRACE("(%p)->(%p)\n", This, p);
416
417     nsAString_Init(&alink_str, NULL);
418     nsres = nsIDOMHTMLBodyElement_GetALink(This->nsbody, &alink_str);
419     if(NS_FAILED(nsres))
420         ERR("GetALink failed: %08x\n", nsres);
421
422     nscolor_to_variant(&alink_str, p);
423     nsAString_Finish(&alink_str);
424
425     return S_OK;
426 }
427
428 static HRESULT WINAPI HTMLBodyElement_put_onload(IHTMLBodyElement *iface, VARIANT v)
429 {
430     HTMLBodyElement *This = HTMLBODY_THIS(iface);
431     FIXME("(%p)->()\n", This);
432     return E_NOTIMPL;
433 }
434
435 static HRESULT WINAPI HTMLBodyElement_get_onload(IHTMLBodyElement *iface, VARIANT *p)
436 {
437     HTMLBodyElement *This = HTMLBODY_THIS(iface);
438     FIXME("(%p)->(%p)\n", This, p);
439     return E_NOTIMPL;
440 }
441
442 static HRESULT WINAPI HTMLBodyElement_put_onunload(IHTMLBodyElement *iface, VARIANT v)
443 {
444     HTMLBodyElement *This = HTMLBODY_THIS(iface);
445     FIXME("(%p)->()\n", This);
446     return E_NOTIMPL;
447 }
448
449 static HRESULT WINAPI HTMLBodyElement_get_onunload(IHTMLBodyElement *iface, VARIANT *p)
450 {
451     HTMLBodyElement *This = HTMLBODY_THIS(iface);
452     FIXME("(%p)->(%p)\n", This, p);
453     return E_NOTIMPL;
454 }
455
456 static HRESULT WINAPI HTMLBodyElement_put_scroll(IHTMLBodyElement *iface, BSTR v)
457 {
458     HTMLBodyElement *This = HTMLBODY_THIS(iface);
459     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
460     return E_NOTIMPL;
461 }
462
463 static HRESULT WINAPI HTMLBodyElement_get_scroll(IHTMLBodyElement *iface, BSTR *p)
464 {
465     HTMLBodyElement *This = HTMLBODY_THIS(iface);
466     FIXME("(%p)->(%p)\n", This, p);
467     return E_NOTIMPL;
468 }
469
470 static HRESULT WINAPI HTMLBodyElement_put_onselect(IHTMLBodyElement *iface, VARIANT v)
471 {
472     HTMLBodyElement *This = HTMLBODY_THIS(iface);
473     FIXME("(%p)->()\n", This);
474     return E_NOTIMPL;
475 }
476
477 static HRESULT WINAPI HTMLBodyElement_get_onselect(IHTMLBodyElement *iface, VARIANT *p)
478 {
479     HTMLBodyElement *This = HTMLBODY_THIS(iface);
480     FIXME("(%p)->(%p)\n", This, p);
481     return E_NOTIMPL;
482 }
483
484 static HRESULT WINAPI HTMLBodyElement_put_onbeforeunload(IHTMLBodyElement *iface, VARIANT v)
485 {
486     HTMLBodyElement *This = HTMLBODY_THIS(iface);
487     FIXME("(%p)->()\n", This);
488     return E_NOTIMPL;
489 }
490
491 static HRESULT WINAPI HTMLBodyElement_get_onbeforeunload(IHTMLBodyElement *iface, VARIANT *p)
492 {
493     HTMLBodyElement *This = HTMLBODY_THIS(iface);
494     FIXME("(%p)->(%p)\n", This, p);
495     return E_NOTIMPL;
496 }
497
498 static HRESULT WINAPI HTMLBodyElement_createTextRange(IHTMLBodyElement *iface, IHTMLTxtRange **range)
499 {
500     HTMLBodyElement *This = HTMLBODY_THIS(iface);
501     nsIDOMRange *nsrange = NULL;
502
503     TRACE("(%p)->(%p)\n", This, range);
504
505     if(This->textcont.element.node.doc->nscontainer) {
506         nsIDOMDocument *nsdoc;
507         nsIDOMDocumentRange *nsdocrange;
508         nsresult nsres;
509
510         nsIWebNavigation_GetDocument(This->textcont.element.node.doc->nscontainer->navigation, &nsdoc);
511         nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMDocumentRange, (void**)&nsdocrange);
512         nsIDOMDocument_Release(nsdoc);
513
514         nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &nsrange);
515         if(NS_SUCCEEDED(nsres)) {
516             nsres = nsIDOMRange_SelectNodeContents(nsrange, This->textcont.element.node.nsnode);
517             if(NS_FAILED(nsres))
518                 ERR("SelectNodeContents failed: %08x\n", nsres);
519         }else {
520             ERR("CreateRange failed: %08x\n", nsres);
521         }
522
523         nsIDOMDocumentRange_Release(nsdocrange);
524     }
525
526     *range = HTMLTxtRange_Create(This->textcont.element.node.doc, nsrange);
527     return S_OK;
528 }
529
530 #undef HTMLBODY_THIS
531
532 static const IHTMLBodyElementVtbl HTMLBodyElementVtbl = {
533     HTMLBodyElement_QueryInterface,
534     HTMLBodyElement_AddRef,
535     HTMLBodyElement_Release,
536     HTMLBodyElement_GetTypeInfoCount,
537     HTMLBodyElement_GetTypeInfo,
538     HTMLBodyElement_GetIDsOfNames,
539     HTMLBodyElement_Invoke,
540     HTMLBodyElement_put_background,
541     HTMLBodyElement_get_background,
542     HTMLBodyElement_put_bgProperties,
543     HTMLBodyElement_get_bgProperties,
544     HTMLBodyElement_put_leftMargin,
545     HTMLBodyElement_get_leftMargin,
546     HTMLBodyElement_put_topMargin,
547     HTMLBodyElement_get_topMargin,
548     HTMLBodyElement_put_rightMargin,
549     HTMLBodyElement_get_rightMargin,
550     HTMLBodyElement_put_bottomMargin,
551     HTMLBodyElement_get_bottomMargin,
552     HTMLBodyElement_put_noWrap,
553     HTMLBodyElement_get_noWrap,
554     HTMLBodyElement_put_bgColor,
555     HTMLBodyElement_get_bgColor,
556     HTMLBodyElement_put_text,
557     HTMLBodyElement_get_text,
558     HTMLBodyElement_put_link,
559     HTMLBodyElement_get_link,
560     HTMLBodyElement_put_vLink,
561     HTMLBodyElement_get_vLink,
562     HTMLBodyElement_put_aLink,
563     HTMLBodyElement_get_aLink,
564     HTMLBodyElement_put_onload,
565     HTMLBodyElement_get_onload,
566     HTMLBodyElement_put_onunload,
567     HTMLBodyElement_get_onunload,
568     HTMLBodyElement_put_scroll,
569     HTMLBodyElement_get_scroll,
570     HTMLBodyElement_put_onselect,
571     HTMLBodyElement_get_onselect,
572     HTMLBodyElement_put_onbeforeunload,
573     HTMLBodyElement_get_onbeforeunload,
574     HTMLBodyElement_createTextRange
575 };
576
577 #define HTMLBODY_NODE_THIS(iface) DEFINE_THIS2(HTMLBodyElement, textcont.element.node, iface)
578
579 static HRESULT HTMLBodyElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
580 {
581     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
582
583     *ppv = NULL;
584
585     if(IsEqualGUID(&IID_IUnknown, riid)) {
586         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
587         *ppv = HTMLBODY(This);
588     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
589         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
590         *ppv = HTMLBODY(This);
591     }else if(IsEqualGUID(&IID_IHTMLBodyElement, riid)) {
592         TRACE("(%p)->(IID_IHTMLBodyElement %p)\n", This, ppv);
593         *ppv = HTMLBODY(This);
594     }else if(IsEqualGUID(&IID_IHTMLTextContainer, riid)) {
595         TRACE("(%p)->(IID_IHTMLTextContainer %p)\n", &This->textcont, ppv);
596         *ppv = HTMLTEXTCONT(&This->textcont);
597     }
598
599     if(*ppv) {
600         IUnknown_AddRef((IUnknown*)*ppv);
601         return S_OK;
602     }
603
604     return HTMLElement_QI(&This->textcont.element.node, riid, ppv);
605 }
606
607 static void HTMLBodyElement_destructor(HTMLDOMNode *iface)
608 {
609     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
610
611     nsIDOMHTMLBodyElement_Release(This->nsbody);
612
613     HTMLElement_destructor(&This->textcont.element.node);
614 }
615
616 #undef HTMLBODY_NODE_THIS
617
618 static const NodeImplVtbl HTMLBodyElementImplVtbl = {
619     HTMLBodyElement_QI,
620     HTMLBodyElement_destructor
621 };
622
623 static const tid_t HTMLBodyElement_iface_tids[] = {
624     IHTMLBodyElement_tid,
625     IHTMLBodyElement2_tid,
626     IHTMLControlElement_tid,
627     IHTMLDOMNode_tid,
628     IHTMLDOMNode2_tid,
629     IHTMLElement_tid,
630     IHTMLElement2_tid,
631     IHTMLElement3_tid,
632     IHTMLElement4_tid,
633     IHTMLTextContainer_tid,
634     IHTMLUniqueName_tid,
635     0
636 };
637
638 static dispex_static_data_t HTMLBodyElement_dispex = {
639     NULL,
640     DispHTMLBody_tid,
641     NULL,
642     HTMLBodyElement_iface_tids
643 };
644
645 HTMLElement *HTMLBodyElement_Create(nsIDOMHTMLElement *nselem)
646 {
647     HTMLBodyElement *ret = heap_alloc_zero(sizeof(HTMLBodyElement));
648     nsresult nsres;
649
650     TRACE("(%p)->(%p)\n", ret, nselem);
651
652     HTMLTextContainer_Init(&ret->textcont);
653
654     ret->lpHTMLBodyElementVtbl = &HTMLBodyElementVtbl;
655
656     init_dispex(&ret->textcont.element.node.dispex, (IUnknown*)HTMLBODY(ret), &HTMLBodyElement_dispex);
657     ret->textcont.element.node.vtbl = &HTMLBodyElementImplVtbl;
658
659     ConnectionPoint_Init(&ret->cp_propnotif, &ret->textcont.element.cp_container, &IID_IPropertyNotifySink);
660
661     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLBodyElement,
662                                              (void**)&ret->nsbody);
663     if(NS_FAILED(nsres))
664         ERR("Could not get nsDOMHTMLBodyElement: %08x\n", nsres);
665
666     return &ret->textcont.element;
667 }