cdata.c 23.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 *    DOM CDATA node implementation
 *
 * Copyright 2007 Alistair Leslie-Hughes
 *
 * 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
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#define COBJMACROS

#include "config.h"

#include <stdarg.h>
26 27 28 29 30
#ifdef HAVE_LIBXML2
# include <libxml/parser.h>
# include <libxml/xmlerror.h>
#endif

31 32 33 34
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
35
#include "msxml6.h"
36 37 38 39 40 41 42 43 44 45 46

#include "msxml_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(msxml);

#ifdef HAVE_LIBXML2

typedef struct _domcdata
{
47
    xmlnode node;
48
    IXMLDOMCDATASection IXMLDOMCDATASection_iface;
49 50 51 52 53
    LONG ref;
} domcdata;

static inline domcdata *impl_from_IXMLDOMCDATASection( IXMLDOMCDATASection *iface )
{
54
    return CONTAINING_RECORD(iface, domcdata, IXMLDOMCDATASection_iface);
55 56 57 58 59 60 61 62
}

static HRESULT WINAPI domcdata_QueryInterface(
    IXMLDOMCDATASection *iface,
    REFIID riid,
    void** ppvObject )
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
63
    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
64 65

    if ( IsEqualGUID( riid, &IID_IXMLDOMCDATASection ) ||
66
         IsEqualGUID( riid, &IID_IXMLDOMCharacterData) ||
67
         IsEqualGUID( riid, &IID_IXMLDOMNode ) ||
68
         IsEqualGUID( riid, &IID_IDispatch ) ||
69 70 71 72
         IsEqualGUID( riid, &IID_IUnknown ) )
    {
        *ppvObject = iface;
    }
73 74 75 76
    else if(node_query_interface(&This->node, riid, ppvObject))
    {
        return *ppvObject ? S_OK : E_NOINTERFACE;
    }
77 78
    else
    {
79
        TRACE("Unsupported interface %s\n", debugstr_guid(riid));
80
        *ppvObject = NULL;
81 82 83
        return E_NOINTERFACE;
    }

84
    IXMLDOMText_AddRef((IUnknown*)*ppvObject);
85 86 87 88 89 90 91
    return S_OK;
}

static ULONG WINAPI domcdata_AddRef(
    IXMLDOMCDATASection *iface )
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
92 93 94
    ULONG ref = InterlockedIncrement( &This->ref );
    TRACE("(%p)->(%d)\n", This, ref);
    return ref;
95 96 97 98 99 100
}

static ULONG WINAPI domcdata_Release(
    IXMLDOMCDATASection *iface )
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
101
    ULONG ref = InterlockedDecrement( &This->ref );
102

103
    TRACE("(%p)->(%d)\n", This, ref);
104 105
    if ( ref == 0 )
    {
106
        destroy_xmlnode(&This->node);
107
        heap_free( This );
108 109 110 111 112 113 114 115 116
    }

    return ref;
}

static HRESULT WINAPI domcdata_GetTypeInfoCount(
    IXMLDOMCDATASection *iface,
    UINT* pctinfo )
{
117 118 119 120 121 122 123
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );

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

    *pctinfo = 1;

    return S_OK;
124 125 126 127 128 129 130
}

static HRESULT WINAPI domcdata_GetTypeInfo(
    IXMLDOMCDATASection *iface,
    UINT iTInfo, LCID lcid,
    ITypeInfo** ppTInfo )
{
131 132 133 134 135 136 137 138
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
    HRESULT hr;

    TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);

    hr = get_typeinfo(IXMLDOMCDATASection_tid, ppTInfo);

    return hr;
139 140 141 142 143 144 145
}

static HRESULT WINAPI domcdata_GetIDsOfNames(
    IXMLDOMCDATASection *iface,
    REFIID riid, LPOLESTR* rgszNames,
    UINT cNames, LCID lcid, DISPID* rgDispId )
{
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
    ITypeInfo *typeinfo;
    HRESULT hr;

    TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
          lcid, rgDispId);

    if(!rgszNames || cNames == 0 || !rgDispId)
        return E_INVALIDARG;

    hr = get_typeinfo(IXMLDOMCDATASection_tid, &typeinfo);
    if(SUCCEEDED(hr))
    {
        hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
        ITypeInfo_Release(typeinfo);
    }

    return hr;
164 165 166 167 168 169 170 171
}

static HRESULT WINAPI domcdata_Invoke(
    IXMLDOMCDATASection *iface,
    DISPID dispIdMember, REFIID riid, LCID lcid,
    WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
    EXCEPINFO* pExcepInfo, UINT* puArgErr )
{
172 173 174 175 176 177 178 179 180 181
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
    ITypeInfo *typeinfo;
    HRESULT hr;

    TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
          lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);

    hr = get_typeinfo(IXMLDOMCDATASection_tid, &typeinfo);
    if(SUCCEEDED(hr))
    {
182 183
        hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMCDATASection_iface, dispIdMember, wFlags,
                pDispParams, pVarResult, pExcepInfo, puArgErr);
184 185 186 187
        ITypeInfo_Release(typeinfo);
    }

    return hr;
188 189 190 191 192 193 194
}

static HRESULT WINAPI domcdata_get_nodeName(
    IXMLDOMCDATASection *iface,
    BSTR* p )
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
195 196 197 198 199 200 201

    static const WCHAR cdata_sectionW[] =
        {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0};

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

    return return_bstr(cdata_sectionW, p);
202 203 204 205
}

static HRESULT WINAPI domcdata_get_nodeValue(
    IXMLDOMCDATASection *iface,
206
    VARIANT* value)
207 208
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
209 210 211 212

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

    return node_get_content(&This->node, value);
213 214 215 216
}

static HRESULT WINAPI domcdata_put_nodeValue(
    IXMLDOMCDATASection *iface,
217
    VARIANT value)
218 219
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
220

221
    TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
222 223

    return node_put_value(&This->node, &value);
224 225 226 227 228 229 230
}

static HRESULT WINAPI domcdata_get_nodeType(
    IXMLDOMCDATASection *iface,
    DOMNodeType* domNodeType )
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
231 232 233 234 235

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

    *domNodeType = NODE_CDATA_SECTION;
    return S_OK;
236 237 238 239 240 241 242
}

static HRESULT WINAPI domcdata_get_parentNode(
    IXMLDOMCDATASection *iface,
    IXMLDOMNode** parent )
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
243 244 245 246

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

    return node_get_parent(&This->node, parent);
247 248 249 250 251 252 253
}

static HRESULT WINAPI domcdata_get_childNodes(
    IXMLDOMCDATASection *iface,
    IXMLDOMNodeList** outList)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
254 255 256 257

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

    return node_get_child_nodes(&This->node, outList);
258 259 260 261 262 263 264
}

static HRESULT WINAPI domcdata_get_firstChild(
    IXMLDOMCDATASection *iface,
    IXMLDOMNode** domNode)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
265 266 267 268

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

    return return_null_node(domNode);
269 270 271 272 273 274 275
}

static HRESULT WINAPI domcdata_get_lastChild(
    IXMLDOMCDATASection *iface,
    IXMLDOMNode** domNode)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
276 277 278 279

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

    return return_null_node(domNode);
280 281 282 283 284 285 286
}

static HRESULT WINAPI domcdata_get_previousSibling(
    IXMLDOMCDATASection *iface,
    IXMLDOMNode** domNode)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
287 288 289 290

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

    return node_get_previous_sibling(&This->node, domNode);
291 292 293 294 295 296 297
}

static HRESULT WINAPI domcdata_get_nextSibling(
    IXMLDOMCDATASection *iface,
    IXMLDOMNode** domNode)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
298 299 300 301

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

    return node_get_next_sibling(&This->node, domNode);
302 303 304 305 306 307
}

static HRESULT WINAPI domcdata_get_attributes(
    IXMLDOMCDATASection *iface,
    IXMLDOMNamedNodeMap** attributeMap)
{
308 309 310 311 312
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );

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

    return return_null_ptr((void**)attributeMap);
313 314 315 316
}

static HRESULT WINAPI domcdata_insertBefore(
    IXMLDOMCDATASection *iface,
317
    IXMLDOMNode* newNode, VARIANT refChild,
318 319 320
    IXMLDOMNode** outOldNode)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
321

322
    FIXME("(%p)->(%p %s %p) needs test\n", This, newNode, debugstr_variant(&refChild), outOldNode);
323 324

    return node_insert_before(&This->node, newNode, &refChild, outOldNode);
325 326 327 328 329 330 331 332 333
}

static HRESULT WINAPI domcdata_replaceChild(
    IXMLDOMCDATASection *iface,
    IXMLDOMNode* newNode,
    IXMLDOMNode* oldNode,
    IXMLDOMNode** outOldNode)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
334 335 336 337

    FIXME("(%p)->(%p %p %p) needs tests\n", This, newNode, oldNode, outOldNode);

    return node_replace_child(&This->node, newNode, oldNode, outOldNode);
338 339 340 341
}

static HRESULT WINAPI domcdata_removeChild(
    IXMLDOMCDATASection *iface,
342
    IXMLDOMNode *child, IXMLDOMNode **oldChild)
343 344
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
345 346
    TRACE("(%p)->(%p %p)\n", This, child, oldChild);
    return node_remove_child(&This->node, child, oldChild);
347 348 349 350
}

static HRESULT WINAPI domcdata_appendChild(
    IXMLDOMCDATASection *iface,
351
    IXMLDOMNode *child, IXMLDOMNode **outChild)
352 353
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
354 355
    TRACE("(%p)->(%p %p)\n", This, child, outChild);
    return node_append_child(&This->node, child, outChild);
356 357 358 359
}

static HRESULT WINAPI domcdata_hasChildNodes(
    IXMLDOMCDATASection *iface,
360
    VARIANT_BOOL *ret)
361 362
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
363 364
    TRACE("(%p)->(%p)\n", This, ret);
    return node_has_childnodes(&This->node, ret);
365 366 367 368
}

static HRESULT WINAPI domcdata_get_ownerDocument(
    IXMLDOMCDATASection *iface,
369
    IXMLDOMDocument    **doc)
370 371
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
372 373
    TRACE("(%p)->(%p)\n", This, doc);
    return node_get_owner_doc(&This->node, doc);
374 375 376 377
}

static HRESULT WINAPI domcdata_cloneNode(
    IXMLDOMCDATASection *iface,
378
    VARIANT_BOOL deep, IXMLDOMNode** outNode)
379 380
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
381 382
    TRACE("(%p)->(%d %p)\n", This, deep, outNode);
    return node_clone( &This->node, deep, outNode );
383 384 385 386 387 388 389
}

static HRESULT WINAPI domcdata_get_nodeTypeString(
    IXMLDOMCDATASection *iface,
    BSTR* p)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
390 391 392 393 394
    static const WCHAR cdatasectionW[] = {'c','d','a','t','a','s','e','c','t','i','o','n',0};

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

    return return_bstr(cdatasectionW, p);
395 396 397 398 399 400 401
}

static HRESULT WINAPI domcdata_get_text(
    IXMLDOMCDATASection *iface,
    BSTR* p)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
402 403
    TRACE("(%p)->(%p)\n", This, p);
    return node_get_text(&This->node, p);
404 405 406 407 408 409 410
}

static HRESULT WINAPI domcdata_put_text(
    IXMLDOMCDATASection *iface,
    BSTR p)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
411 412
    TRACE("(%p)->(%p)\n", This, debugstr_w(p));
    return node_put_text( &This->node, p );
413 414 415 416
}

static HRESULT WINAPI domcdata_get_specified(
    IXMLDOMCDATASection *iface,
417
    VARIANT_BOOL* isSpecified)
418 419
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
420 421 422
    FIXME("(%p)->(%p) stub!\n", This, isSpecified);
    *isSpecified = VARIANT_TRUE;
    return S_OK;
423 424 425 426
}

static HRESULT WINAPI domcdata_get_definition(
    IXMLDOMCDATASection *iface,
427
    IXMLDOMNode** definitionNode)
428 429
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
430 431
    FIXME("(%p)->(%p)\n", This, definitionNode);
    return E_NOTIMPL;
432 433 434 435
}

static HRESULT WINAPI domcdata_get_nodeTypedValue(
    IXMLDOMCDATASection *iface,
436
    VARIANT* v)
437 438
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
439 440
    TRACE("(%p)->(%p)\n", This, v);
    return node_get_content(&This->node, v);
441 442 443 444
}

static HRESULT WINAPI domcdata_put_nodeTypedValue(
    IXMLDOMCDATASection *iface,
445
    VARIANT typedValue)
446 447
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
448 449
    FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue));
    return E_NOTIMPL;
450 451 452 453
}

static HRESULT WINAPI domcdata_get_dataType(
    IXMLDOMCDATASection *iface,
454
    VARIANT* typename)
455 456
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
457 458
    TRACE("(%p)->(%p)\n", This, typename);
    return return_null_var( typename );
459 460 461 462 463 464 465
}

static HRESULT WINAPI domcdata_put_dataType(
    IXMLDOMCDATASection *iface,
    BSTR p)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
466 467 468 469 470 471 472

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

    if(!p)
        return E_INVALIDARG;

    return E_FAIL;
473 474 475 476 477 478 479
}

static HRESULT WINAPI domcdata_get_xml(
    IXMLDOMCDATASection *iface,
    BSTR* p)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
480 481 482 483

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

    return node_get_xml(&This->node, FALSE, FALSE, p);
484 485 486 487
}

static HRESULT WINAPI domcdata_transformNode(
    IXMLDOMCDATASection *iface,
488
    IXMLDOMNode *node, BSTR *p)
489 490
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
491 492
    TRACE("(%p)->(%p %p)\n", This, node, p);
    return node_transform_node(&This->node, node, p);
493 494 495 496 497 498 499
}

static HRESULT WINAPI domcdata_selectNodes(
    IXMLDOMCDATASection *iface,
    BSTR p, IXMLDOMNodeList** outList)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
500 501
    TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList);
    return node_select_nodes(&This->node, p, outList);
502 503 504 505 506 507 508
}

static HRESULT WINAPI domcdata_selectSingleNode(
    IXMLDOMCDATASection *iface,
    BSTR p, IXMLDOMNode** outNode)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
509 510
    TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode);
    return node_select_singlenode(&This->node, p, outNode);
511 512 513 514
}

static HRESULT WINAPI domcdata_get_parsed(
    IXMLDOMCDATASection *iface,
515
    VARIANT_BOOL* isParsed)
516 517
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
518 519 520
    FIXME("(%p)->(%p) stub!\n", This, isParsed);
    *isParsed = VARIANT_TRUE;
    return S_OK;
521 522 523 524 525 526 527
}

static HRESULT WINAPI domcdata_get_namespaceURI(
    IXMLDOMCDATASection *iface,
    BSTR* p)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
528 529
    TRACE("(%p)->(%p)\n", This, p);
    return node_get_namespaceURI(&This->node, p);
530 531 532 533
}

static HRESULT WINAPI domcdata_get_prefix(
    IXMLDOMCDATASection *iface,
534
    BSTR* prefix)
535 536
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
537 538
    TRACE("(%p)->(%p)\n", This, prefix);
    return return_null_bstr( prefix );
539 540 541 542
}

static HRESULT WINAPI domcdata_get_baseName(
    IXMLDOMCDATASection *iface,
543
    BSTR* name)
544 545
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
546 547
    FIXME("(%p)->(%p): needs test\n", This, name);
    return return_null_bstr( name );
548 549 550 551 552 553 554
}

static HRESULT WINAPI domcdata_transformNodeToObject(
    IXMLDOMCDATASection *iface,
    IXMLDOMNode* domNode, VARIANT var1)
{
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
555 556
    FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1));
    return E_NOTIMPL;
557 558 559 560 561 562
}

static HRESULT WINAPI domcdata_get_data(
    IXMLDOMCDATASection *iface,
    BSTR *p)
{
563
    HRESULT hr;
564 565 566 567 568
    VARIANT vRet;

    if(!p)
        return E_INVALIDARG;

569
    hr = IXMLDOMCDATASection_get_nodeValue( iface, &vRet );
570 571 572 573 574 575
    if(hr == S_OK)
    {
        *p = V_BSTR(&vRet);
    }

    return hr;
576 577 578 579 580 581
}

static HRESULT WINAPI domcdata_put_data(
    IXMLDOMCDATASection *iface,
    BSTR data)
{
582 583 584
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
    VARIANT val;

585
    TRACE("(%p)->(%s)\n", This, debugstr_w(data) );
586 587 588 589

    V_VT(&val) = VT_BSTR;
    V_BSTR(&val) = data;

590
    return IXMLDOMCDATASection_put_nodeValue( iface, val );
591 592 593 594
}

static HRESULT WINAPI domcdata_get_length(
    IXMLDOMCDATASection *iface,
595
    LONG *len)
596
{
597
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
598 599
    HRESULT hr;
    BSTR data;
600

601
    TRACE("(%p)->(%p)\n", This, len);
602 603 604 605

    if(!len)
        return E_INVALIDARG;

606 607
    hr = IXMLDOMCDATASection_get_data(iface, &data);
    if(hr == S_OK)
608
    {
609 610
        *len = SysStringLen(data);
        SysFreeString(data);
611 612 613
    }

    return S_OK;
614 615 616 617
}

static HRESULT WINAPI domcdata_substringData(
    IXMLDOMCDATASection *iface,
618
    LONG offset, LONG count, BSTR *p)
619
{
620
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
621 622
    HRESULT hr;
    BSTR data;
623

624
    TRACE("(%p)->(%d %d %p)\n", This, offset, count, p);
625 626 627 628 629 630 631 632 633

    if(!p)
        return E_INVALIDARG;

    *p = NULL;
    if(offset < 0 || count < 0)
        return E_INVALIDARG;

    if(count == 0)
634
        return S_FALSE;
635

636 637
    hr = IXMLDOMCDATASection_get_data(iface, &data);
    if(hr == S_OK)
638
    {
639
        LONG len = SysStringLen(data);
640

641
        if(offset < len)
642
        {
643 644
            if(offset + count > len)
                *p = SysAllocString(&data[offset]);
645
            else
646
                *p = SysAllocStringLen(&data[offset], count);
647
        }
648 649
        else
            hr = S_FALSE;
650

651
        SysFreeString(data);
652 653 654
    }

    return hr;
655 656 657 658 659 660
}

static HRESULT WINAPI domcdata_appendData(
    IXMLDOMCDATASection *iface,
    BSTR p)
{
661
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
662 663 664
    HRESULT hr;
    BSTR data;
    LONG p_len;
665

666
    TRACE("(%p)->(%s)\n", This, debugstr_w(p));
667 668

    /* Nothing to do if NULL or an Empty string passed in. */
669
    if((p_len = SysStringLen(p)) == 0) return S_OK;
670

671 672
    hr = IXMLDOMCDATASection_get_data(iface, &data);
    if(hr == S_OK)
673
    {
674 675 676 677 678 679 680 681 682 683 684
        LONG len = SysStringLen(data);
        BSTR str = SysAllocStringLen(NULL, p_len + len);

        memcpy(str, data, len*sizeof(WCHAR));
        memcpy(&str[len], p, p_len*sizeof(WCHAR));
        str[len+p_len] = 0;

        hr = IXMLDOMCDATASection_put_data(iface, str);

        SysFreeString(str);
        SysFreeString(data);
685 686 687
    }

    return hr;
688 689 690 691
}

static HRESULT WINAPI domcdata_insertData(
    IXMLDOMCDATASection *iface,
692
    LONG offset, BSTR p)
693
{
694
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
695 696 697
    HRESULT hr;
    BSTR data;
    LONG p_len;
698

699
    TRACE("(%p)->(%d %s)\n", This, offset, debugstr_w(p));
700

701
    /* If have a NULL or empty string, don't do anything. */
702
    if((p_len = SysStringLen(p)) == 0)
703 704 705 706 707 708 709
        return S_OK;

    if(offset < 0)
    {
        return E_INVALIDARG;
    }

710 711
    hr = IXMLDOMCDATASection_get_data(iface, &data);
    if(hr == S_OK)
712
    {
713 714
        LONG len = SysStringLen(data);
        BSTR str;
715

716
        if(len < offset)
717
        {
718
            SysFreeString(data);
719 720 721
            return E_INVALIDARG;
        }

722 723 724 725 726 727
        str = SysAllocStringLen(NULL, len + p_len);
        /* start part, supplied string and end part */
        memcpy(str, data, offset*sizeof(WCHAR));
        memcpy(&str[offset], p, p_len*sizeof(WCHAR));
        memcpy(&str[offset+p_len], &data[offset], (len-offset)*sizeof(WCHAR));
        str[len+p_len] = 0;
728

729
        hr = IXMLDOMCDATASection_put_data(iface, str);
730

731 732
        SysFreeString(str);
        SysFreeString(data);
733 734 735
    }

    return hr;
736 737 738 739
}

static HRESULT WINAPI domcdata_deleteData(
    IXMLDOMCDATASection *iface,
740
    LONG offset, LONG count)
741
{
742
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
743 744 745 746
    HRESULT hr;
    LONG len = -1;
    BSTR str;

747
    TRACE("(%p)->(%d %d)\n", This, offset, count);
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783

    hr = IXMLDOMCDATASection_get_length(iface, &len);
    if(hr != S_OK) return hr;

    if((offset < 0) || (offset > len) || (count < 0))
        return E_INVALIDARG;

    if(len == 0) return S_OK;

    /* cutting start or end */
    if((offset == 0) || ((count + offset) >= len))
    {
        if(offset == 0)
            IXMLDOMCDATASection_substringData(iface, count, len - count, &str);
        else
            IXMLDOMCDATASection_substringData(iface, 0, offset, &str);
        hr = IXMLDOMCDATASection_put_data(iface, str);
    }
    else
    /* cutting from the inside */
    {
        BSTR str_end;

        IXMLDOMCDATASection_substringData(iface, 0, offset, &str);
        IXMLDOMCDATASection_substringData(iface, offset + count, len - count, &str_end);

        hr = IXMLDOMCDATASection_put_data(iface, str);
        if(hr == S_OK)
            hr = IXMLDOMCDATASection_appendData(iface, str_end);

        SysFreeString(str_end);
    }

    SysFreeString(str);

    return hr;
784 785 786 787
}

static HRESULT WINAPI domcdata_replaceData(
    IXMLDOMCDATASection *iface,
788
    LONG offset, LONG count, BSTR p)
789
{
790 791 792
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
    HRESULT hr;

793
    TRACE("(%p)->(%d %d %s)\n", This, offset, count, debugstr_w(p));
794 795 796 797 798 799 800

    hr = IXMLDOMCDATASection_deleteData(iface, offset, count);

    if (hr == S_OK)
       hr = IXMLDOMCDATASection_insertData(iface, offset, p);

    return hr;
801 802 803 804
}

static HRESULT WINAPI domcdata_splitText(
    IXMLDOMCDATASection *iface,
805
    LONG offset, IXMLDOMText **txtNode)
806
{
807
    domcdata *This = impl_from_IXMLDOMCDATASection( iface );
808 809 810 811 812 813 814 815 816
    IXMLDOMDocument *doc;
    LONG length = 0;
    HRESULT hr;

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

    if (!txtNode || offset < 0) return E_INVALIDARG;

    *txtNode = NULL;
817

818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
    IXMLDOMCDATASection_get_length(iface, &length);

    if (offset > length) return E_INVALIDARG;
    if (offset == length) return S_FALSE;

    hr = IXMLDOMCDATASection_get_ownerDocument(iface, &doc);
    if (hr == S_OK)
    {
        BSTR data;

        hr = IXMLDOMCDATASection_substringData(iface, offset, length - offset, &data);
        if (hr == S_OK)
        {
            hr = IXMLDOMDocument_createTextNode(doc, data, txtNode);
            if (hr == S_OK)
            {
                IXMLDOMNode *parent;

                hr = IXMLDOMCDATASection_get_parentNode(iface, &parent);
                if (hr == S_OK)
                {
                    IXMLDOMCDATASection_deleteData(iface, 0, offset);
                    hr = IXMLDOMNode_appendChild(parent, (IXMLDOMNode*)*txtNode, NULL);
841
                    IXMLDOMNode_Release(parent);
842 843 844 845 846 847 848 849 850
                }
            }
            SysFreeString(data);
        }
        IXMLDOMDocument_Release(doc);
    }

    return hr;
}
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911

static const struct IXMLDOMCDATASectionVtbl domcdata_vtbl =
{
    domcdata_QueryInterface,
    domcdata_AddRef,
    domcdata_Release,
    domcdata_GetTypeInfoCount,
    domcdata_GetTypeInfo,
    domcdata_GetIDsOfNames,
    domcdata_Invoke,
    domcdata_get_nodeName,
    domcdata_get_nodeValue,
    domcdata_put_nodeValue,
    domcdata_get_nodeType,
    domcdata_get_parentNode,
    domcdata_get_childNodes,
    domcdata_get_firstChild,
    domcdata_get_lastChild,
    domcdata_get_previousSibling,
    domcdata_get_nextSibling,
    domcdata_get_attributes,
    domcdata_insertBefore,
    domcdata_replaceChild,
    domcdata_removeChild,
    domcdata_appendChild,
    domcdata_hasChildNodes,
    domcdata_get_ownerDocument,
    domcdata_cloneNode,
    domcdata_get_nodeTypeString,
    domcdata_get_text,
    domcdata_put_text,
    domcdata_get_specified,
    domcdata_get_definition,
    domcdata_get_nodeTypedValue,
    domcdata_put_nodeTypedValue,
    domcdata_get_dataType,
    domcdata_put_dataType,
    domcdata_get_xml,
    domcdata_transformNode,
    domcdata_selectNodes,
    domcdata_selectSingleNode,
    domcdata_get_parsed,
    domcdata_get_namespaceURI,
    domcdata_get_prefix,
    domcdata_get_baseName,
    domcdata_transformNodeToObject,
    domcdata_get_data,
    domcdata_put_data,
    domcdata_get_length,
    domcdata_substringData,
    domcdata_appendData,
    domcdata_insertData,
    domcdata_deleteData,
    domcdata_replaceData,
    domcdata_splitText
};

IUnknown* create_cdata( xmlNodePtr text )
{
    domcdata *This;

912
    This = heap_alloc( sizeof *This );
913 914 915
    if ( !This )
        return NULL;

916
    This->IXMLDOMCDATASection_iface.lpVtbl = &domcdata_vtbl;
917 918
    This->ref = 1;

919
    init_xmlnode(&This->node, text, (IXMLDOMNode*)&This->IXMLDOMCDATASection_iface, NULL);
920

921
    return (IUnknown*)&This->IXMLDOMCDATASection_iface;
922 923 924
}

#endif