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