htmlbody.c 23.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright 2006 Jacek Caban for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 */

#include <stdarg.h>
#include <stdio.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"

#include "wine/debug.h"

#include "mshtml_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(mshtml);

typedef struct {
36
    HTMLTextContainer textcont;
37

38
    IHTMLBodyElement IHTMLBodyElement_iface;
39

40
    ConnectionPoint cp_propnotif;
41

42 43 44
    nsIDOMHTMLBodyElement *nsbody;
} HTMLBodyElement;

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
static const WCHAR aquaW[] = {'a','q','u','a',0};
static const WCHAR blackW[] = {'b','l','a','c','k',0};
static const WCHAR blueW[] = {'b','l','u','e',0};
static const WCHAR fuchsiaW[] = {'f','u','s','h','s','i','a',0};
static const WCHAR grayW[] = {'g','r','a','y',0};
static const WCHAR greenW[] = {'g','r','e','e','n',0};
static const WCHAR limeW[] = {'l','i','m','e',0};
static const WCHAR maroonW[] = {'m','a','r','o','o','n',0};
static const WCHAR navyW[] = {'n','a','v','y',0};
static const WCHAR oliveW[] = {'o','l','i','v','e',0};
static const WCHAR purpleW[] = {'p','u','r','p','l','e',0};
static const WCHAR redW[] = {'r','e','d',0};
static const WCHAR silverW[] = {'s','i','l','v','e','r',0};
static const WCHAR tealW[] = {'t','e','a','l',0};
static const WCHAR whiteW[] = {'w','h','i','t','e',0};
static const WCHAR yellowW[] = {'y','e','l','l','o','w',0};

static const struct {
    LPCWSTR keyword;
64
    DWORD rgb;
65
} keyword_table[] = {
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
    {aquaW,     0x00ffff},
    {blackW,    0x000000},
    {blueW,     0x0000ff},
    {fuchsiaW,  0xff00ff},
    {grayW,     0x808080},
    {greenW,    0x008000},
    {limeW,     0x00ff00},
    {maroonW,   0x800000},
    {navyW,     0x000080},
    {oliveW,    0x808000},
    {purpleW,   0x800080},
    {redW,      0xff0000},
    {silverW,   0xc0c0c0},
    {tealW,     0x008080},
    {whiteW,    0xffffff},
    {yellowW,   0xffff00}
82 83
};

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
static int comp_value(const WCHAR *ptr, int dpc)
{
    int ret = 0;
    WCHAR ch;

    if(dpc > 2)
        dpc = 2;

    while(dpc--) {
        if(!*ptr)
            ret *= 16;
        else if(isdigitW(ch = *ptr++))
            ret = ret*16 + (ch-'0');
        else if('a' <= ch && ch <= 'f')
            ret = ret*16 + (ch-'a') + 10;
        else if('A' <= ch && ch <= 'F')
            ret = ret*16 + (ch-'A') + 10;
        else
            ret *= 16;
    }

    return ret;
}

/* Based on Gecko NS_LooseHexToRGB */
static int loose_hex_to_rgb(const WCHAR *hex)
{
    int len, dpc;

    len = strlenW(hex);
    if(*hex == '#') {
        hex++;
        len--;
    }
    if(len <= 3)
        return 0;

    dpc = min(len/3 + (len%3 ? 1 : 0), 4);
    return (comp_value(hex, dpc) << 16)
        | (comp_value(hex+dpc, dpc) << 8)
        | comp_value(hex+2*dpc, dpc);
}

127
static HRESULT nscolor_to_str(LPCWSTR color, BSTR *ret)
128
{
129 130 131
    int i, rgb = -1;

    static const WCHAR formatW[] = {'#','%','0','2','x','%','0','2','x','%','0','2','x',0};
132

133 134 135
    if(!color || !*color) {
        *ret = NULL;
        return S_OK;
136
    }
137

138 139 140 141
    if(*color != '#') {
        for(i=0; i < sizeof(keyword_table)/sizeof(keyword_table[0]); i++) {
            if(!strcmpiW(color, keyword_table[i].keyword))
                rgb = keyword_table[i].rgb;
142
        }
143
    }
144 145
    if(rgb == -1)
        rgb = loose_hex_to_rgb(color);
146 147 148 149 150 151

    *ret = SysAllocStringLen(NULL, 7);
    if(!*ret)
        return E_OUTOFMEMORY;

    sprintfW(*ret, formatW, rgb>>16, (rgb>>8)&0xff, rgb&0xff);
152

153 154
    TRACE("%s -> %s\n", debugstr_w(color), debugstr_w(*ret));
    return S_OK;
155 156
}

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
static BOOL variant_to_nscolor(const VARIANT *v, nsAString *nsstr)
{
    switch(V_VT(v)) {
    case VT_BSTR:
        nsAString_Init(nsstr, V_BSTR(v));
        return TRUE;

    case VT_I4: {
        PRUnichar buf[10];
        static const WCHAR formatW[] = {'#','%','x',0};

        wsprintfW(buf, formatW, V_I4(v));
        nsAString_Init(nsstr, buf);
        return TRUE;
    }

    default:
174
        FIXME("invalid color %s\n", debugstr_variant(v));
175 176 177 178 179 180
    }

    return FALSE;

}

181
static HRESULT return_nscolor(nsresult nsres, nsAString *nsstr, VARIANT *p)
182 183 184
{
    const PRUnichar *color;

185 186 187 188 189 190
    if(NS_FAILED(nsres)) {
        ERR("failed: %08x\n", nsres);
        nsAString_Finish(nsstr);
        return E_FAIL;
    }

191 192 193 194 195 196 197 198
    nsAString_GetData(nsstr, &color);

    if(*color == '#') {
        V_VT(p) = VT_I4;
        V_I4(p) = strtolW(color+1, NULL, 16);
    }else {
        V_VT(p) = VT_BSTR;
        V_BSTR(p) = SysAllocString(color);
199 200 201 202
        if(!V_BSTR(p)) {
            nsAString_Finish(nsstr);
            return E_OUTOFMEMORY;
        }
203
    }
204 205 206 207

    nsAString_Finish(nsstr);
    TRACE("ret %s\n", debugstr_variant(p));
    return S_OK;
208 209
}

210 211 212 213
static inline HTMLBodyElement *impl_from_IHTMLBodyElement(IHTMLBodyElement *iface)
{
    return CONTAINING_RECORD(iface, HTMLBodyElement, IHTMLBodyElement_iface);
}
214 215 216 217

static HRESULT WINAPI HTMLBodyElement_QueryInterface(IHTMLBodyElement *iface,
                                                     REFIID riid, void **ppv)
{
218
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
219

220
    return IHTMLDOMNode_QueryInterface(&This->textcont.element.node.IHTMLDOMNode_iface, riid, ppv);
221 222 223 224
}

static ULONG WINAPI HTMLBodyElement_AddRef(IHTMLBodyElement *iface)
{
225
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
226

227
    return IHTMLDOMNode_AddRef(&This->textcont.element.node.IHTMLDOMNode_iface);
228 229 230 231
}

static ULONG WINAPI HTMLBodyElement_Release(IHTMLBodyElement *iface)
{
232
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
233

234
    return IHTMLDOMNode_Release(&This->textcont.element.node.IHTMLDOMNode_iface);
235 236 237 238
}

static HRESULT WINAPI HTMLBodyElement_GetTypeInfoCount(IHTMLBodyElement *iface, UINT *pctinfo)
{
239
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
240 241
    return IDispatchEx_GetTypeInfoCount(&This->textcont.element.node.dispex.IDispatchEx_iface,
            pctinfo);
242 243 244 245 246
}

static HRESULT WINAPI HTMLBodyElement_GetTypeInfo(IHTMLBodyElement *iface, UINT iTInfo,
                                              LCID lcid, ITypeInfo **ppTInfo)
{
247
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
248 249
    return IDispatchEx_GetTypeInfo(&This->textcont.element.node.dispex.IDispatchEx_iface, iTInfo,
            lcid, ppTInfo);
250 251 252 253 254 255
}

static HRESULT WINAPI HTMLBodyElement_GetIDsOfNames(IHTMLBodyElement *iface, REFIID riid,
                                                LPOLESTR *rgszNames, UINT cNames,
                                                LCID lcid, DISPID *rgDispId)
{
256
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
257 258
    return IDispatchEx_GetIDsOfNames(&This->textcont.element.node.dispex.IDispatchEx_iface, riid,
            rgszNames, cNames, lcid, rgDispId);
259 260 261 262 263 264
}

static HRESULT WINAPI HTMLBodyElement_Invoke(IHTMLBodyElement *iface, DISPID dispIdMember,
                            REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
                            VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
265
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
266 267
    return IDispatchEx_Invoke(&This->textcont.element.node.dispex.IDispatchEx_iface, dispIdMember,
            riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
268 269 270 271
}

static HRESULT WINAPI HTMLBodyElement_put_background(IHTMLBodyElement *iface, BSTR v)
{
272
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
273 274 275 276 277
    nsAString nsstr;
    nsresult nsres;

    TRACE("(%p)->(%s)\n", This, debugstr_w(v));

278
    nsAString_InitDepend(&nsstr, v);
279 280
    nsres = nsIDOMHTMLBodyElement_SetBackground(This->nsbody, &nsstr);
    nsAString_Finish(&nsstr);
281 282
    if(NS_FAILED(nsres))
        return E_FAIL;
283

284
    return S_OK;
285 286 287 288
}

static HRESULT WINAPI HTMLBodyElement_get_background(IHTMLBodyElement *iface, BSTR *p)
{
289
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
290 291 292 293 294 295 296
    nsAString background_str;
    nsresult nsres;

    TRACE("(%p)->(%p)\n", This, p);

    nsAString_Init(&background_str, NULL);
    nsres = nsIDOMHTMLBodyElement_GetBackground(This->nsbody, &background_str);
297
    return return_nsstr(nsres, &background_str, p);
298 299 300 301
}

static HRESULT WINAPI HTMLBodyElement_put_bgProperties(IHTMLBodyElement *iface, BSTR v)
{
302
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
303
    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
304 305 306 307 308
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_bgProperties(IHTMLBodyElement *iface, BSTR *p)
{
309
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
310
    FIXME("(%p)->(%p)\n", This, p);
311 312 313 314 315
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_leftMargin(IHTMLBodyElement *iface, VARIANT v)
{
316
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
317
    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
318 319 320 321 322
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_leftMargin(IHTMLBodyElement *iface, VARIANT *p)
{
323
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
324
    FIXME("(%p)->(%p)\n", This, p);
325 326 327 328 329
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_topMargin(IHTMLBodyElement *iface, VARIANT v)
{
330
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
331
    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
332 333 334 335 336
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_topMargin(IHTMLBodyElement *iface, VARIANT *p)
{
337
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
338
    FIXME("(%p)->(%p)\n", This, p);
339 340 341 342 343
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_rightMargin(IHTMLBodyElement *iface, VARIANT v)
{
344
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
345
    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
346 347 348 349 350
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_rightMargin(IHTMLBodyElement *iface, VARIANT *p)
{
351
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
352
    FIXME("(%p)->(%p)\n", This, p);
353 354 355 356 357
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_bottomMargin(IHTMLBodyElement *iface, VARIANT v)
{
358
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
359
    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
360 361 362 363 364
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_bottomMargin(IHTMLBodyElement *iface, VARIANT *p)
{
365
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
366
    FIXME("(%p)->(%p)\n", This, p);
367 368 369 370 371
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL v)
{
372
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
373
    FIXME("(%p)->(%x)\n", This, v);
374 375 376 377 378
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_noWrap(IHTMLBodyElement *iface, VARIANT_BOOL *p)
{
379
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
380
    FIXME("(%p)->(%p)\n", This, p);
381 382 383 384 385
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_bgColor(IHTMLBodyElement *iface, VARIANT v)
{
386
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
387 388 389
    nsAString strColor;
    nsresult nsres;

390
    TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
391 392 393 394 395 396 397 398 399 400

    if(!variant_to_nscolor(&v, &strColor))
        return S_OK;

    nsres = nsIDOMHTMLBodyElement_SetBgColor(This->nsbody, &strColor);
    nsAString_Finish(&strColor);
    if(NS_FAILED(nsres))
        ERR("SetBgColor failed: %08x\n", nsres);

    return S_OK;
401 402 403 404
}

static HRESULT WINAPI HTMLBodyElement_get_bgColor(IHTMLBodyElement *iface, VARIANT *p)
{
405
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
406 407
    nsAString strColor;
    nsresult nsres;
408
    HRESULT hres;
409 410 411 412 413

    TRACE("(%p)->(%p)\n", This, p);

    nsAString_Init(&strColor, NULL);
    nsres = nsIDOMHTMLBodyElement_GetBgColor(This->nsbody, &strColor);
414 415
    if(NS_SUCCEEDED(nsres)) {
        const PRUnichar *color;
416

417 418 419 420 421 422 423
        nsAString_GetData(&strColor, &color);
        V_VT(p) = VT_BSTR;
        hres = nscolor_to_str(color, &V_BSTR(p));
    }else {
        ERR("SetBgColor failed: %08x\n", nsres);
        hres = E_FAIL;
    }
424 425

    nsAString_Finish(&strColor);
426
    return hres;
427 428 429 430
}

static HRESULT WINAPI HTMLBodyElement_put_text(IHTMLBodyElement *iface, VARIANT v)
{
431
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
432 433 434
    nsAString text;
    nsresult nsres;

435
    TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
436 437 438 439 440 441

    if(!variant_to_nscolor(&v, &text))
        return S_OK;

    nsres = nsIDOMHTMLBodyElement_SetText(This->nsbody, &text);
    nsAString_Finish(&text);
442 443 444 445
    if(NS_FAILED(nsres)) {
        ERR("SetText failed: %08x\n", nsres);
        return E_FAIL;
    }
446 447

    return S_OK;
448 449 450 451
}

static HRESULT WINAPI HTMLBodyElement_get_text(IHTMLBodyElement *iface, VARIANT *p)
{
452
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
453 454
    nsAString text;
    nsresult nsres;
455
    HRESULT hres;
456 457 458 459 460

    TRACE("(%p)->(%p)\n", This, p);

    nsAString_Init(&text, NULL);
    nsres = nsIDOMHTMLBodyElement_GetText(This->nsbody, &text);
461 462
    if(NS_SUCCEEDED(nsres)) {
        const PRUnichar *color;
463

464
        nsAString_GetData(&text, &color);
465
        V_VT(p) = VT_BSTR;
466 467 468 469
        hres = nscolor_to_str(color, &V_BSTR(p));
    }else {
        ERR("GetText failed: %08x\n", nsres);
        hres = E_FAIL;
470 471 472 473
    }

    nsAString_Finish(&text);

474
    return hres;
475 476 477 478
}

static HRESULT WINAPI HTMLBodyElement_put_link(IHTMLBodyElement *iface, VARIANT v)
{
479
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
480 481 482
    nsAString link_str;
    nsresult nsres;

483
    TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
484 485 486 487 488 489 490 491 492 493

    if(!variant_to_nscolor(&v, &link_str))
        return S_OK;

    nsres = nsIDOMHTMLBodyElement_SetLink(This->nsbody, &link_str);
    nsAString_Finish(&link_str);
    if(NS_FAILED(nsres))
        ERR("SetLink failed: %08x\n", nsres);

    return S_OK;
494 495 496 497
}

static HRESULT WINAPI HTMLBodyElement_get_link(IHTMLBodyElement *iface, VARIANT *p)
{
498
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
499 500 501 502 503 504 505
    nsAString link_str;
    nsresult nsres;

    TRACE("(%p)->(%p)\n", This, p);

    nsAString_Init(&link_str, NULL);
    nsres = nsIDOMHTMLBodyElement_GetLink(This->nsbody, &link_str);
506
    return return_nscolor(nsres, &link_str, p);
507 508 509 510
}

static HRESULT WINAPI HTMLBodyElement_put_vLink(IHTMLBodyElement *iface, VARIANT v)
{
511
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
512 513 514
    nsAString vlink_str;
    nsresult nsres;

515
    TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
516 517 518 519 520 521 522 523 524 525

    if(!variant_to_nscolor(&v, &vlink_str))
        return S_OK;

    nsres = nsIDOMHTMLBodyElement_SetVLink(This->nsbody, &vlink_str);
    nsAString_Finish(&vlink_str);
    if(NS_FAILED(nsres))
        ERR("SetLink failed: %08x\n", nsres);

    return S_OK;
526 527 528 529
}

static HRESULT WINAPI HTMLBodyElement_get_vLink(IHTMLBodyElement *iface, VARIANT *p)
{
530
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
531 532 533 534 535 536 537
    nsAString vlink_str;
    nsresult nsres;

    TRACE("(%p)->(%p)\n", This, p);

    nsAString_Init(&vlink_str, NULL);
    nsres = nsIDOMHTMLBodyElement_GetVLink(This->nsbody, &vlink_str);
538
    return return_nscolor(nsres, &vlink_str, p);
539 540 541 542
}

static HRESULT WINAPI HTMLBodyElement_put_aLink(IHTMLBodyElement *iface, VARIANT v)
{
543
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
544 545 546
    nsAString alink_str;
    nsresult nsres;

547
    TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
548 549 550 551 552 553 554 555 556 557

    if(!variant_to_nscolor(&v, &alink_str))
        return S_OK;

    nsres = nsIDOMHTMLBodyElement_SetALink(This->nsbody, &alink_str);
    nsAString_Finish(&alink_str);
    if(NS_FAILED(nsres))
        ERR("SetALink failed: %08x\n", nsres);

    return S_OK;
558 559 560 561
}

static HRESULT WINAPI HTMLBodyElement_get_aLink(IHTMLBodyElement *iface, VARIANT *p)
{
562
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
563 564 565 566 567 568 569
    nsAString alink_str;
    nsresult nsres;

    TRACE("(%p)->(%p)\n", This, p);

    nsAString_Init(&alink_str, NULL);
    nsres = nsIDOMHTMLBodyElement_GetALink(This->nsbody, &alink_str);
570
    return return_nscolor(nsres, &alink_str, p);
571 572 573 574
}

static HRESULT WINAPI HTMLBodyElement_put_onload(IHTMLBodyElement *iface, VARIANT v)
{
575
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
576
    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
577 578 579 580 581
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_onload(IHTMLBodyElement *iface, VARIANT *p)
{
582
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
583
    FIXME("(%p)->(%p)\n", This, p);
584 585 586 587 588
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_onunload(IHTMLBodyElement *iface, VARIANT v)
{
589
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
590
    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
591 592 593 594 595
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_onunload(IHTMLBodyElement *iface, VARIANT *p)
{
596
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
597
    FIXME("(%p)->(%p)\n", This, p);
598 599 600 601 602
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_scroll(IHTMLBodyElement *iface, BSTR v)
{
603
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
604
    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
605 606 607 608 609
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_scroll(IHTMLBodyElement *iface, BSTR *p)
{
610
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
611
    FIXME("(%p)->(%p)\n", This, p);
612 613 614 615 616
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_onselect(IHTMLBodyElement *iface, VARIANT v)
{
617
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
618
    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
619 620 621 622 623
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_onselect(IHTMLBodyElement *iface, VARIANT *p)
{
624
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
625
    FIXME("(%p)->(%p)\n", This, p);
626 627 628 629 630
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_put_onbeforeunload(IHTMLBodyElement *iface, VARIANT v)
{
631
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
632
    FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
633 634 635 636 637
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_get_onbeforeunload(IHTMLBodyElement *iface, VARIANT *p)
{
638
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
639
    FIXME("(%p)->(%p)\n", This, p);
640 641 642 643 644
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLBodyElement_createTextRange(IHTMLBodyElement *iface, IHTMLTxtRange **range)
{
645
    HTMLBodyElement *This = impl_from_IHTMLBodyElement(iface);
646
    nsIDOMRange *nsrange = NULL;
647
    nsresult nsres;
648
    HRESULT hres;
649 650 651

    TRACE("(%p)->(%p)\n", This, range);

652
    if(!This->textcont.element.node.doc->nsdoc) {
653 654 655 656
        WARN("No nsdoc\n");
        return E_UNEXPECTED;
    }

657
    nsres = nsIDOMHTMLDocument_CreateRange(This->textcont.element.node.doc->nsdoc, &nsrange);
658 659 660 661 662 663
    if(NS_SUCCEEDED(nsres)) {
        nsres = nsIDOMRange_SelectNodeContents(nsrange, This->textcont.element.node.nsnode);
        if(NS_FAILED(nsres))
            ERR("SelectNodeContents failed: %08x\n", nsres);
    }else {
        ERR("CreateRange failed: %08x\n", nsres);
664 665
    }

666
    hres = HTMLTxtRange_Create(This->textcont.element.node.doc->basedoc.doc_node, nsrange, range);
667 668 669

    nsIDOMRange_Release(nsrange);
    return hres;
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
}

static const IHTMLBodyElementVtbl HTMLBodyElementVtbl = {
    HTMLBodyElement_QueryInterface,
    HTMLBodyElement_AddRef,
    HTMLBodyElement_Release,
    HTMLBodyElement_GetTypeInfoCount,
    HTMLBodyElement_GetTypeInfo,
    HTMLBodyElement_GetIDsOfNames,
    HTMLBodyElement_Invoke,
    HTMLBodyElement_put_background,
    HTMLBodyElement_get_background,
    HTMLBodyElement_put_bgProperties,
    HTMLBodyElement_get_bgProperties,
    HTMLBodyElement_put_leftMargin,
    HTMLBodyElement_get_leftMargin,
    HTMLBodyElement_put_topMargin,
    HTMLBodyElement_get_topMargin,
    HTMLBodyElement_put_rightMargin,
    HTMLBodyElement_get_rightMargin,
    HTMLBodyElement_put_bottomMargin,
    HTMLBodyElement_get_bottomMargin,
    HTMLBodyElement_put_noWrap,
    HTMLBodyElement_get_noWrap,
    HTMLBodyElement_put_bgColor,
    HTMLBodyElement_get_bgColor,
    HTMLBodyElement_put_text,
    HTMLBodyElement_get_text,
    HTMLBodyElement_put_link,
    HTMLBodyElement_get_link,
    HTMLBodyElement_put_vLink,
    HTMLBodyElement_get_vLink,
    HTMLBodyElement_put_aLink,
    HTMLBodyElement_get_aLink,
    HTMLBodyElement_put_onload,
    HTMLBodyElement_get_onload,
    HTMLBodyElement_put_onunload,
    HTMLBodyElement_get_onunload,
    HTMLBodyElement_put_scroll,
    HTMLBodyElement_get_scroll,
    HTMLBodyElement_put_onselect,
    HTMLBodyElement_get_onselect,
    HTMLBodyElement_put_onbeforeunload,
    HTMLBodyElement_get_onbeforeunload,
    HTMLBodyElement_createTextRange
};

717 718 719 720
static inline HTMLBodyElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
{
    return CONTAINING_RECORD(iface, HTMLBodyElement, textcont.element.node);
}
721

722 723
static HRESULT HTMLBodyElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
{
724
    HTMLBodyElement *This = impl_from_HTMLDOMNode(iface);
725 726 727 728 729

    *ppv = NULL;

    if(IsEqualGUID(&IID_IUnknown, riid)) {
        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
730
        *ppv = &This->IHTMLBodyElement_iface;
731 732
    }else if(IsEqualGUID(&IID_IDispatch, riid)) {
        TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
733
        *ppv = &This->IHTMLBodyElement_iface;
734 735
    }else if(IsEqualGUID(&IID_IHTMLBodyElement, riid)) {
        TRACE("(%p)->(IID_IHTMLBodyElement %p)\n", This, ppv);
736
        *ppv = &This->IHTMLBodyElement_iface;
737 738
    }else if(IsEqualGUID(&IID_IHTMLTextContainer, riid)) {
        TRACE("(%p)->(IID_IHTMLTextContainer %p)\n", &This->textcont, ppv);
739
        *ppv = &This->textcont.IHTMLTextContainer_iface;
740 741 742 743 744 745 746 747 748 749
    }

    if(*ppv) {
        IUnknown_AddRef((IUnknown*)*ppv);
        return S_OK;
    }

    return HTMLElement_QI(&This->textcont.element.node, riid, ppv);
}

750 751
static void HTMLBodyElement_destructor(HTMLDOMNode *iface)
{
752
    HTMLBodyElement *This = impl_from_HTMLDOMNode(iface);
753 754

    nsIDOMHTMLBodyElement_Release(This->nsbody);
755 756

    HTMLElement_destructor(&This->textcont.element.node);
757 758
}

759 760
static event_target_t **HTMLBodyElement_get_event_target(HTMLDOMNode *iface)
{
761
    HTMLBodyElement *This = impl_from_HTMLDOMNode(iface);
762

763 764
    return This->textcont.element.node.doc
        ? &This->textcont.element.node.doc->body_event_target
765 766 767
        : &This->textcont.element.node.event_target;
}

768
static const NodeImplVtbl HTMLBodyElementImplVtbl = {
769
    HTMLBodyElement_QI,
770
    HTMLBodyElement_destructor,
771
    HTMLElement_clone,
772
    HTMLElement_handle_event,
773
    HTMLElement_get_attr_col,
774
    HTMLBodyElement_get_event_target
775 776
};

777 778 779
static const tid_t HTMLBodyElement_iface_tids[] = {
    IHTMLBodyElement_tid,
    IHTMLBodyElement2_tid,
780
    HTMLELEMENT_TIDS,
781 782 783 784 785 786 787 788 789 790 791 792
    IHTMLTextContainer_tid,
    IHTMLUniqueName_tid,
    0
};

static dispex_static_data_t HTMLBodyElement_dispex = {
    NULL,
    DispHTMLBody_tid,
    NULL,
    HTMLBodyElement_iface_tids
};

793
HRESULT HTMLBodyElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
794
{
795
    HTMLBodyElement *ret;
796 797
    nsresult nsres;

798 799 800
    ret = heap_alloc_zero(sizeof(HTMLBodyElement));
    if(!ret)
        return E_OUTOFMEMORY;
801

802
    ret->IHTMLBodyElement_iface.lpVtbl = &HTMLBodyElementVtbl;
803
    ret->textcont.element.node.vtbl = &HTMLBodyElementImplVtbl;
804

805 806 807 808 809 810 811
    nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLBodyElement, (void**)&ret->nsbody);
    if(NS_FAILED(nsres)) {
        ERR("Could not get nsDOMHTMLBodyElement: %08x\n", nsres);
        heap_free(ret);
        return E_OUTOFMEMORY;
    }

812
    HTMLTextContainer_Init(&ret->textcont, doc, nselem, &HTMLBodyElement_dispex);
813

814
    ConnectionPoint_Init(&ret->cp_propnotif, &ret->textcont.element.cp_container, &IID_IPropertyNotifySink, NULL);
815

816 817
    *elem = &ret->textcont.element;
    return S_OK;
818
}