mshtml: Implement HTMLCurrentStyle_get_borderRightWidth.
[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)  (&(x)->lpHTMLBodyElementVtbl)
46
47 static const WCHAR aquaW[] = {'a','q','u','a',0};
48 static const WCHAR blackW[] = {'b','l','a','c','k',0};
49 static const WCHAR blueW[] = {'b','l','u','e',0};
50 static const WCHAR fuchsiaW[] = {'f','u','s','h','s','i','a',0};
51 static const WCHAR grayW[] = {'g','r','a','y',0};
52 static const WCHAR greenW[] = {'g','r','e','e','n',0};
53 static const WCHAR limeW[] = {'l','i','m','e',0};
54 static const WCHAR maroonW[] = {'m','a','r','o','o','n',0};
55 static const WCHAR navyW[] = {'n','a','v','y',0};
56 static const WCHAR oliveW[] = {'o','l','i','v','e',0};
57 static const WCHAR purpleW[] = {'p','u','r','p','l','e',0};
58 static const WCHAR redW[] = {'r','e','d',0};
59 static const WCHAR silverW[] = {'s','i','l','v','e','r',0};
60 static const WCHAR tealW[] = {'t','e','a','l',0};
61 static const WCHAR whiteW[] = {'w','h','i','t','e',0};
62 static const WCHAR yellowW[] = {'y','e','l','l','o','w',0};
63
64 static const struct {
65     LPCWSTR keyword;
66     const WCHAR hexstr[8];
67 } keyword_table[] = {
68     {aquaW,     {'#','0','0','f','f','f','f',0}},
69     {blackW,    {'#','0','0','0','0','0','0',0}},
70     {blueW,     {'#','0','0','0','0','f','f',0}},
71     {fuchsiaW,  {'#','f','f','0','0','f','f',0}},
72     {grayW,     {'#','8','0','8','0','8','0',0}},
73     {greenW,    {'#','0','0','8','0','0','0',0}},
74     {limeW,     {'#','0','0','f','f','0','0',0}},
75     {maroonW,   {'#','8','0','0','0','0','0',0}},
76     {navyW,     {'#','0','0','0','0','8','0',0}},
77     {oliveW,    {'#','8','0','8','0','0','0',0}},
78     {purpleW,   {'#','8','0','0','0','8','0',0}},
79     {redW,      {'#','f','f','0','0','0','0',0}},
80     {silverW,   {'#','c','0','c','0','c','0',0}},
81     {tealW,     {'#','0','0','8','0','8','0',0}},
82     {whiteW,    {'#','f','f','f','f','f','f',0}},
83     {yellowW,   {'#','f','f','f','f','0','0',0}}
84 };
85
86 static BSTR nscolor_to_str(LPCWSTR color)
87 {
88     int i;
89
90     if(!color || *color == '#')
91         return SysAllocString(color);
92
93     for(i=0; i < sizeof(keyword_table)/sizeof(keyword_table[0]); i++) {
94         if(!strcmpiW(color, keyword_table[i].keyword))
95             return SysAllocString(keyword_table[i].hexstr);
96     }
97
98     WARN("unknown color %s\n", debugstr_w(color));
99     return SysAllocString(color);
100 }
101
102 static BOOL variant_to_nscolor(const VARIANT *v, nsAString *nsstr)
103 {
104     switch(V_VT(v)) {
105     case VT_BSTR:
106         nsAString_Init(nsstr, V_BSTR(v));
107         return TRUE;
108
109     case VT_I4: {
110         PRUnichar buf[10];
111         static const WCHAR formatW[] = {'#','%','x',0};
112
113         wsprintfW(buf, formatW, V_I4(v));
114         nsAString_Init(nsstr, buf);
115         return TRUE;
116     }
117
118     default:
119         FIXME("invalid vt=%d\n", V_VT(v));
120     }
121
122     return FALSE;
123
124 }
125
126 static void nscolor_to_variant(const nsAString *nsstr, VARIANT *p)
127 {
128     const PRUnichar *color;
129
130     nsAString_GetData(nsstr, &color);
131
132     if(*color == '#') {
133         V_VT(p) = VT_I4;
134         V_I4(p) = strtolW(color+1, NULL, 16);
135     }else {
136         V_VT(p) = VT_BSTR;
137         V_BSTR(p) = SysAllocString(color);
138     }
139 }
140
141 #define HTMLBODY_THIS(iface) DEFINE_THIS(HTMLBodyElement, HTMLBodyElement, iface)
142
143 static HRESULT WINAPI HTMLBodyElement_QueryInterface(IHTMLBodyElement *iface,
144                                                      REFIID riid, void **ppv)
145 {
146     HTMLBodyElement *This = HTMLBODY_THIS(iface);
147
148     return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(&This->textcont.element.node), riid, ppv);
149 }
150
151 static ULONG WINAPI HTMLBodyElement_AddRef(IHTMLBodyElement *iface)
152 {
153     HTMLBodyElement *This = HTMLBODY_THIS(iface);
154
155     return IHTMLDOMNode_AddRef(HTMLDOMNODE(&This->textcont.element.node));
156 }
157
158 static ULONG WINAPI HTMLBodyElement_Release(IHTMLBodyElement *iface)
159 {
160     HTMLBodyElement *This = HTMLBODY_THIS(iface);
161
162     return IHTMLDOMNode_Release(HTMLDOMNODE(&This->textcont.element.node));
163 }
164
165 static HRESULT WINAPI HTMLBodyElement_GetTypeInfoCount(IHTMLBodyElement *iface, UINT *pctinfo)
166 {
167     HTMLBodyElement *This = HTMLBODY_THIS(iface);
168     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->textcont.element.node.dispex), pctinfo);
169 }
170
171 static HRESULT WINAPI HTMLBodyElement_GetTypeInfo(IHTMLBodyElement *iface, UINT iTInfo,
172                                               LCID lcid, ITypeInfo **ppTInfo)
173 {
174     HTMLBodyElement *This = HTMLBODY_THIS(iface);
175     return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->textcont.element.node.dispex), iTInfo, lcid, ppTInfo);
176 }
177
178 static HRESULT WINAPI HTMLBodyElement_GetIDsOfNames(IHTMLBodyElement *iface, REFIID riid,
179                                                 LPOLESTR *rgszNames, UINT cNames,
180                                                 LCID lcid, DISPID *rgDispId)
181 {
182     HTMLBodyElement *This = HTMLBODY_THIS(iface);
183     return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->textcont.element.node.dispex), riid, rgszNames, cNames, lcid, rgDispId);
184 }
185
186 static HRESULT WINAPI HTMLBodyElement_Invoke(IHTMLBodyElement *iface, DISPID dispIdMember,
187                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
188                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
189 {
190     HTMLBodyElement *This = HTMLBODY_THIS(iface);
191     return IDispatchEx_Invoke(DISPATCHEX(&This->textcont.element.node.dispex), dispIdMember, riid, lcid,
192             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
193 }
194
195 static HRESULT WINAPI HTMLBodyElement_put_background(IHTMLBodyElement *iface, BSTR v)
196 {
197     HTMLBodyElement *This = HTMLBODY_THIS(iface);
198     HRESULT hr = S_OK;
199     nsAString nsstr;
200     nsresult nsres;
201
202     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
203
204     nsAString_Init(&nsstr, v);
205
206     nsres = nsIDOMHTMLBodyElement_SetBackground(This->nsbody, &nsstr);
207     if(!NS_SUCCEEDED(nsres))
208     {
209         hr = E_FAIL;
210     }
211
212     nsAString_Finish(&nsstr);
213
214     return hr;
215 }
216
217 static HRESULT WINAPI HTMLBodyElement_get_background(IHTMLBodyElement *iface, BSTR *p)
218 {
219     HTMLBodyElement *This = HTMLBODY_THIS(iface);
220     nsAString background_str;
221     nsresult nsres;
222
223     TRACE("(%p)->(%p)\n", This, p);
224
225     nsAString_Init(&background_str, NULL);
226
227     nsres = nsIDOMHTMLBodyElement_GetBackground(This->nsbody, &background_str);
228     if(NS_SUCCEEDED(nsres)) {
229         const PRUnichar *background;
230         nsAString_GetData(&background_str, &background);
231         *p = *background ? SysAllocString(background) : NULL;
232     }else {
233         ERR("GetBackground failed: %08x\n", nsres);
234         *p = NULL;
235     }
236
237     nsAString_Finish(&background_str);
238
239     TRACE("*p = %s\n", debugstr_w(*p));
240     return S_OK;
241 }
242
243 static HRESULT WINAPI HTMLBodyElement_put_bgProperties(IHTMLBodyElement *iface, BSTR v)
244 {
245     HTMLBodyElement *This = HTMLBODY_THIS(iface);
246     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
247     return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI HTMLBodyElement_get_bgProperties(IHTMLBodyElement *iface, BSTR *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_leftMargin(IHTMLBodyElement *iface, VARIANT v)
258 {
259     HTMLBodyElement *This = HTMLBODY_THIS(iface);
260     FIXME("(%p)->()\n", This);
261     return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI HTMLBodyElement_get_leftMargin(IHTMLBodyElement *iface, VARIANT *p)
265 {
266     HTMLBodyElement *This = HTMLBODY_THIS(iface);
267     FIXME("(%p)->(%p)\n", This, p);
268     return E_NOTIMPL;
269 }
270
271 static HRESULT WINAPI HTMLBodyElement_put_topMargin(IHTMLBodyElement *iface, VARIANT v)
272 {
273     HTMLBodyElement *This = HTMLBODY_THIS(iface);
274     FIXME("(%p)->()\n", This);
275     return E_NOTIMPL;
276 }
277
278 static HRESULT WINAPI HTMLBodyElement_get_topMargin(IHTMLBodyElement *iface, VARIANT *p)
279 {
280     HTMLBodyElement *This = HTMLBODY_THIS(iface);
281     FIXME("(%p)->(%p)\n", This, p);
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI HTMLBodyElement_put_rightMargin(IHTMLBodyElement *iface, VARIANT v)
286 {
287     HTMLBodyElement *This = HTMLBODY_THIS(iface);
288     FIXME("(%p)->()\n", This);
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI HTMLBodyElement_get_rightMargin(IHTMLBodyElement *iface, VARIANT *p)
293 {
294     HTMLBodyElement *This = HTMLBODY_THIS(iface);
295     FIXME("(%p)->(%p)\n", This, p);
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI HTMLBodyElement_put_bottomMargin(IHTMLBodyElement *iface, VARIANT v)
300 {
301     HTMLBodyElement *This = HTMLBODY_THIS(iface);
302     FIXME("(%p)->()\n", This);
303     return E_NOTIMPL;
304 }
305
306 static HRESULT WINAPI HTMLBodyElement_get_bottomMargin(IHTMLBodyElement *iface, VARIANT *p)
307 {
308     HTMLBodyElement *This = HTMLBODY_THIS(iface);
309     FIXME("(%p)->(%p)\n", This, p);
310     return E_NOTIMPL;
311 }
312
313 static HRESULT WINAPI HTMLBodyElement_put_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL v)
314 {
315     HTMLBodyElement *This = HTMLBODY_THIS(iface);
316     FIXME("(%p)->(%x)\n", This, v);
317     return E_NOTIMPL;
318 }
319
320 static HRESULT WINAPI HTMLBodyElement_get_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL *p)
321 {
322     HTMLBodyElement *This = HTMLBODY_THIS(iface);
323     FIXME("(%p)->(%p)\n", This, p);
324     return E_NOTIMPL;
325 }
326
327 static HRESULT WINAPI HTMLBodyElement_put_bgColor(IHTMLBodyElement *iface, VARIANT v)
328 {
329     HTMLBodyElement *This = HTMLBODY_THIS(iface);
330     nsAString strColor;
331     nsresult nsres;
332
333     TRACE("(%p)->()\n", This);
334
335     if(!variant_to_nscolor(&v, &strColor))
336         return S_OK;
337
338     nsres = nsIDOMHTMLBodyElement_SetBgColor(This->nsbody, &strColor);
339     nsAString_Finish(&strColor);
340     if(NS_FAILED(nsres))
341         ERR("SetBgColor failed: %08x\n", nsres);
342
343     return S_OK;
344 }
345
346 static HRESULT WINAPI HTMLBodyElement_get_bgColor(IHTMLBodyElement *iface, VARIANT *p)
347 {
348     HTMLBodyElement *This = HTMLBODY_THIS(iface);
349     nsAString strColor;
350     nsresult nsres;
351     const PRUnichar *color;
352
353     TRACE("(%p)->(%p)\n", This, p);
354
355     nsAString_Init(&strColor, NULL);
356     nsres = nsIDOMHTMLBodyElement_GetBgColor(This->nsbody, &strColor);
357     if(NS_FAILED(nsres))
358         ERR("SetBgColor failed: %08x\n", nsres);
359
360     nsAString_GetData(&strColor, &color);
361
362     V_VT(p) = VT_BSTR;
363     V_BSTR(p) = nscolor_to_str(color);
364
365     nsAString_Finish(&strColor);
366
367     return S_OK;
368 }
369
370 static HRESULT WINAPI HTMLBodyElement_put_text(IHTMLBodyElement *iface, VARIANT v)
371 {
372     HTMLBodyElement *This = HTMLBODY_THIS(iface);
373     nsAString text;
374     nsresult nsres;
375
376     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
377
378     if(!variant_to_nscolor(&v, &text))
379         return S_OK;
380
381     nsres = nsIDOMHTMLBodyElement_SetText(This->nsbody, &text);
382     nsAString_Finish(&text);
383
384     return S_OK;
385 }
386
387 static HRESULT WINAPI HTMLBodyElement_get_text(IHTMLBodyElement *iface, VARIANT *p)
388 {
389     HTMLBodyElement *This = HTMLBODY_THIS(iface);
390     nsAString text;
391     nsresult nsres;
392
393     TRACE("(%p)->(%p)\n", This, p);
394
395     nsAString_Init(&text, NULL);
396
397     V_VT(p) = VT_BSTR;
398     V_BSTR(p) = NULL;
399
400     nsres = nsIDOMHTMLBodyElement_GetText(This->nsbody, &text);
401     if(NS_SUCCEEDED(nsres))
402     {
403         const PRUnichar *sText;
404         nsAString_GetData(&text, &sText);
405
406         V_VT(p) = VT_BSTR;
407         V_BSTR(p) = SysAllocString(sText);
408     }
409
410     nsAString_Finish(&text);
411
412     return S_OK;
413 }
414
415 static HRESULT WINAPI HTMLBodyElement_put_link(IHTMLBodyElement *iface, VARIANT v)
416 {
417     HTMLBodyElement *This = HTMLBODY_THIS(iface);
418     nsAString link_str;
419     nsresult nsres;
420
421     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
422
423     if(!variant_to_nscolor(&v, &link_str))
424         return S_OK;
425
426     nsres = nsIDOMHTMLBodyElement_SetLink(This->nsbody, &link_str);
427     nsAString_Finish(&link_str);
428     if(NS_FAILED(nsres))
429         ERR("SetLink failed: %08x\n", nsres);
430
431     return S_OK;
432 }
433
434 static HRESULT WINAPI HTMLBodyElement_get_link(IHTMLBodyElement *iface, VARIANT *p)
435 {
436     HTMLBodyElement *This = HTMLBODY_THIS(iface);
437     nsAString link_str;
438     nsresult nsres;
439
440     TRACE("(%p)->(%p)\n", This, p);
441
442     nsAString_Init(&link_str, NULL);
443     nsres = nsIDOMHTMLBodyElement_GetLink(This->nsbody, &link_str);
444     if(NS_FAILED(nsres))
445         ERR("GetLink failed: %08x\n", nsres);
446
447     nscolor_to_variant(&link_str, p);
448     nsAString_Finish(&link_str);
449
450     return S_OK;
451 }
452
453 static HRESULT WINAPI HTMLBodyElement_put_vLink(IHTMLBodyElement *iface, VARIANT v)
454 {
455     HTMLBodyElement *This = HTMLBODY_THIS(iface);
456     nsAString vlink_str;
457     nsresult nsres;
458
459     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
460
461     if(!variant_to_nscolor(&v, &vlink_str))
462         return S_OK;
463
464     nsres = nsIDOMHTMLBodyElement_SetVLink(This->nsbody, &vlink_str);
465     nsAString_Finish(&vlink_str);
466     if(NS_FAILED(nsres))
467         ERR("SetLink failed: %08x\n", nsres);
468
469     return S_OK;
470 }
471
472 static HRESULT WINAPI HTMLBodyElement_get_vLink(IHTMLBodyElement *iface, VARIANT *p)
473 {
474     HTMLBodyElement *This = HTMLBODY_THIS(iface);
475     nsAString vlink_str;
476     nsresult nsres;
477
478     TRACE("(%p)->(%p)\n", This, p);
479
480     nsAString_Init(&vlink_str, NULL);
481     nsres = nsIDOMHTMLBodyElement_GetVLink(This->nsbody, &vlink_str);
482     if(NS_FAILED(nsres))
483         ERR("GetLink failed: %08x\n", nsres);
484
485     nscolor_to_variant(&vlink_str, p);
486     nsAString_Finish(&vlink_str);
487
488     return S_OK;
489 }
490
491 static HRESULT WINAPI HTMLBodyElement_put_aLink(IHTMLBodyElement *iface, VARIANT v)
492 {
493     HTMLBodyElement *This = HTMLBODY_THIS(iface);
494     nsAString alink_str;
495     nsresult nsres;
496
497     TRACE("(%p)->(v%d)\n", This, V_VT(&v));
498
499     if(!variant_to_nscolor(&v, &alink_str))
500         return S_OK;
501
502     nsres = nsIDOMHTMLBodyElement_SetALink(This->nsbody, &alink_str);
503     nsAString_Finish(&alink_str);
504     if(NS_FAILED(nsres))
505         ERR("SetALink failed: %08x\n", nsres);
506
507     return S_OK;
508 }
509
510 static HRESULT WINAPI HTMLBodyElement_get_aLink(IHTMLBodyElement *iface, VARIANT *p)
511 {
512     HTMLBodyElement *This = HTMLBODY_THIS(iface);
513     nsAString alink_str;
514     nsresult nsres;
515
516     TRACE("(%p)->(%p)\n", This, p);
517
518     nsAString_Init(&alink_str, NULL);
519     nsres = nsIDOMHTMLBodyElement_GetALink(This->nsbody, &alink_str);
520     if(NS_FAILED(nsres))
521         ERR("GetALink failed: %08x\n", nsres);
522
523     nscolor_to_variant(&alink_str, p);
524     nsAString_Finish(&alink_str);
525
526     return S_OK;
527 }
528
529 static HRESULT WINAPI HTMLBodyElement_put_onload(IHTMLBodyElement *iface, VARIANT v)
530 {
531     HTMLBodyElement *This = HTMLBODY_THIS(iface);
532     FIXME("(%p)->()\n", This);
533     return E_NOTIMPL;
534 }
535
536 static HRESULT WINAPI HTMLBodyElement_get_onload(IHTMLBodyElement *iface, VARIANT *p)
537 {
538     HTMLBodyElement *This = HTMLBODY_THIS(iface);
539     FIXME("(%p)->(%p)\n", This, p);
540     return E_NOTIMPL;
541 }
542
543 static HRESULT WINAPI HTMLBodyElement_put_onunload(IHTMLBodyElement *iface, VARIANT v)
544 {
545     HTMLBodyElement *This = HTMLBODY_THIS(iface);
546     FIXME("(%p)->()\n", This);
547     return E_NOTIMPL;
548 }
549
550 static HRESULT WINAPI HTMLBodyElement_get_onunload(IHTMLBodyElement *iface, VARIANT *p)
551 {
552     HTMLBodyElement *This = HTMLBODY_THIS(iface);
553     FIXME("(%p)->(%p)\n", This, p);
554     return E_NOTIMPL;
555 }
556
557 static HRESULT WINAPI HTMLBodyElement_put_scroll(IHTMLBodyElement *iface, BSTR v)
558 {
559     HTMLBodyElement *This = HTMLBODY_THIS(iface);
560     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
561     return E_NOTIMPL;
562 }
563
564 static HRESULT WINAPI HTMLBodyElement_get_scroll(IHTMLBodyElement *iface, BSTR *p)
565 {
566     HTMLBodyElement *This = HTMLBODY_THIS(iface);
567     FIXME("(%p)->(%p)\n", This, p);
568     return E_NOTIMPL;
569 }
570
571 static HRESULT WINAPI HTMLBodyElement_put_onselect(IHTMLBodyElement *iface, VARIANT v)
572 {
573     HTMLBodyElement *This = HTMLBODY_THIS(iface);
574     FIXME("(%p)->()\n", This);
575     return E_NOTIMPL;
576 }
577
578 static HRESULT WINAPI HTMLBodyElement_get_onselect(IHTMLBodyElement *iface, VARIANT *p)
579 {
580     HTMLBodyElement *This = HTMLBODY_THIS(iface);
581     FIXME("(%p)->(%p)\n", This, p);
582     return E_NOTIMPL;
583 }
584
585 static HRESULT WINAPI HTMLBodyElement_put_onbeforeunload(IHTMLBodyElement *iface, VARIANT v)
586 {
587     HTMLBodyElement *This = HTMLBODY_THIS(iface);
588     FIXME("(%p)->()\n", This);
589     return E_NOTIMPL;
590 }
591
592 static HRESULT WINAPI HTMLBodyElement_get_onbeforeunload(IHTMLBodyElement *iface, VARIANT *p)
593 {
594     HTMLBodyElement *This = HTMLBODY_THIS(iface);
595     FIXME("(%p)->(%p)\n", This, p);
596     return E_NOTIMPL;
597 }
598
599 static HRESULT WINAPI HTMLBodyElement_createTextRange(IHTMLBodyElement *iface, IHTMLTxtRange **range)
600 {
601     HTMLBodyElement *This = HTMLBODY_THIS(iface);
602     nsIDOMDocumentRange *nsdocrange;
603     nsIDOMRange *nsrange = NULL;
604     nsresult nsres;
605
606     TRACE("(%p)->(%p)\n", This, range);
607
608     if(!This->textcont.element.node.doc->nsdoc) {
609         WARN("No nsdoc\n");
610         return E_UNEXPECTED;
611     }
612
613     nsres = nsIDOMDocument_QueryInterface(This->textcont.element.node.doc->nsdoc, &IID_nsIDOMDocumentRange,
614             (void**)&nsdocrange);
615     if(NS_FAILED(nsres)) {
616         ERR("Could not get nsIDOMDocumentRabge iface: %08x\n", nsres);
617         return E_FAIL;
618     }
619
620     nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &nsrange);
621     if(NS_SUCCEEDED(nsres)) {
622         nsres = nsIDOMRange_SelectNodeContents(nsrange, This->textcont.element.node.nsnode);
623         if(NS_FAILED(nsres))
624             ERR("SelectNodeContents failed: %08x\n", nsres);
625     }else {
626         ERR("CreateRange failed: %08x\n", nsres);
627     }
628
629     nsIDOMDocumentRange_Release(nsdocrange);
630
631     *range = HTMLTxtRange_Create(This->textcont.element.node.doc, nsrange);
632     return S_OK;
633 }
634
635 #undef HTMLBODY_THIS
636
637 static const IHTMLBodyElementVtbl HTMLBodyElementVtbl = {
638     HTMLBodyElement_QueryInterface,
639     HTMLBodyElement_AddRef,
640     HTMLBodyElement_Release,
641     HTMLBodyElement_GetTypeInfoCount,
642     HTMLBodyElement_GetTypeInfo,
643     HTMLBodyElement_GetIDsOfNames,
644     HTMLBodyElement_Invoke,
645     HTMLBodyElement_put_background,
646     HTMLBodyElement_get_background,
647     HTMLBodyElement_put_bgProperties,
648     HTMLBodyElement_get_bgProperties,
649     HTMLBodyElement_put_leftMargin,
650     HTMLBodyElement_get_leftMargin,
651     HTMLBodyElement_put_topMargin,
652     HTMLBodyElement_get_topMargin,
653     HTMLBodyElement_put_rightMargin,
654     HTMLBodyElement_get_rightMargin,
655     HTMLBodyElement_put_bottomMargin,
656     HTMLBodyElement_get_bottomMargin,
657     HTMLBodyElement_put_noWrap,
658     HTMLBodyElement_get_noWrap,
659     HTMLBodyElement_put_bgColor,
660     HTMLBodyElement_get_bgColor,
661     HTMLBodyElement_put_text,
662     HTMLBodyElement_get_text,
663     HTMLBodyElement_put_link,
664     HTMLBodyElement_get_link,
665     HTMLBodyElement_put_vLink,
666     HTMLBodyElement_get_vLink,
667     HTMLBodyElement_put_aLink,
668     HTMLBodyElement_get_aLink,
669     HTMLBodyElement_put_onload,
670     HTMLBodyElement_get_onload,
671     HTMLBodyElement_put_onunload,
672     HTMLBodyElement_get_onunload,
673     HTMLBodyElement_put_scroll,
674     HTMLBodyElement_get_scroll,
675     HTMLBodyElement_put_onselect,
676     HTMLBodyElement_get_onselect,
677     HTMLBodyElement_put_onbeforeunload,
678     HTMLBodyElement_get_onbeforeunload,
679     HTMLBodyElement_createTextRange
680 };
681
682 #define HTMLBODY_NODE_THIS(iface) DEFINE_THIS2(HTMLBodyElement, textcont.element.node, iface)
683
684 static HRESULT HTMLBodyElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
685 {
686     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
687
688     *ppv = NULL;
689
690     if(IsEqualGUID(&IID_IUnknown, riid)) {
691         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
692         *ppv = HTMLBODY(This);
693     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
694         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
695         *ppv = HTMLBODY(This);
696     }else if(IsEqualGUID(&IID_IHTMLBodyElement, riid)) {
697         TRACE("(%p)->(IID_IHTMLBodyElement %p)\n", This, ppv);
698         *ppv = HTMLBODY(This);
699     }else if(IsEqualGUID(&IID_IHTMLTextContainer, riid)) {
700         TRACE("(%p)->(IID_IHTMLTextContainer %p)\n", &This->textcont, ppv);
701         *ppv = HTMLTEXTCONT(&This->textcont);
702     }
703
704     if(*ppv) {
705         IUnknown_AddRef((IUnknown*)*ppv);
706         return S_OK;
707     }
708
709     return HTMLElement_QI(&This->textcont.element.node, riid, ppv);
710 }
711
712 static void HTMLBodyElement_destructor(HTMLDOMNode *iface)
713 {
714     HTMLBodyElement *This = HTMLBODY_NODE_THIS(iface);
715
716     nsIDOMHTMLBodyElement_Release(This->nsbody);
717
718     HTMLElement_destructor(&This->textcont.element.node);
719 }
720
721 #undef HTMLBODY_NODE_THIS
722
723 static const NodeImplVtbl HTMLBodyElementImplVtbl = {
724     HTMLBodyElement_QI,
725     HTMLBodyElement_destructor
726 };
727
728 static const tid_t HTMLBodyElement_iface_tids[] = {
729     IHTMLBodyElement_tid,
730     IHTMLBodyElement2_tid,
731     IHTMLDOMNode_tid,
732     IHTMLDOMNode2_tid,
733     IHTMLElement_tid,
734     IHTMLElement2_tid,
735     IHTMLElement3_tid,
736     IHTMLElement4_tid,
737     IHTMLTextContainer_tid,
738     IHTMLUniqueName_tid,
739     0
740 };
741
742 static dispex_static_data_t HTMLBodyElement_dispex = {
743     NULL,
744     DispHTMLBody_tid,
745     NULL,
746     HTMLBodyElement_iface_tids
747 };
748
749 HTMLElement *HTMLBodyElement_Create(nsIDOMHTMLElement *nselem)
750 {
751     HTMLBodyElement *ret = heap_alloc_zero(sizeof(HTMLBodyElement));
752     nsresult nsres;
753
754     TRACE("(%p)->(%p)\n", ret, nselem);
755
756     HTMLTextContainer_Init(&ret->textcont);
757
758     ret->lpHTMLBodyElementVtbl = &HTMLBodyElementVtbl;
759
760     init_dispex(&ret->textcont.element.node.dispex, (IUnknown*)HTMLBODY(ret), &HTMLBodyElement_dispex);
761     ret->textcont.element.node.vtbl = &HTMLBodyElementImplVtbl;
762
763     ConnectionPoint_Init(&ret->cp_propnotif, &ret->textcont.element.cp_container, &IID_IPropertyNotifySink);
764
765     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLBodyElement,
766                                              (void**)&ret->nsbody);
767     if(NS_FAILED(nsres))
768         ERR("Could not get nsDOMHTMLBodyElement: %08x\n", nsres);
769
770     return &ret->textcont.element;
771 }