1 /* 2 * DOM text node implementation 3 * 4 * Copyright 2006 Huw Davies 5 * Copyright 2007-2008 Alistair Leslie-Hughes 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define COBJMACROS 23 24 #include "config.h" 25 26 #include <stdarg.h> 27 #ifdef HAVE_LIBXML2 28 # include <libxml/parser.h> 29 # include <libxml/parserInternals.h> 30 # include <libxml/xmlerror.h> 31 #endif 32 33 #include "windef.h" 34 #include "winbase.h" 35 #include "winuser.h" 36 #include "ole2.h" 37 #include "msxml6.h" 38 39 #include "msxml_private.h" 40 41 #include "wine/debug.h" 42 43 #ifdef HAVE_LIBXML2 44 45 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 46 47 typedef struct _domtext 48 { 49 xmlnode node; 50 IXMLDOMText IXMLDOMText_iface; 51 LONG ref; 52 } domtext; 53 54 static inline domtext *impl_from_IXMLDOMText( IXMLDOMText *iface ) 55 { 56 return CONTAINING_RECORD(iface, domtext, IXMLDOMText_iface); 57 } 58 59 static void domtext_reset_noenc(domtext *This) 60 { 61 This->node.node->name = NULL; 62 } 63 64 static HRESULT WINAPI domtext_QueryInterface( 65 IXMLDOMText *iface, 66 REFIID riid, 67 void** ppvObject ) 68 { 69 domtext *This = impl_from_IXMLDOMText( iface ); 70 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); 71 72 if ( IsEqualGUID( riid, &IID_IXMLDOMText ) || 73 IsEqualGUID( riid, &IID_IXMLDOMCharacterData) || 74 IsEqualGUID( riid, &IID_IXMLDOMNode ) || 75 IsEqualGUID( riid, &IID_IDispatch ) || 76 IsEqualGUID( riid, &IID_IUnknown ) ) 77 { 78 *ppvObject = iface; 79 } 80 else if(node_query_interface(&This->node, riid, ppvObject)) 81 { 82 return *ppvObject ? S_OK : E_NOINTERFACE; 83 } 84 else 85 { 86 TRACE("Unsupported interface %s\n", debugstr_guid(riid)); 87 *ppvObject = NULL; 88 return E_NOINTERFACE; 89 } 90 91 IXMLDOMText_AddRef(iface); 92 return S_OK; 93 } 94 95 static ULONG WINAPI domtext_AddRef( 96 IXMLDOMText *iface ) 97 { 98 domtext *This = impl_from_IXMLDOMText( iface ); 99 ULONG ref = InterlockedIncrement( &This->ref ); 100 TRACE("(%p)->(%d)\n", This, ref); 101 return ref; 102 } 103 104 static ULONG WINAPI domtext_Release( 105 IXMLDOMText *iface ) 106 { 107 domtext *This = impl_from_IXMLDOMText( iface ); 108 ULONG ref = InterlockedDecrement( &This->ref ); 109 110 TRACE("(%p)->(%d)\n", This, ref); 111 if ( ref == 0 ) 112 { 113 destroy_xmlnode(&This->node); 114 heap_free( This ); 115 } 116 117 return ref; 118 } 119 120 static HRESULT WINAPI domtext_GetTypeInfoCount( 121 IXMLDOMText *iface, 122 UINT* pctinfo ) 123 { 124 domtext *This = impl_from_IXMLDOMText( iface ); 125 return IDispatchEx_GetTypeInfoCount(&This->node.dispex.IDispatchEx_iface, pctinfo); 126 } 127 128 static HRESULT WINAPI domtext_GetTypeInfo( 129 IXMLDOMText *iface, 130 UINT iTInfo, LCID lcid, 131 ITypeInfo** ppTInfo ) 132 { 133 domtext *This = impl_from_IXMLDOMText( iface ); 134 return IDispatchEx_GetTypeInfo(&This->node.dispex.IDispatchEx_iface, 135 iTInfo, lcid, ppTInfo); 136 } 137 138 static HRESULT WINAPI domtext_GetIDsOfNames( 139 IXMLDOMText *iface, 140 REFIID riid, LPOLESTR* rgszNames, 141 UINT cNames, LCID lcid, DISPID* rgDispId ) 142 { 143 domtext *This = impl_from_IXMLDOMText( iface ); 144 return IDispatchEx_GetIDsOfNames(&This->node.dispex.IDispatchEx_iface, 145 riid, rgszNames, cNames, lcid, rgDispId); 146 } 147 148 static HRESULT WINAPI domtext_Invoke( 149 IXMLDOMText *iface, 150 DISPID dispIdMember, REFIID riid, LCID lcid, 151 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, 152 EXCEPINFO* pExcepInfo, UINT* puArgErr ) 153 { 154 domtext *This = impl_from_IXMLDOMText( iface ); 155 return IDispatchEx_Invoke(&This->node.dispex.IDispatchEx_iface, 156 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 157 } 158 159 static HRESULT WINAPI domtext_get_nodeName( 160 IXMLDOMText *iface, 161 BSTR* p ) 162 { 163 domtext *This = impl_from_IXMLDOMText( iface ); 164 165 static const WCHAR textW[] = {'#','t','e','x','t',0}; 166 167 TRACE("(%p)->(%p)\n", This, p); 168 169 return return_bstr(textW, p); 170 } 171 172 static HRESULT WINAPI domtext_get_nodeValue( 173 IXMLDOMText *iface, 174 VARIANT* value ) 175 { 176 domtext *This = impl_from_IXMLDOMText( iface ); 177 178 TRACE("(%p)->(%p)\n", This, value); 179 180 return node_get_content(&This->node, value); 181 } 182 183 static HRESULT WINAPI domtext_put_nodeValue( 184 IXMLDOMText *iface, 185 VARIANT value) 186 { 187 domtext *This = impl_from_IXMLDOMText( iface ); 188 189 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value)); 190 191 domtext_reset_noenc(This); 192 return node_put_value(&This->node, &value); 193 } 194 195 static HRESULT WINAPI domtext_get_nodeType( 196 IXMLDOMText *iface, 197 DOMNodeType* domNodeType ) 198 { 199 domtext *This = impl_from_IXMLDOMText( iface ); 200 201 TRACE("(%p)->(%p)\n", This, domNodeType); 202 203 *domNodeType = NODE_TEXT; 204 return S_OK; 205 } 206 207 static HRESULT WINAPI domtext_get_parentNode( 208 IXMLDOMText *iface, 209 IXMLDOMNode** parent ) 210 { 211 domtext *This = impl_from_IXMLDOMText( iface ); 212 213 TRACE("(%p)->(%p)\n", This, parent); 214 215 return node_get_parent(&This->node, parent); 216 } 217 218 static HRESULT WINAPI domtext_get_childNodes( 219 IXMLDOMText *iface, 220 IXMLDOMNodeList** outList) 221 { 222 domtext *This = impl_from_IXMLDOMText( iface ); 223 224 TRACE("(%p)->(%p)\n", This, outList); 225 226 return node_get_child_nodes(&This->node, outList); 227 } 228 229 static HRESULT WINAPI domtext_get_firstChild( 230 IXMLDOMText *iface, 231 IXMLDOMNode** domNode) 232 { 233 domtext *This = impl_from_IXMLDOMText( iface ); 234 235 TRACE("(%p)->(%p)\n", This, domNode); 236 237 return return_null_node(domNode); 238 } 239 240 static HRESULT WINAPI domtext_get_lastChild( 241 IXMLDOMText *iface, 242 IXMLDOMNode** domNode) 243 { 244 domtext *This = impl_from_IXMLDOMText( iface ); 245 246 TRACE("(%p)->(%p)\n", This, domNode); 247 248 return return_null_node(domNode); 249 } 250 251 static HRESULT WINAPI domtext_get_previousSibling( 252 IXMLDOMText *iface, 253 IXMLDOMNode** domNode) 254 { 255 domtext *This = impl_from_IXMLDOMText( iface ); 256 257 TRACE("(%p)->(%p)\n", This, domNode); 258 259 return node_get_previous_sibling(&This->node, domNode); 260 } 261 262 static HRESULT WINAPI domtext_get_nextSibling( 263 IXMLDOMText *iface, 264 IXMLDOMNode** domNode) 265 { 266 domtext *This = impl_from_IXMLDOMText( iface ); 267 268 TRACE("(%p)->(%p)\n", This, domNode); 269 270 return node_get_next_sibling(&This->node, domNode); 271 } 272 273 static HRESULT WINAPI domtext_get_attributes( 274 IXMLDOMText *iface, 275 IXMLDOMNamedNodeMap** attributeMap) 276 { 277 domtext *This = impl_from_IXMLDOMText( iface ); 278 279 TRACE("(%p)->(%p)\n", This, attributeMap); 280 281 return return_null_ptr((void**)attributeMap); 282 } 283 284 static HRESULT WINAPI domtext_insertBefore( 285 IXMLDOMText *iface, 286 IXMLDOMNode* newNode, VARIANT refChild, 287 IXMLDOMNode** outOldNode) 288 { 289 domtext *This = impl_from_IXMLDOMText( iface ); 290 291 FIXME("(%p)->(%p %s %p) needs test\n", This, newNode, debugstr_variant(&refChild), outOldNode); 292 293 return node_insert_before(&This->node, newNode, &refChild, outOldNode); 294 } 295 296 static HRESULT WINAPI domtext_replaceChild( 297 IXMLDOMText *iface, 298 IXMLDOMNode* newNode, 299 IXMLDOMNode* oldNode, 300 IXMLDOMNode** outOldNode) 301 { 302 domtext *This = impl_from_IXMLDOMText( iface ); 303 304 FIXME("(%p)->(%p %p %p) needs test\n", This, newNode, oldNode, outOldNode); 305 306 return node_replace_child(&This->node, newNode, oldNode, outOldNode); 307 } 308 309 static HRESULT WINAPI domtext_removeChild( 310 IXMLDOMText *iface, 311 IXMLDOMNode *child, IXMLDOMNode **oldChild) 312 { 313 domtext *This = impl_from_IXMLDOMText( iface ); 314 TRACE("(%p)->(%p %p)\n", This, child, oldChild); 315 return node_remove_child(&This->node, child, oldChild); 316 } 317 318 static HRESULT WINAPI domtext_appendChild( 319 IXMLDOMText *iface, 320 IXMLDOMNode *child, IXMLDOMNode **outChild) 321 { 322 domtext *This = impl_from_IXMLDOMText( iface ); 323 TRACE("(%p)->(%p %p)\n", This, child, outChild); 324 return node_append_child(&This->node, child, outChild); 325 } 326 327 static HRESULT WINAPI domtext_hasChildNodes( 328 IXMLDOMText *iface, 329 VARIANT_BOOL *ret) 330 { 331 domtext *This = impl_from_IXMLDOMText( iface ); 332 TRACE("(%p)->(%p)\n", This, ret); 333 return return_var_false(ret); 334 } 335 336 static HRESULT WINAPI domtext_get_ownerDocument( 337 IXMLDOMText *iface, 338 IXMLDOMDocument **doc) 339 { 340 domtext *This = impl_from_IXMLDOMText( iface ); 341 TRACE("(%p)->(%p)\n", This, doc); 342 return node_get_owner_doc(&This->node, doc); 343 } 344 345 static HRESULT WINAPI domtext_cloneNode( 346 IXMLDOMText *iface, 347 VARIANT_BOOL deep, IXMLDOMNode** outNode) 348 { 349 domtext *This = impl_from_IXMLDOMText( iface ); 350 TRACE("(%p)->(%d %p)\n", This, deep, outNode); 351 return node_clone( &This->node, deep, outNode ); 352 } 353 354 static HRESULT WINAPI domtext_get_nodeTypeString( 355 IXMLDOMText *iface, 356 BSTR* p) 357 { 358 domtext *This = impl_from_IXMLDOMText( iface ); 359 static const WCHAR textW[] = {'t','e','x','t',0}; 360 361 TRACE("(%p)->(%p)\n", This, p); 362 363 return return_bstr(textW, p); 364 } 365 366 static HRESULT WINAPI domtext_get_text( 367 IXMLDOMText *iface, 368 BSTR* p) 369 { 370 domtext *This = impl_from_IXMLDOMText( iface ); 371 TRACE("(%p)->(%p)\n", This, p); 372 return node_get_text(&This->node, p); 373 } 374 375 static HRESULT WINAPI domtext_put_text( 376 IXMLDOMText *iface, 377 BSTR p) 378 { 379 domtext *This = impl_from_IXMLDOMText( iface ); 380 TRACE("(%p)->(%s)\n", This, debugstr_w(p)); 381 domtext_reset_noenc(This); 382 return node_put_text( &This->node, p ); 383 } 384 385 static HRESULT WINAPI domtext_get_specified( 386 IXMLDOMText *iface, 387 VARIANT_BOOL* isSpecified) 388 { 389 domtext *This = impl_from_IXMLDOMText( iface ); 390 FIXME("(%p)->(%p) stub!\n", This, isSpecified); 391 *isSpecified = VARIANT_TRUE; 392 return S_OK; 393 } 394 395 static HRESULT WINAPI domtext_get_definition( 396 IXMLDOMText *iface, 397 IXMLDOMNode** definitionNode) 398 { 399 domtext *This = impl_from_IXMLDOMText( iface ); 400 FIXME("(%p)->(%p)\n", This, definitionNode); 401 return E_NOTIMPL; 402 } 403 404 static HRESULT WINAPI domtext_get_nodeTypedValue( 405 IXMLDOMText *iface, 406 VARIANT* var1) 407 { 408 domtext *This = impl_from_IXMLDOMText( iface ); 409 IXMLDOMNode* parent = NULL; 410 HRESULT hr; 411 412 TRACE("(%p)->(%p)\n", This, var1); 413 414 if (!var1) 415 return E_INVALIDARG; 416 417 hr = IXMLDOMText_get_parentNode(iface, &parent); 418 419 if (hr == S_OK) 420 { 421 hr = IXMLDOMNode_get_nodeTypedValue(parent, var1); 422 IXMLDOMNode_Release(parent); 423 } 424 else 425 { 426 V_VT(var1) = VT_NULL; 427 V_BSTR(var1) = NULL; 428 hr = S_FALSE; 429 } 430 431 return hr; 432 } 433 434 static HRESULT WINAPI domtext_put_nodeTypedValue( 435 IXMLDOMText *iface, 436 VARIANT value) 437 { 438 domtext *This = impl_from_IXMLDOMText( iface ); 439 IXMLDOMNode* parent = NULL; 440 HRESULT hr; 441 442 TRACE("(%p)->(%s)\n", This, debugstr_variant(&value)); 443 444 hr = IXMLDOMText_get_parentNode(iface, &parent); 445 446 if (hr == S_OK) 447 { 448 hr = IXMLDOMNode_put_nodeTypedValue(parent, value); 449 IXMLDOMNode_Release(parent); 450 } 451 else 452 { 453 hr = S_FALSE; 454 } 455 456 return hr; 457 } 458 459 static HRESULT WINAPI domtext_get_dataType( 460 IXMLDOMText *iface, 461 VARIANT* dtName) 462 { 463 domtext *This = impl_from_IXMLDOMText( iface ); 464 IXMLDOMNode* parent = NULL; 465 HRESULT hr; 466 467 TRACE("(%p)->(%p)\n", This, dtName); 468 469 if (!dtName) 470 return E_INVALIDARG; 471 472 hr = IXMLDOMText_get_parentNode(iface, &parent); 473 474 if (hr == S_OK) 475 { 476 hr = IXMLDOMNode_get_dataType(parent, dtName); 477 IXMLDOMNode_Release(parent); 478 } 479 else 480 { 481 V_VT(dtName) = VT_NULL; 482 V_BSTR(dtName) = NULL; 483 hr = S_FALSE; 484 } 485 486 return hr; 487 } 488 489 static HRESULT WINAPI domtext_put_dataType( 490 IXMLDOMText *iface, 491 BSTR dtName) 492 { 493 domtext *This = impl_from_IXMLDOMText( iface ); 494 IXMLDOMNode* parent = NULL; 495 HRESULT hr; 496 497 TRACE("(%p)->(%p)\n", This, dtName); 498 499 if (!dtName) 500 return E_INVALIDARG; 501 502 hr = IXMLDOMText_get_parentNode(iface, &parent); 503 504 if (hr == S_OK) 505 { 506 hr = IXMLDOMNode_put_dataType(parent, dtName); 507 IXMLDOMNode_Release(parent); 508 } 509 else 510 { 511 hr = S_FALSE; 512 } 513 514 return hr; 515 } 516 517 static HRESULT WINAPI domtext_get_xml( 518 IXMLDOMText *iface, 519 BSTR* p) 520 { 521 domtext *This = impl_from_IXMLDOMText( iface ); 522 523 TRACE("(%p)->(%p)\n", This, p); 524 525 return node_get_xml(&This->node, TRUE, p); 526 } 527 528 static HRESULT WINAPI domtext_transformNode( 529 IXMLDOMText *iface, 530 IXMLDOMNode *node, BSTR *p) 531 { 532 domtext *This = impl_from_IXMLDOMText( iface ); 533 TRACE("(%p)->(%p %p)\n", This, node, p); 534 return node_transform_node(&This->node, node, p); 535 } 536 537 static HRESULT WINAPI domtext_selectNodes( 538 IXMLDOMText *iface, 539 BSTR p, IXMLDOMNodeList** outList) 540 { 541 domtext *This = impl_from_IXMLDOMText( iface ); 542 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outList); 543 return node_select_nodes(&This->node, p, outList); 544 } 545 546 static HRESULT WINAPI domtext_selectSingleNode( 547 IXMLDOMText *iface, 548 BSTR p, IXMLDOMNode** outNode) 549 { 550 domtext *This = impl_from_IXMLDOMText( iface ); 551 TRACE("(%p)->(%s %p)\n", This, debugstr_w(p), outNode); 552 return node_select_singlenode(&This->node, p, outNode); 553 } 554 555 static HRESULT WINAPI domtext_get_parsed( 556 IXMLDOMText *iface, 557 VARIANT_BOOL* isParsed) 558 { 559 domtext *This = impl_from_IXMLDOMText( iface ); 560 FIXME("(%p)->(%p) stub!\n", This, isParsed); 561 *isParsed = VARIANT_TRUE; 562 return S_OK; 563 } 564 565 static HRESULT WINAPI domtext_get_namespaceURI( 566 IXMLDOMText *iface, 567 BSTR* p) 568 { 569 domtext *This = impl_from_IXMLDOMText( iface ); 570 TRACE("(%p)->(%p)\n", This, p); 571 return node_get_namespaceURI(&This->node, p); 572 } 573 574 static HRESULT WINAPI domtext_get_prefix( 575 IXMLDOMText *iface, 576 BSTR* prefix) 577 { 578 domtext *This = impl_from_IXMLDOMText( iface ); 579 TRACE("(%p)->(%p)\n", This, prefix); 580 return return_null_bstr( prefix ); 581 } 582 583 static HRESULT WINAPI domtext_get_baseName( 584 IXMLDOMText *iface, 585 BSTR* name) 586 { 587 domtext *This = impl_from_IXMLDOMText( iface ); 588 TRACE("(%p)->(%p)\n", This, name); 589 return return_null_bstr( name ); 590 } 591 592 static HRESULT WINAPI domtext_transformNodeToObject( 593 IXMLDOMText *iface, 594 IXMLDOMNode* domNode, VARIANT var1) 595 { 596 domtext *This = impl_from_IXMLDOMText( iface ); 597 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1)); 598 return E_NOTIMPL; 599 } 600 601 static HRESULT WINAPI domtext_get_data( 602 IXMLDOMText *iface, 603 BSTR *p) 604 { 605 domtext *This = impl_from_IXMLDOMText( iface ); 606 607 if(!p) 608 return E_INVALIDARG; 609 610 *p = bstr_from_xmlChar(This->node.node->content); 611 return S_OK; 612 } 613 614 static HRESULT WINAPI domtext_put_data( 615 IXMLDOMText *iface, 616 BSTR data) 617 { 618 domtext *This = impl_from_IXMLDOMText( iface ); 619 BSTR normalized_data = NULL; 620 HRESULT hr; 621 size_t i, j; 622 623 TRACE("(%p)->(%s)\n", This, debugstr_w(data)); 624 625 if (data) 626 { 627 /* normalize line endings */ 628 normalized_data = SysAllocStringLen(NULL, SysStringLen(data)); 629 if (!normalized_data) return E_OUTOFMEMORY; 630 for (i = 0, j = 0; data[i]; i++) 631 { 632 if (data[i] == '\r') 633 { 634 if (data[i + 1] == '\n') i++; /* change \r\n to just \n */ 635 normalized_data[j++] = '\n'; /* change \r by itself to \n */ 636 } 637 else 638 normalized_data[j++] = data[i]; 639 } 640 normalized_data[j] = 0; 641 } 642 643 domtext_reset_noenc(This); 644 hr = node_set_content(&This->node, normalized_data); 645 646 SysFreeString(normalized_data); 647 return hr; 648 } 649 650 static HRESULT WINAPI domtext_get_length( 651 IXMLDOMText *iface, 652 LONG *len) 653 { 654 domtext *This = impl_from_IXMLDOMText( iface ); 655 HRESULT hr; 656 BSTR data; 657 658 TRACE("(%p)->(%p)\n", This, len); 659 660 if(!len) 661 return E_INVALIDARG; 662 663 hr = IXMLDOMText_get_data(iface, &data); 664 if(hr == S_OK) 665 { 666 *len = SysStringLen(data); 667 SysFreeString(data); 668 } 669 670 return hr; 671 } 672 673 static HRESULT WINAPI domtext_substringData( 674 IXMLDOMText *iface, 675 LONG offset, LONG count, BSTR *p) 676 { 677 domtext *This = impl_from_IXMLDOMText( iface ); 678 HRESULT hr; 679 BSTR data; 680 681 TRACE("(%p)->(%d %d %p)\n", This, offset, count, p); 682 683 if(!p) 684 return E_INVALIDARG; 685 686 *p = NULL; 687 if(offset < 0 || count < 0) 688 return E_INVALIDARG; 689 690 if(count == 0) 691 return S_FALSE; 692 693 hr = IXMLDOMText_get_data(iface, &data); 694 if(hr == S_OK) 695 { 696 LONG len = SysStringLen(data); 697 698 if(offset < len) 699 { 700 if(offset + count > len) 701 *p = SysAllocString(&data[offset]); 702 else 703 *p = SysAllocStringLen(&data[offset], count); 704 } 705 else 706 hr = S_FALSE; 707 708 SysFreeString(data); 709 } 710 711 return hr; 712 } 713 714 static HRESULT WINAPI domtext_appendData( 715 IXMLDOMText *iface, 716 BSTR p) 717 { 718 domtext *This = impl_from_IXMLDOMText( iface ); 719 HRESULT hr; 720 BSTR data; 721 LONG p_len; 722 723 TRACE("(%p)->(%s)\n", This, debugstr_w(p)); 724 725 /* Nothing to do if NULL or an Empty string passed in. */ 726 if((p_len = SysStringLen(p)) == 0) return S_OK; 727 728 hr = IXMLDOMText_get_data(iface, &data); 729 if(hr == S_OK) 730 { 731 LONG len = SysStringLen(data); 732 BSTR str = SysAllocStringLen(NULL, p_len + len); 733 734 memcpy(str, data, len*sizeof(WCHAR)); 735 memcpy(&str[len], p, p_len*sizeof(WCHAR)); 736 str[len+p_len] = 0; 737 738 hr = IXMLDOMText_put_data(iface, str); 739 740 SysFreeString(str); 741 SysFreeString(data); 742 } 743 744 return hr; 745 } 746 747 static HRESULT WINAPI domtext_insertData( 748 IXMLDOMText *iface, 749 LONG offset, BSTR p) 750 { 751 domtext *This = impl_from_IXMLDOMText( iface ); 752 HRESULT hr; 753 BSTR data; 754 LONG p_len; 755 756 TRACE("(%p)->(%d %s)\n", This, offset, debugstr_w(p)); 757 758 /* If have a NULL or empty string, don't do anything. */ 759 if((p_len = SysStringLen(p)) == 0) 760 return S_OK; 761 762 if(offset < 0) 763 { 764 return E_INVALIDARG; 765 } 766 767 hr = IXMLDOMText_get_data(iface, &data); 768 if(hr == S_OK) 769 { 770 LONG len = SysStringLen(data); 771 BSTR str; 772 773 if(len < offset) 774 { 775 SysFreeString(data); 776 return E_INVALIDARG; 777 } 778 779 str = SysAllocStringLen(NULL, len + p_len); 780 /* start part, supplied string and end part */ 781 memcpy(str, data, offset*sizeof(WCHAR)); 782 memcpy(&str[offset], p, p_len*sizeof(WCHAR)); 783 memcpy(&str[offset+p_len], &data[offset], (len-offset)*sizeof(WCHAR)); 784 str[len+p_len] = 0; 785 786 hr = IXMLDOMText_put_data(iface, str); 787 788 SysFreeString(str); 789 SysFreeString(data); 790 } 791 792 return hr; 793 } 794 795 static HRESULT WINAPI domtext_deleteData( 796 IXMLDOMText *iface, 797 LONG offset, LONG count) 798 { 799 HRESULT hr; 800 LONG len = -1; 801 BSTR str; 802 803 TRACE("(%p)->(%d %d)\n", iface, offset, count); 804 805 hr = IXMLDOMText_get_length(iface, &len); 806 if(hr != S_OK) return hr; 807 808 if((offset < 0) || (offset > len) || (count < 0)) 809 return E_INVALIDARG; 810 811 if(len == 0) return S_OK; 812 813 /* cutting start or end */ 814 if((offset == 0) || ((count + offset) >= len)) 815 { 816 if(offset == 0) 817 IXMLDOMText_substringData(iface, count, len - count, &str); 818 else 819 IXMLDOMText_substringData(iface, 0, offset, &str); 820 hr = IXMLDOMText_put_data(iface, str); 821 } 822 else 823 /* cutting from the inside */ 824 { 825 BSTR str_end; 826 827 IXMLDOMText_substringData(iface, 0, offset, &str); 828 IXMLDOMText_substringData(iface, offset + count, len - count, &str_end); 829 830 hr = IXMLDOMText_put_data(iface, str); 831 if(hr == S_OK) 832 hr = IXMLDOMText_appendData(iface, str_end); 833 834 SysFreeString(str_end); 835 } 836 837 SysFreeString(str); 838 839 return hr; 840 } 841 842 static HRESULT WINAPI domtext_replaceData( 843 IXMLDOMText *iface, 844 LONG offset, LONG count, BSTR p) 845 { 846 domtext *This = impl_from_IXMLDOMText( iface ); 847 HRESULT hr; 848 849 TRACE("(%p)->(%d %d %s)\n", This, offset, count, debugstr_w(p)); 850 851 hr = IXMLDOMText_deleteData(iface, offset, count); 852 853 if (hr == S_OK) 854 hr = IXMLDOMText_insertData(iface, offset, p); 855 856 return hr; 857 } 858 859 static HRESULT WINAPI domtext_splitText( 860 IXMLDOMText *iface, 861 LONG offset, IXMLDOMText **txtNode) 862 { 863 domtext *This = impl_from_IXMLDOMText( iface ); 864 LONG length = 0; 865 866 TRACE("(%p)->(%d %p)\n", This, offset, txtNode); 867 868 if (!txtNode || offset < 0) return E_INVALIDARG; 869 870 *txtNode = NULL; 871 872 IXMLDOMText_get_length(iface, &length); 873 874 if (offset > length) return E_INVALIDARG; 875 if (offset == length) return S_FALSE; 876 877 FIXME("adjacent text nodes are not supported\n"); 878 879 return E_NOTIMPL; 880 } 881 882 static const struct IXMLDOMTextVtbl domtext_vtbl = 883 { 884 domtext_QueryInterface, 885 domtext_AddRef, 886 domtext_Release, 887 domtext_GetTypeInfoCount, 888 domtext_GetTypeInfo, 889 domtext_GetIDsOfNames, 890 domtext_Invoke, 891 domtext_get_nodeName, 892 domtext_get_nodeValue, 893 domtext_put_nodeValue, 894 domtext_get_nodeType, 895 domtext_get_parentNode, 896 domtext_get_childNodes, 897 domtext_get_firstChild, 898 domtext_get_lastChild, 899 domtext_get_previousSibling, 900 domtext_get_nextSibling, 901 domtext_get_attributes, 902 domtext_insertBefore, 903 domtext_replaceChild, 904 domtext_removeChild, 905 domtext_appendChild, 906 domtext_hasChildNodes, 907 domtext_get_ownerDocument, 908 domtext_cloneNode, 909 domtext_get_nodeTypeString, 910 domtext_get_text, 911 domtext_put_text, 912 domtext_get_specified, 913 domtext_get_definition, 914 domtext_get_nodeTypedValue, 915 domtext_put_nodeTypedValue, 916 domtext_get_dataType, 917 domtext_put_dataType, 918 domtext_get_xml, 919 domtext_transformNode, 920 domtext_selectNodes, 921 domtext_selectSingleNode, 922 domtext_get_parsed, 923 domtext_get_namespaceURI, 924 domtext_get_prefix, 925 domtext_get_baseName, 926 domtext_transformNodeToObject, 927 domtext_get_data, 928 domtext_put_data, 929 domtext_get_length, 930 domtext_substringData, 931 domtext_appendData, 932 domtext_insertData, 933 domtext_deleteData, 934 domtext_replaceData, 935 domtext_splitText 936 }; 937 938 static const tid_t domtext_iface_tids[] = { 939 IXMLDOMText_tid, 940 0 941 }; 942 943 static dispex_static_data_t domtext_dispex = { 944 NULL, 945 IXMLDOMText_tid, 946 NULL, 947 domtext_iface_tids 948 }; 949 950 IUnknown* create_text( xmlNodePtr text ) 951 { 952 domtext *This; 953 954 This = heap_alloc( sizeof *This ); 955 if ( !This ) 956 return NULL; 957 958 This->IXMLDOMText_iface.lpVtbl = &domtext_vtbl; 959 This->ref = 1; 960 961 init_xmlnode(&This->node, text, (IXMLDOMNode*)&This->IXMLDOMText_iface, &domtext_dispex); 962 963 return (IUnknown*)&This->IXMLDOMText_iface; 964 } 965 966 #endif 967