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