mshtml: Added IHTMLElement2::get_scrollWidth 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     FIXME("(%p)->(%p)\n", This, pctinfo);
114     return E_NOTIMPL;
115 }
116
117 static HRESULT WINAPI HTMLBodyElement_GetTypeInfo(IHTMLBodyElement *iface, UINT iTInfo,
118                                               LCID lcid, ITypeInfo **ppTInfo)
119 {
120     HTMLBodyElement *This = HTMLBODY_THIS(iface);
121     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
122     return E_NOTIMPL;
123 }
124
125 static HRESULT WINAPI HTMLBodyElement_GetIDsOfNames(IHTMLBodyElement *iface, REFIID riid,
126                                                 LPOLESTR *rgszNames, UINT cNames,
127                                                 LCID lcid, DISPID *rgDispId)
128 {
129     HTMLBodyElement *This = HTMLBODY_THIS(iface);
130     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
131                                         lcid, rgDispId);
132     return E_NOTIMPL;
133 }
134
135 static HRESULT WINAPI HTMLBodyElement_Invoke(IHTMLBodyElement *iface, DISPID dispIdMember,
136                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
137                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
138 {
139     HTMLBodyElement *This = HTMLBODY_THIS(iface);
140     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
141             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
142     return E_NOTIMPL;
143 }
144
145 static HRESULT WINAPI HTMLBodyElement_put_background(IHTMLBodyElement *iface, BSTR v)
146 {
147     HTMLBodyElement *This = HTMLBODY_THIS(iface);
148     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
149     return E_NOTIMPL;
150 }
151
152 static HRESULT WINAPI HTMLBodyElement_get_background(IHTMLBodyElement *iface, BSTR *p)
153 {
154     HTMLBodyElement *This = HTMLBODY_THIS(iface);
155     nsAString background_str;
156     nsresult nsres;
157
158     TRACE("(%p)->(%p)\n", This, p);
159
160     nsAString_Init(&background_str, NULL);
161
162     nsres = nsIDOMHTMLBodyElement_GetBackground(This->nsbody, &background_str);
163     if(NS_SUCCEEDED(nsres)) {
164         const PRUnichar *background;
165         nsAString_GetData(&background_str, &background);
166         *p = *background ? SysAllocString(background) : NULL;
167     }else {
168         ERR("GetBackground failed: %08x\n", nsres);
169         *p = NULL;
170     }
171
172     nsAString_Finish(&background_str);
173
174     TRACE("*p = %s\n", debugstr_w(*p));
175     return S_OK;
176 }
177
178 static HRESULT WINAPI HTMLBodyElement_put_bgProperties(IHTMLBodyElement *iface, BSTR v)
179 {
180     HTMLBodyElement *This = HTMLBODY_THIS(iface);
181     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
182     return E_NOTIMPL;
183 }
184
185 static HRESULT WINAPI HTMLBodyElement_get_bgProperties(IHTMLBodyElement *iface, BSTR *p)
186 {
187     HTMLBodyElement *This = HTMLBODY_THIS(iface);
188     FIXME("(%p)->(%p)\n", This, p);
189     return E_NOTIMPL;
190 }
191
192 static HRESULT WINAPI HTMLBodyElement_put_leftMargin(IHTMLBodyElement *iface, VARIANT v)
193 {
194     HTMLBodyElement *This = HTMLBODY_THIS(iface);
195     FIXME("(%p)->()\n", This);
196     return E_NOTIMPL;
197 }
198
199 static HRESULT WINAPI HTMLBodyElement_get_leftMargin(IHTMLBodyElement *iface, VARIANT *p)
200 {
201     HTMLBodyElement *This = HTMLBODY_THIS(iface);
202     FIXME("(%p)->(%p)\n", This, p);
203     return E_NOTIMPL;
204 }
205
206 static HRESULT WINAPI HTMLBodyElement_put_topMargin(IHTMLBodyElement *iface, VARIANT v)
207 {
208     HTMLBodyElement *This = HTMLBODY_THIS(iface);
209     FIXME("(%p)->()\n", This);
210     return E_NOTIMPL;
211 }
212
213 static HRESULT WINAPI HTMLBodyElement_get_topMargin(IHTMLBodyElement *iface, VARIANT *p)
214 {
215     HTMLBodyElement *This = HTMLBODY_THIS(iface);
216     FIXME("(%p)->(%p)\n", This, p);
217     return E_NOTIMPL;
218 }
219
220 static HRESULT WINAPI HTMLBodyElement_put_rightMargin(IHTMLBodyElement *iface, VARIANT v)
221 {
222     HTMLBodyElement *This = HTMLBODY_THIS(iface);
223     FIXME("(%p)->()\n", This);
224     return E_NOTIMPL;
225 }
226
227 static HRESULT WINAPI HTMLBodyElement_get_rightMargin(IHTMLBodyElement *iface, VARIANT *p)
228 {
229     HTMLBodyElement *This = HTMLBODY_THIS(iface);
230     FIXME("(%p)->(%p)\n", This, p);
231     return E_NOTIMPL;
232 }
233
234 static HRESULT WINAPI HTMLBodyElement_put_bottomMargin(IHTMLBodyElement *iface, VARIANT v)
235 {
236     HTMLBodyElement *This = HTMLBODY_THIS(iface);
237     FIXME("(%p)->()\n", This);
238     return E_NOTIMPL;
239 }
240
241 static HRESULT WINAPI HTMLBodyElement_get_bottomMargin(IHTMLBodyElement *iface, VARIANT *p)
242 {
243     HTMLBodyElement *This = HTMLBODY_THIS(iface);
244     FIXME("(%p)->(%p)\n", This, p);
245     return E_NOTIMPL;
246 }
247
248 static HRESULT WINAPI HTMLBodyElement_put_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL v)
249 {
250     HTMLBodyElement *This = HTMLBODY_THIS(iface);
251     FIXME("(%p)->(%x)\n", This, v);
252     return E_NOTIMPL;
253 }
254
255 static HRESULT WINAPI HTMLBodyElement_get_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL *p)
256 {
257     HTMLBodyElement *This = HTMLBODY_THIS(iface);
258     FIXME("(%p)->(%p)\n", This, p);
259     return E_NOTIMPL;
260 }
261
262 static HRESULT WINAPI HTMLBodyElement_put_bgColor(IHTMLBodyElement *iface, VARIANT v)
263 {
264     HTMLBodyElement *This = HTMLBODY_THIS(iface);
265     FIXME("(%p)->()\n", This);
266     return E_NOTIMPL;
267 }
268
269 static HRESULT WINAPI HTMLBodyElement_get_bgColor(IHTMLBodyElement *iface, VARIANT *p)
270 {
271     HTMLBodyElement *This = HTMLBODY_THIS(iface);
272     FIXME("(%p)->(%p)\n", This, p);
273     return E_NOTIMPL;
274 }
275
276 static HRESULT WINAPI HTMLBodyElement_put_text(IHTMLBodyElement *iface, VARIANT v)
277 {
278     HTMLBodyElement *This = HTMLBODY_THIS(iface);
279     FIXME("(%p)->()\n", This);
280     return E_NOTIMPL;
281 }
282
283 static HRESULT WINAPI HTMLBodyElement_get_text(IHTMLBodyElement *iface, VARIANT *p)
284 {
285     HTMLBodyElement *This = HTMLBODY_THIS(iface);
286     FIXME("(%p)->(%p)\n", This, p);
287     return E_NOTIMPL;
288 }
289
290 static HRESULT WINAPI HTMLBodyElement_put_link(IHTMLBodyElement *iface, VARIANT v)
291 {
292     HTMLBodyElement *This = HTMLBODY_THIS(iface);
293     nsAString link_str;
294     nsresult nsres;
295
296     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
297
298     if(!variant_to_nscolor(&v, &link_str))
299         return S_OK;
300
301     nsres = nsIDOMHTMLBodyElement_SetLink(This->nsbody, &link_str);
302     nsAString_Finish(&link_str);
303     if(NS_FAILED(nsres))
304         ERR("SetLink failed: %08x\n", nsres);
305
306     return S_OK;
307 }
308
309 static HRESULT WINAPI HTMLBodyElement_get_link(IHTMLBodyElement *iface, VARIANT *p)
310 {
311     HTMLBodyElement *This = HTMLBODY_THIS(iface);
312     nsAString link_str;
313     nsresult nsres;
314
315     TRACE("(%p)->(%p)\n", This, p);
316
317     nsAString_Init(&link_str, NULL);
318     nsres = nsIDOMHTMLBodyElement_GetLink(This->nsbody, &link_str);
319     if(NS_FAILED(nsres))
320         ERR("GetLink failed: %08x\n", nsres);
321
322     nscolor_to_variant(&link_str, p);
323     nsAString_Finish(&link_str);
324
325     return S_OK;
326 }
327
328 static HRESULT WINAPI HTMLBodyElement_put_vLink(IHTMLBodyElement *iface, VARIANT v)
329 {
330     HTMLBodyElement *This = HTMLBODY_THIS(iface);
331     nsAString vlink_str;
332     nsresult nsres;
333
334     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
335
336     if(!variant_to_nscolor(&v, &vlink_str))
337         return S_OK;
338
339     nsres = nsIDOMHTMLBodyElement_SetVLink(This->nsbody, &vlink_str);
340     nsAString_Finish(&vlink_str);
341     if(NS_FAILED(nsres))
342         ERR("SetLink failed: %08x\n", nsres);
343
344     return S_OK;
345 }
346
347 static HRESULT WINAPI HTMLBodyElement_get_vLink(IHTMLBodyElement *iface, VARIANT *p)
348 {
349     HTMLBodyElement *This = HTMLBODY_THIS(iface);
350     nsAString vlink_str;
351     nsresult nsres;
352
353     TRACE("(%p)->(%p)\n", This, p);
354
355     nsAString_Init(&vlink_str, NULL);
356     nsres = nsIDOMHTMLBodyElement_GetVLink(This->nsbody, &vlink_str);
357     if(NS_FAILED(nsres))
358         ERR("GetLink failed: %08x\n", nsres);
359
360     nscolor_to_variant(&vlink_str, p);
361     nsAString_Finish(&vlink_str);
362
363     return S_OK;
364 }
365
366 static HRESULT WINAPI HTMLBodyElement_put_aLink(IHTMLBodyElement *iface, VARIANT v)
367 {
368     HTMLBodyElement *This = HTMLBODY_THIS(iface);
369     nsAString alink_str;
370     nsresult nsres;
371
372     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
373
374     if(!variant_to_nscolor(&v, &alink_str))
375         return S_OK;
376
377     nsres = nsIDOMHTMLBodyElement_SetALink(This->nsbody, &alink_str);
378     nsAString_Finish(&alink_str);
379     if(NS_FAILED(nsres))
380         ERR("SetALink failed: %08x\n", nsres);
381
382     return S_OK;
383 }
384
385 static HRESULT WINAPI HTMLBodyElement_get_aLink(IHTMLBodyElement *iface, VARIANT *p)
386 {
387     HTMLBodyElement *This = HTMLBODY_THIS(iface);
388     nsAString alink_str;
389     nsresult nsres;
390
391     TRACE("(%p)->(%p)\n", This, p);
392
393     nsAString_Init(&alink_str, NULL);
394     nsres = nsIDOMHTMLBodyElement_GetALink(This->nsbody, &alink_str);
395     if(NS_FAILED(nsres))
396         ERR("GetALink failed: %08x\n", nsres);
397
398     nscolor_to_variant(&alink_str, p);
399     nsAString_Finish(&alink_str);
400
401     return S_OK;
402 }
403
404 static HRESULT WINAPI HTMLBodyElement_put_onload(IHTMLBodyElement *iface, VARIANT v)
405 {
406     HTMLBodyElement *This = HTMLBODY_THIS(iface);
407     FIXME("(%p)->()\n", This);
408     return E_NOTIMPL;
409 }
410
411 static HRESULT WINAPI HTMLBodyElement_get_onload(IHTMLBodyElement *iface, VARIANT *p)
412 {
413     HTMLBodyElement *This = HTMLBODY_THIS(iface);
414     FIXME("(%p)->(%p)\n", This, p);
415     return E_NOTIMPL;
416 }
417
418 static HRESULT WINAPI HTMLBodyElement_put_onunload(IHTMLBodyElement *iface, VARIANT v)
419 {
420     HTMLBodyElement *This = HTMLBODY_THIS(iface);
421     FIXME("(%p)->()\n", This);
422     return E_NOTIMPL;
423 }
424
425 static HRESULT WINAPI HTMLBodyElement_get_onunload(IHTMLBodyElement *iface, VARIANT *p)
426 {
427     HTMLBodyElement *This = HTMLBODY_THIS(iface);
428     FIXME("(%p)->(%p)\n", This, p);
429     return E_NOTIMPL;
430 }
431
432 static HRESULT WINAPI HTMLBodyElement_put_scroll(IHTMLBodyElement *iface, BSTR v)
433 {
434     HTMLBodyElement *This = HTMLBODY_THIS(iface);
435     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
436     return E_NOTIMPL;
437 }
438
439 static HRESULT WINAPI HTMLBodyElement_get_scroll(IHTMLBodyElement *iface, BSTR *p)
440 {
441     HTMLBodyElement *This = HTMLBODY_THIS(iface);
442     FIXME("(%p)->(%p)\n", This, p);
443     return E_NOTIMPL;
444 }
445
446 static HRESULT WINAPI HTMLBodyElement_put_onselect(IHTMLBodyElement *iface, VARIANT v)
447 {
448     HTMLBodyElement *This = HTMLBODY_THIS(iface);
449     FIXME("(%p)->()\n", This);
450     return E_NOTIMPL;
451 }
452
453 static HRESULT WINAPI HTMLBodyElement_get_onselect(IHTMLBodyElement *iface, VARIANT *p)
454 {
455     HTMLBodyElement *This = HTMLBODY_THIS(iface);
456     FIXME("(%p)->(%p)\n", This, p);
457     return E_NOTIMPL;
458 }
459
460 static HRESULT WINAPI HTMLBodyElement_put_onbeforeunload(IHTMLBodyElement *iface, VARIANT v)
461 {
462     HTMLBodyElement *This = HTMLBODY_THIS(iface);
463     FIXME("(%p)->()\n", This);
464     return E_NOTIMPL;
465 }
466
467 static HRESULT WINAPI HTMLBodyElement_get_onbeforeunload(IHTMLBodyElement *iface, VARIANT *p)
468 {
469     HTMLBodyElement *This = HTMLBODY_THIS(iface);
470     FIXME("(%p)->(%p)\n", This, p);
471     return E_NOTIMPL;
472 }
473
474 static HRESULT WINAPI HTMLBodyElement_createTextRange(IHTMLBodyElement *iface, IHTMLTxtRange **range)
475 {
476     HTMLBodyElement *This = HTMLBODY_THIS(iface);
477     nsIDOMRange *nsrange = NULL;
478
479     TRACE("(%p)->(%p)\n", This, range);
480
481     if(This->textcont.element.node.doc->nscontainer) {
482         nsIDOMDocument *nsdoc;
483         nsIDOMDocumentRange *nsdocrange;
484         nsresult nsres;
485
486         nsIWebNavigation_GetDocument(This->textcont.element.node.doc->nscontainer->navigation, &nsdoc);
487         nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMDocumentRange, (void**)&nsdocrange);
488         nsIDOMDocument_Release(nsdoc);
489
490         nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &nsrange);
491         if(NS_SUCCEEDED(nsres)) {
492             nsres = nsIDOMRange_SelectNodeContents(nsrange, This->textcont.element.node.nsnode);
493             if(NS_FAILED(nsres))
494                 ERR("SelectNodeContents failed: %08x\n", nsres);
495         }else {
496             ERR("CreateRange failed: %08x\n", nsres);
497         }
498
499         nsIDOMDocumentRange_Release(nsdocrange);
500     }
501
502     *range = HTMLTxtRange_Create(This->textcont.element.node.doc, nsrange);
503     return S_OK;
504 }
505
506 #undef HTMLBODY_THIS
507
508 static const IHTMLBodyElementVtbl HTMLBodyElementVtbl = {
509     HTMLBodyElement_QueryInterface,
510     HTMLBodyElement_AddRef,
511     HTMLBodyElement_Release,
512     HTMLBodyElement_GetTypeInfoCount,
513     HTMLBodyElement_GetTypeInfo,
514     HTMLBodyElement_GetIDsOfNames,
515     HTMLBodyElement_Invoke,
516     HTMLBodyElement_put_background,
517     HTMLBodyElement_get_background,
518     HTMLBodyElement_put_bgProperties,
519     HTMLBodyElement_get_bgProperties,
520     HTMLBodyElement_put_leftMargin,
521     HTMLBodyElement_get_leftMargin,
522     HTMLBodyElement_put_topMargin,
523     HTMLBodyElement_get_topMargin,
524     HTMLBodyElement_put_rightMargin,
525     HTMLBodyElement_get_rightMargin,
526     HTMLBodyElement_put_bottomMargin,
527     HTMLBodyElement_get_bottomMargin,
528     HTMLBodyElement_put_noWrap,
529     HTMLBodyElement_get_noWrap,
530     HTMLBodyElement_put_bgColor,
531     HTMLBodyElement_get_bgColor,
532     HTMLBodyElement_put_text,
533     HTMLBodyElement_get_text,
534     HTMLBodyElement_put_link,
535     HTMLBodyElement_get_link,
536     HTMLBodyElement_put_vLink,
537     HTMLBodyElement_get_vLink,
538     HTMLBodyElement_put_aLink,
539     HTMLBodyElement_get_aLink,
540     HTMLBodyElement_put_onload,
541     HTMLBodyElement_get_onload,
542     HTMLBodyElement_put_onunload,
543     HTMLBodyElement_get_onunload,
544     HTMLBodyElement_put_scroll,
545     HTMLBodyElement_get_scroll,
546     HTMLBodyElement_put_onselect,
547     HTMLBodyElement_get_onselect,
548     HTMLBodyElement_put_onbeforeunload,
549     HTMLBodyElement_get_onbeforeunload,
550     HTMLBodyElement_createTextRange
551 };
552
553 #define HTMLBODY_NODE_THIS(iface) DEFINE_THIS2(HTMLBodyElement, textcont.element.node, iface)
554
555 static HRESULT HTMLBodyElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
556 {
557     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
558
559     *ppv = NULL;
560
561     if(IsEqualGUID(&IID_IUnknown, riid)) {
562         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
563         *ppv = HTMLBODY(This);
564     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
565         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
566         *ppv = HTMLBODY(This);
567     }else if(IsEqualGUID(&IID_IHTMLBodyElement, riid)) {
568         TRACE("(%p)->(IID_IHTMLBodyElement %p)\n", This, ppv);
569         *ppv = HTMLBODY(This);
570     }else if(IsEqualGUID(&IID_IHTMLTextContainer, riid)) {
571         TRACE("(%p)->(IID_IHTMLTextContainer %p)\n", &This->textcont, ppv);
572         *ppv = HTMLTEXTCONT(&This->textcont);
573     }
574
575     if(*ppv) {
576         IUnknown_AddRef((IUnknown*)*ppv);
577         return S_OK;
578     }
579
580     return HTMLElement_QI(&This->textcont.element.node, riid, ppv);
581 }
582
583 static void HTMLBodyElement_destructor(HTMLDOMNode *iface)
584 {
585     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
586
587     nsIDOMHTMLBodyElement_Release(This->nsbody);
588
589     HTMLElement_destructor(&This->textcont.element.node);
590 }
591
592 #undef HTMLBODY_NODE_THIS
593
594 static const NodeImplVtbl HTMLBodyElementImplVtbl = {
595     HTMLBodyElement_QI,
596     HTMLBodyElement_destructor
597 };
598
599 HTMLElement *HTMLBodyElement_Create(nsIDOMHTMLElement *nselem)
600 {
601     HTMLBodyElement *ret = heap_alloc_zero(sizeof(HTMLBodyElement));
602     nsresult nsres;
603
604     TRACE("(%p)->(%p)\n", ret, nselem);
605
606     HTMLTextContainer_Init(&ret->textcont);
607
608     ret->lpHTMLBodyElementVtbl = &HTMLBodyElementVtbl;
609     ret->textcont.element.node.vtbl = &HTMLBodyElementImplVtbl;
610
611     ConnectionPoint_Init(&ret->cp_propnotif, &ret->textcont.element.cp_container, &IID_IPropertyNotifySink);
612
613     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLBodyElement,
614                                              (void**)&ret->nsbody);
615     if(NS_FAILED(nsres))
616         ERR("Could not get nsDOMHTMLBodyElement: %08x\n", nsres);
617
618     return &ret->textcont.element;
619 }