richedit: Correct limitations on values for setting zoom ratio.
[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     HRESULT hr = S_OK;
144     nsAString nsstr;
145     nsresult nsres;
146
147     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
148
149     nsAString_Init(&nsstr, v);
150
151     nsres = nsIDOMHTMLBodyElement_SetBackground(This->nsbody, &nsstr);
152     if(!NS_SUCCEEDED(nsres))
153     {
154         hr = E_FAIL;
155     }
156
157     nsAString_Finish(&nsstr);
158
159     return hr;
160 }
161
162 static HRESULT WINAPI HTMLBodyElement_get_background(IHTMLBodyElement *iface, BSTR *p)
163 {
164     HTMLBodyElement *This = HTMLBODY_THIS(iface);
165     nsAString background_str;
166     nsresult nsres;
167
168     TRACE("(%p)->(%p)\n", This, p);
169
170     nsAString_Init(&background_str, NULL);
171
172     nsres = nsIDOMHTMLBodyElement_GetBackground(This->nsbody, &background_str);
173     if(NS_SUCCEEDED(nsres)) {
174         const PRUnichar *background;
175         nsAString_GetData(&background_str, &background);
176         *p = *background ? SysAllocString(background) : NULL;
177     }else {
178         ERR("GetBackground failed: %08x\n", nsres);
179         *p = NULL;
180     }
181
182     nsAString_Finish(&background_str);
183
184     TRACE("*p = %s\n", debugstr_w(*p));
185     return S_OK;
186 }
187
188 static HRESULT WINAPI HTMLBodyElement_put_bgProperties(IHTMLBodyElement *iface, BSTR v)
189 {
190     HTMLBodyElement *This = HTMLBODY_THIS(iface);
191     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
192     return E_NOTIMPL;
193 }
194
195 static HRESULT WINAPI HTMLBodyElement_get_bgProperties(IHTMLBodyElement *iface, BSTR *p)
196 {
197     HTMLBodyElement *This = HTMLBODY_THIS(iface);
198     FIXME("(%p)->(%p)\n", This, p);
199     return E_NOTIMPL;
200 }
201
202 static HRESULT WINAPI HTMLBodyElement_put_leftMargin(IHTMLBodyElement *iface, VARIANT v)
203 {
204     HTMLBodyElement *This = HTMLBODY_THIS(iface);
205     FIXME("(%p)->()\n", This);
206     return E_NOTIMPL;
207 }
208
209 static HRESULT WINAPI HTMLBodyElement_get_leftMargin(IHTMLBodyElement *iface, VARIANT *p)
210 {
211     HTMLBodyElement *This = HTMLBODY_THIS(iface);
212     FIXME("(%p)->(%p)\n", This, p);
213     return E_NOTIMPL;
214 }
215
216 static HRESULT WINAPI HTMLBodyElement_put_topMargin(IHTMLBodyElement *iface, VARIANT v)
217 {
218     HTMLBodyElement *This = HTMLBODY_THIS(iface);
219     FIXME("(%p)->()\n", This);
220     return E_NOTIMPL;
221 }
222
223 static HRESULT WINAPI HTMLBodyElement_get_topMargin(IHTMLBodyElement *iface, VARIANT *p)
224 {
225     HTMLBodyElement *This = HTMLBODY_THIS(iface);
226     FIXME("(%p)->(%p)\n", This, p);
227     return E_NOTIMPL;
228 }
229
230 static HRESULT WINAPI HTMLBodyElement_put_rightMargin(IHTMLBodyElement *iface, VARIANT v)
231 {
232     HTMLBodyElement *This = HTMLBODY_THIS(iface);
233     FIXME("(%p)->()\n", This);
234     return E_NOTIMPL;
235 }
236
237 static HRESULT WINAPI HTMLBodyElement_get_rightMargin(IHTMLBodyElement *iface, VARIANT *p)
238 {
239     HTMLBodyElement *This = HTMLBODY_THIS(iface);
240     FIXME("(%p)->(%p)\n", This, p);
241     return E_NOTIMPL;
242 }
243
244 static HRESULT WINAPI HTMLBodyElement_put_bottomMargin(IHTMLBodyElement *iface, VARIANT v)
245 {
246     HTMLBodyElement *This = HTMLBODY_THIS(iface);
247     FIXME("(%p)->()\n", This);
248     return E_NOTIMPL;
249 }
250
251 static HRESULT WINAPI HTMLBodyElement_get_bottomMargin(IHTMLBodyElement *iface, VARIANT *p)
252 {
253     HTMLBodyElement *This = HTMLBODY_THIS(iface);
254     FIXME("(%p)->(%p)\n", This, p);
255     return E_NOTIMPL;
256 }
257
258 static HRESULT WINAPI HTMLBodyElement_put_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL v)
259 {
260     HTMLBodyElement *This = HTMLBODY_THIS(iface);
261     FIXME("(%p)->(%x)\n", This, v);
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI HTMLBodyElement_get_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL *p)
266 {
267     HTMLBodyElement *This = HTMLBODY_THIS(iface);
268     FIXME("(%p)->(%p)\n", This, p);
269     return E_NOTIMPL;
270 }
271
272 static HRESULT WINAPI HTMLBodyElement_put_bgColor(IHTMLBodyElement *iface, VARIANT v)
273 {
274     HTMLBodyElement *This = HTMLBODY_THIS(iface);
275     nsAString strColor;
276     nsresult nsres;
277
278     TRACE("(%p)->()\n", This);
279
280     if(!variant_to_nscolor(&v, &strColor))
281         return S_OK;
282
283     nsres = nsIDOMHTMLBodyElement_SetBgColor(This->nsbody, &strColor);
284     nsAString_Finish(&strColor);
285     if(NS_FAILED(nsres))
286         ERR("SetBgColor failed: %08x\n", nsres);
287
288     return S_OK;
289 }
290
291 static HRESULT WINAPI HTMLBodyElement_get_bgColor(IHTMLBodyElement *iface, VARIANT *p)
292 {
293     HTMLBodyElement *This = HTMLBODY_THIS(iface);
294     nsAString strColor;
295     nsresult nsres;
296     const PRUnichar *color;
297
298     TRACE("(%p)->(%p)\n", This, p);
299
300     nsAString_Init(&strColor, NULL);
301     nsres = nsIDOMHTMLBodyElement_GetBgColor(This->nsbody, &strColor);
302     if(NS_FAILED(nsres))
303         ERR("SetBgColor failed: %08x\n", nsres);
304
305     nsAString_GetData(&strColor, &color);
306
307     V_VT(p) = VT_BSTR;
308     V_BSTR(p) = SysAllocString(color);
309
310     nsAString_Finish(&strColor);
311
312     return S_OK;
313 }
314
315 static HRESULT WINAPI HTMLBodyElement_put_text(IHTMLBodyElement *iface, VARIANT v)
316 {
317     HTMLBodyElement *This = HTMLBODY_THIS(iface);
318     nsAString text;
319     nsresult nsres;
320
321     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
322
323     if(!variant_to_nscolor(&v, &text))
324         return S_OK;
325
326     nsres = nsIDOMHTMLBodyElement_SetText(This->nsbody, &text);
327     nsAString_Finish(&text);
328
329     return S_OK;
330 }
331
332 static HRESULT WINAPI HTMLBodyElement_get_text(IHTMLBodyElement *iface, VARIANT *p)
333 {
334     HTMLBodyElement *This = HTMLBODY_THIS(iface);
335     nsAString text;
336     nsresult nsres;
337
338     TRACE("(%p)->(%p)\n", This, p);
339
340     nsAString_Init(&text, NULL);
341
342     V_VT(p) = VT_BSTR;
343     V_BSTR(p) = NULL;
344
345     nsres = nsIDOMHTMLBodyElement_GetText(This->nsbody, &text);
346     if(NS_SUCCEEDED(nsres))
347     {
348         const PRUnichar *sText;
349         nsAString_GetData(&text, &sText);
350
351         V_VT(p) = VT_BSTR;
352         V_BSTR(p) = SysAllocString(sText);
353     }
354
355     nsAString_Finish(&text);
356
357     return S_OK;
358 }
359
360 static HRESULT WINAPI HTMLBodyElement_put_link(IHTMLBodyElement *iface, VARIANT v)
361 {
362     HTMLBodyElement *This = HTMLBODY_THIS(iface);
363     nsAString link_str;
364     nsresult nsres;
365
366     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
367
368     if(!variant_to_nscolor(&v, &link_str))
369         return S_OK;
370
371     nsres = nsIDOMHTMLBodyElement_SetLink(This->nsbody, &link_str);
372     nsAString_Finish(&link_str);
373     if(NS_FAILED(nsres))
374         ERR("SetLink failed: %08x\n", nsres);
375
376     return S_OK;
377 }
378
379 static HRESULT WINAPI HTMLBodyElement_get_link(IHTMLBodyElement *iface, VARIANT *p)
380 {
381     HTMLBodyElement *This = HTMLBODY_THIS(iface);
382     nsAString link_str;
383     nsresult nsres;
384
385     TRACE("(%p)->(%p)\n", This, p);
386
387     nsAString_Init(&link_str, NULL);
388     nsres = nsIDOMHTMLBodyElement_GetLink(This->nsbody, &link_str);
389     if(NS_FAILED(nsres))
390         ERR("GetLink failed: %08x\n", nsres);
391
392     nscolor_to_variant(&link_str, p);
393     nsAString_Finish(&link_str);
394
395     return S_OK;
396 }
397
398 static HRESULT WINAPI HTMLBodyElement_put_vLink(IHTMLBodyElement *iface, VARIANT v)
399 {
400     HTMLBodyElement *This = HTMLBODY_THIS(iface);
401     nsAString vlink_str;
402     nsresult nsres;
403
404     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
405
406     if(!variant_to_nscolor(&v, &vlink_str))
407         return S_OK;
408
409     nsres = nsIDOMHTMLBodyElement_SetVLink(This->nsbody, &vlink_str);
410     nsAString_Finish(&vlink_str);
411     if(NS_FAILED(nsres))
412         ERR("SetLink failed: %08x\n", nsres);
413
414     return S_OK;
415 }
416
417 static HRESULT WINAPI HTMLBodyElement_get_vLink(IHTMLBodyElement *iface, VARIANT *p)
418 {
419     HTMLBodyElement *This = HTMLBODY_THIS(iface);
420     nsAString vlink_str;
421     nsresult nsres;
422
423     TRACE("(%p)->(%p)\n", This, p);
424
425     nsAString_Init(&vlink_str, NULL);
426     nsres = nsIDOMHTMLBodyElement_GetVLink(This->nsbody, &vlink_str);
427     if(NS_FAILED(nsres))
428         ERR("GetLink failed: %08x\n", nsres);
429
430     nscolor_to_variant(&vlink_str, p);
431     nsAString_Finish(&vlink_str);
432
433     return S_OK;
434 }
435
436 static HRESULT WINAPI HTMLBodyElement_put_aLink(IHTMLBodyElement *iface, VARIANT v)
437 {
438     HTMLBodyElement *This = HTMLBODY_THIS(iface);
439     nsAString alink_str;
440     nsresult nsres;
441
442     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
443
444     if(!variant_to_nscolor(&v, &alink_str))
445         return S_OK;
446
447     nsres = nsIDOMHTMLBodyElement_SetALink(This->nsbody, &alink_str);
448     nsAString_Finish(&alink_str);
449     if(NS_FAILED(nsres))
450         ERR("SetALink failed: %08x\n", nsres);
451
452     return S_OK;
453 }
454
455 static HRESULT WINAPI HTMLBodyElement_get_aLink(IHTMLBodyElement *iface, VARIANT *p)
456 {
457     HTMLBodyElement *This = HTMLBODY_THIS(iface);
458     nsAString alink_str;
459     nsresult nsres;
460
461     TRACE("(%p)->(%p)\n", This, p);
462
463     nsAString_Init(&alink_str, NULL);
464     nsres = nsIDOMHTMLBodyElement_GetALink(This->nsbody, &alink_str);
465     if(NS_FAILED(nsres))
466         ERR("GetALink failed: %08x\n", nsres);
467
468     nscolor_to_variant(&alink_str, p);
469     nsAString_Finish(&alink_str);
470
471     return S_OK;
472 }
473
474 static HRESULT WINAPI HTMLBodyElement_put_onload(IHTMLBodyElement *iface, VARIANT v)
475 {
476     HTMLBodyElement *This = HTMLBODY_THIS(iface);
477     FIXME("(%p)->()\n", This);
478     return E_NOTIMPL;
479 }
480
481 static HRESULT WINAPI HTMLBodyElement_get_onload(IHTMLBodyElement *iface, VARIANT *p)
482 {
483     HTMLBodyElement *This = HTMLBODY_THIS(iface);
484     FIXME("(%p)->(%p)\n", This, p);
485     return E_NOTIMPL;
486 }
487
488 static HRESULT WINAPI HTMLBodyElement_put_onunload(IHTMLBodyElement *iface, VARIANT v)
489 {
490     HTMLBodyElement *This = HTMLBODY_THIS(iface);
491     FIXME("(%p)->()\n", This);
492     return E_NOTIMPL;
493 }
494
495 static HRESULT WINAPI HTMLBodyElement_get_onunload(IHTMLBodyElement *iface, VARIANT *p)
496 {
497     HTMLBodyElement *This = HTMLBODY_THIS(iface);
498     FIXME("(%p)->(%p)\n", This, p);
499     return E_NOTIMPL;
500 }
501
502 static HRESULT WINAPI HTMLBodyElement_put_scroll(IHTMLBodyElement *iface, BSTR v)
503 {
504     HTMLBodyElement *This = HTMLBODY_THIS(iface);
505     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
506     return E_NOTIMPL;
507 }
508
509 static HRESULT WINAPI HTMLBodyElement_get_scroll(IHTMLBodyElement *iface, BSTR *p)
510 {
511     HTMLBodyElement *This = HTMLBODY_THIS(iface);
512     FIXME("(%p)->(%p)\n", This, p);
513     return E_NOTIMPL;
514 }
515
516 static HRESULT WINAPI HTMLBodyElement_put_onselect(IHTMLBodyElement *iface, VARIANT v)
517 {
518     HTMLBodyElement *This = HTMLBODY_THIS(iface);
519     FIXME("(%p)->()\n", This);
520     return E_NOTIMPL;
521 }
522
523 static HRESULT WINAPI HTMLBodyElement_get_onselect(IHTMLBodyElement *iface, VARIANT *p)
524 {
525     HTMLBodyElement *This = HTMLBODY_THIS(iface);
526     FIXME("(%p)->(%p)\n", This, p);
527     return E_NOTIMPL;
528 }
529
530 static HRESULT WINAPI HTMLBodyElement_put_onbeforeunload(IHTMLBodyElement *iface, VARIANT v)
531 {
532     HTMLBodyElement *This = HTMLBODY_THIS(iface);
533     FIXME("(%p)->()\n", This);
534     return E_NOTIMPL;
535 }
536
537 static HRESULT WINAPI HTMLBodyElement_get_onbeforeunload(IHTMLBodyElement *iface, VARIANT *p)
538 {
539     HTMLBodyElement *This = HTMLBODY_THIS(iface);
540     FIXME("(%p)->(%p)\n", This, p);
541     return E_NOTIMPL;
542 }
543
544 static HRESULT WINAPI HTMLBodyElement_createTextRange(IHTMLBodyElement *iface, IHTMLTxtRange **range)
545 {
546     HTMLBodyElement *This = HTMLBODY_THIS(iface);
547     nsIDOMDocumentRange *nsdocrange;
548     nsIDOMRange *nsrange = NULL;
549     nsresult nsres;
550
551     TRACE("(%p)->(%p)\n", This, range);
552
553     if(!This->textcont.element.node.doc->nsdoc) {
554         WARN("No nsdoc\n");
555         return E_UNEXPECTED;
556     }
557
558     nsres = nsIDOMDocument_QueryInterface(This->textcont.element.node.doc->nsdoc, &IID_nsIDOMDocumentRange,
559             (void**)&nsdocrange);
560     if(NS_FAILED(nsres)) {
561         ERR("Could not get nsIDOMDocumentRabge iface: %08x\n", nsres);
562         return E_FAIL;
563     }
564
565     nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &nsrange);
566     if(NS_SUCCEEDED(nsres)) {
567         nsres = nsIDOMRange_SelectNodeContents(nsrange, This->textcont.element.node.nsnode);
568         if(NS_FAILED(nsres))
569             ERR("SelectNodeContents failed: %08x\n", nsres);
570     }else {
571         ERR("CreateRange failed: %08x\n", nsres);
572     }
573
574     nsIDOMDocumentRange_Release(nsdocrange);
575
576     *range = HTMLTxtRange_Create(This->textcont.element.node.doc, nsrange);
577     return S_OK;
578 }
579
580 #undef HTMLBODY_THIS
581
582 static const IHTMLBodyElementVtbl HTMLBodyElementVtbl = {
583     HTMLBodyElement_QueryInterface,
584     HTMLBodyElement_AddRef,
585     HTMLBodyElement_Release,
586     HTMLBodyElement_GetTypeInfoCount,
587     HTMLBodyElement_GetTypeInfo,
588     HTMLBodyElement_GetIDsOfNames,
589     HTMLBodyElement_Invoke,
590     HTMLBodyElement_put_background,
591     HTMLBodyElement_get_background,
592     HTMLBodyElement_put_bgProperties,
593     HTMLBodyElement_get_bgProperties,
594     HTMLBodyElement_put_leftMargin,
595     HTMLBodyElement_get_leftMargin,
596     HTMLBodyElement_put_topMargin,
597     HTMLBodyElement_get_topMargin,
598     HTMLBodyElement_put_rightMargin,
599     HTMLBodyElement_get_rightMargin,
600     HTMLBodyElement_put_bottomMargin,
601     HTMLBodyElement_get_bottomMargin,
602     HTMLBodyElement_put_noWrap,
603     HTMLBodyElement_get_noWrap,
604     HTMLBodyElement_put_bgColor,
605     HTMLBodyElement_get_bgColor,
606     HTMLBodyElement_put_text,
607     HTMLBodyElement_get_text,
608     HTMLBodyElement_put_link,
609     HTMLBodyElement_get_link,
610     HTMLBodyElement_put_vLink,
611     HTMLBodyElement_get_vLink,
612     HTMLBodyElement_put_aLink,
613     HTMLBodyElement_get_aLink,
614     HTMLBodyElement_put_onload,
615     HTMLBodyElement_get_onload,
616     HTMLBodyElement_put_onunload,
617     HTMLBodyElement_get_onunload,
618     HTMLBodyElement_put_scroll,
619     HTMLBodyElement_get_scroll,
620     HTMLBodyElement_put_onselect,
621     HTMLBodyElement_get_onselect,
622     HTMLBodyElement_put_onbeforeunload,
623     HTMLBodyElement_get_onbeforeunload,
624     HTMLBodyElement_createTextRange
625 };
626
627 #define HTMLBODY_NODE_THIS(iface) DEFINE_THIS2(HTMLBodyElement, textcont.element.node, iface)
628
629 static HRESULT HTMLBodyElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
630 {
631     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
632
633     *ppv = NULL;
634
635     if(IsEqualGUID(&IID_IUnknown, riid)) {
636         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
637         *ppv = HTMLBODY(This);
638     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
639         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
640         *ppv = HTMLBODY(This);
641     }else if(IsEqualGUID(&IID_IHTMLBodyElement, riid)) {
642         TRACE("(%p)->(IID_IHTMLBodyElement %p)\n", This, ppv);
643         *ppv = HTMLBODY(This);
644     }else if(IsEqualGUID(&IID_IHTMLTextContainer, riid)) {
645         TRACE("(%p)->(IID_IHTMLTextContainer %p)\n", &This->textcont, ppv);
646         *ppv = HTMLTEXTCONT(&This->textcont);
647     }
648
649     if(*ppv) {
650         IUnknown_AddRef((IUnknown*)*ppv);
651         return S_OK;
652     }
653
654     return HTMLElement_QI(&This->textcont.element.node, riid, ppv);
655 }
656
657 static void HTMLBodyElement_destructor(HTMLDOMNode *iface)
658 {
659     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
660
661     nsIDOMHTMLBodyElement_Release(This->nsbody);
662
663     HTMLElement_destructor(&This->textcont.element.node);
664 }
665
666 #undef HTMLBODY_NODE_THIS
667
668 static const NodeImplVtbl HTMLBodyElementImplVtbl = {
669     HTMLBodyElement_QI,
670     HTMLBodyElement_destructor
671 };
672
673 static const tid_t HTMLBodyElement_iface_tids[] = {
674     IHTMLBodyElement_tid,
675     IHTMLBodyElement2_tid,
676     IHTMLDOMNode_tid,
677     IHTMLDOMNode2_tid,
678     IHTMLElement_tid,
679     IHTMLElement2_tid,
680     IHTMLElement3_tid,
681     IHTMLElement4_tid,
682     IHTMLTextContainer_tid,
683     IHTMLUniqueName_tid,
684     0
685 };
686
687 static dispex_static_data_t HTMLBodyElement_dispex = {
688     NULL,
689     DispHTMLBody_tid,
690     NULL,
691     HTMLBodyElement_iface_tids
692 };
693
694 HTMLElement *HTMLBodyElement_Create(nsIDOMHTMLElement *nselem)
695 {
696     HTMLBodyElement *ret = heap_alloc_zero(sizeof(HTMLBodyElement));
697     nsresult nsres;
698
699     TRACE("(%p)->(%p)\n", ret, nselem);
700
701     HTMLTextContainer_Init(&ret->textcont);
702
703     ret->lpHTMLBodyElementVtbl = &HTMLBodyElementVtbl;
704
705     init_dispex(&ret->textcont.element.node.dispex, (IUnknown*)HTMLBODY(ret), &HTMLBodyElement_dispex);
706     ret->textcont.element.node.vtbl = &HTMLBodyElementImplVtbl;
707
708     ConnectionPoint_Init(&ret->cp_propnotif, &ret->textcont.element.cp_container, &IID_IPropertyNotifySink);
709
710     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLBodyElement,
711                                              (void**)&ret->nsbody);
712     if(NS_FAILED(nsres))
713         ERR("Could not get nsDOMHTMLBodyElement: %08x\n", nsres);
714
715     return &ret->textcont.element;
716 }