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