1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 #include <com/sun/star/embed/ElementModes.hpp> 32 #include <com/sun/star/embed/XTransactedObject.hpp> 33 #include <tools/urlobj.hxx> 34 #include <sot/stg.hxx> 35 #include <sfx2/docfile.hxx> 36 #include <unotools/localfilehelper.hxx> 37 #include <unotools/ucbstreamhelper.hxx> 38 39 #include <comphelper/storagehelper.hxx> 40 #include <doc.hxx> 41 #include <IDocumentUndoRedo.hxx> 42 #include <docsh.hxx> 43 #include <pam.hxx> 44 #include <swblocks.hxx> 45 #include <ndtxt.hxx> 46 #include <shellio.hxx> 47 #include <poolfmt.hxx> 48 #include <SwXMLTextBlocks.hxx> 49 #include <errhdl.hxx> 50 #include <SwXMLBlockImport.hxx> 51 #include <SwXMLBlockExport.hxx> 52 #include <swerror.h> 53 54 #define STREAM_STGREAD ( STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE ) 55 #define STREAM_STGWRITE ( STREAM_READ | STREAM_WRITE | STREAM_SHARE_DENYWRITE ) 56 57 using namespace ::com::sun::star; 58 59 60 void SwXMLTextBlocks::InitBlockMode ( const uno::Reference < embed::XStorage >& rStorage ) 61 { 62 xBlkRoot = rStorage; 63 xRoot = 0; 64 } 65 66 void SwXMLTextBlocks::ResetBlockMode ( ) 67 { 68 xBlkRoot = 0; 69 xRoot = 0; 70 } 71 72 SwXMLTextBlocks::SwXMLTextBlocks( const String& rFile ) 73 : SwImpBlocks( rFile ), bAutocorrBlock( sal_False ), nFlags ( 0 ) 74 { 75 SwDocShell* pDocSh = new SwDocShell ( SFX_CREATE_MODE_INTERNAL ); 76 if( !pDocSh->DoInitNew( 0 ) ) 77 return; 78 bReadOnly = sal_True; 79 pDoc = pDocSh->GetDoc(); 80 xDocShellRef = pDocSh; 81 pDoc->SetOle2Link( Link() ); 82 pDoc->GetIDocumentUndoRedo().DoUndo(false); 83 pDoc->acquire(); 84 uno::Reference< embed::XStorage > refStg; 85 if( !aDateModified.GetDate() || !aTimeModified.GetTime() ) 86 Touch(); // falls neu angelegt -> neuen ZeitStempel besorgen 87 try 88 { 89 refStg = comphelper::OStorageHelper::GetStorageFromURL( rFile, embed::ElementModes::READWRITE ); 90 bReadOnly = sal_False; 91 } 92 catch( const uno::Exception& ) 93 { 94 //couldn't open the file - maybe it's readonly 95 } 96 if( !refStg.is()) 97 { 98 try 99 { 100 refStg = comphelper::OStorageHelper::GetStorageFromURL( rFile, embed::ElementModes::READ ); 101 } 102 catch( const uno::Exception& ) 103 { 104 DBG_ERROR("exception while creating AutoText storage"); 105 } 106 } 107 InitBlockMode ( refStg ); 108 ReadInfo(); 109 ResetBlockMode (); 110 bInfoChanged = sal_False; 111 } 112 113 SwXMLTextBlocks::SwXMLTextBlocks( const uno::Reference < embed::XStorage >& rStg, const String& rName ) 114 : SwImpBlocks( rName ) 115 , bAutocorrBlock( sal_True ) 116 , nFlags ( 0 ) 117 { 118 SwDocShell* pDocSh = new SwDocShell ( SFX_CREATE_MODE_INTERNAL ); 119 if( !pDocSh->DoInitNew( 0 ) ) 120 return; 121 bReadOnly = sal_False; 122 pDoc = pDocSh->GetDoc(); 123 xDocShellRef = pDocSh; 124 pDoc->SetOle2Link( Link() ); 125 pDoc->GetIDocumentUndoRedo().DoUndo(false); 126 pDoc->acquire(); 127 128 InitBlockMode ( rStg ); 129 ReadInfo(); 130 bInfoChanged = sal_False; 131 } 132 133 SwXMLTextBlocks::~SwXMLTextBlocks() 134 { 135 if ( bInfoChanged ) 136 WriteInfo(); 137 ResetBlockMode (); 138 if(xDocShellRef.Is()) 139 xDocShellRef->DoClose(); 140 xDocShellRef = 0; 141 if( pDoc && !pDoc->release() ) 142 delete pDoc; 143 } 144 145 void SwXMLTextBlocks::ClearDoc() 146 { 147 SwDocShell * pDocShell = pDoc->GetDocShell(); 148 pDocShell->InvalidateModel(); 149 pDocShell->ReactivateModel(); 150 151 pDoc->ClearDoc(); 152 pDocShell->ClearEmbeddedObjects(); 153 } 154 void SwXMLTextBlocks::AddName( const String& rShort, const String& rLong, sal_Bool bOnlyTxt ) 155 { 156 sal_uInt16 nIdx = GetIndex( rShort ); 157 SwBlockName* pNew = NULL; 158 if( nIdx != (sal_uInt16) -1 ) 159 aNames.DeleteAndDestroy( nIdx ); 160 161 GeneratePackageName( rShort, aPackageName ); 162 pNew = new SwBlockName( rShort, rLong, aPackageName ); 163 164 pNew->bIsOnlyTxtFlagInit = sal_True; 165 pNew->bIsOnlyTxt = bOnlyTxt; 166 aNames.C40_PTR_INSERT( SwBlockName, pNew ); 167 bInfoChanged = sal_True; 168 } 169 void SwXMLTextBlocks::AddName( const String& rShort, const String& rLong, 170 const String& rPackageName, sal_Bool bOnlyTxt ) 171 { 172 sal_uInt16 nIdx = GetIndex( rShort ); 173 if( nIdx != (sal_uInt16) -1 ) 174 aNames.DeleteAndDestroy( nIdx ); 175 SwBlockName* pNew = new SwBlockName( rShort, rLong, rPackageName ); 176 pNew->bIsOnlyTxtFlagInit = sal_True; 177 pNew->bIsOnlyTxt = bOnlyTxt; 178 aNames.C40_PTR_INSERT( SwBlockName, pNew ); 179 bInfoChanged = sal_True; 180 } 181 182 sal_uLong SwXMLTextBlocks::Delete( sal_uInt16 n ) 183 { 184 String aPckName (aNames[ n ]->aPackageName); 185 uno::Reference < container::XNameAccess > xAccess( xBlkRoot, uno::UNO_QUERY ); 186 if ( xAccess.is() && 187 xAccess->hasByName( aPckName ) && xBlkRoot->isStreamElement( aPckName ) ) 188 { 189 try 190 { 191 xBlkRoot->removeElement ( aPckName ); 192 uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY ); 193 if ( xTrans.is() ) 194 xTrans->commit(); 195 return 0; 196 } 197 catch ( uno::Exception) 198 { 199 return ERR_SWG_WRITE_ERROR; 200 } 201 } 202 return 0; 203 } 204 205 sal_uLong SwXMLTextBlocks::Rename( sal_uInt16 nIdx, const String& rNewShort, const String& ) 206 { 207 DBG_ASSERT( xBlkRoot.is(), "No storage set" ); 208 if(!xBlkRoot.is()) 209 return 0; 210 String aOldName (aNames[ nIdx ]->aPackageName); 211 aShort = rNewShort; 212 GeneratePackageName( aShort, aPackageName ); 213 if (IsOnlyTextBlock ( nIdx ) ) 214 { 215 String sExt( String::CreateFromAscii( ".xml" )); 216 String aOldStreamName( aOldName ); aOldStreamName += sExt; 217 String aNewStreamName( aPackageName ); aNewStreamName += sExt; 218 219 xRoot = xBlkRoot->openStorageElement( aOldName, embed::ElementModes::READWRITE ); 220 xRoot->renameElement ( aOldStreamName, aNewStreamName ); 221 uno::Reference < embed::XTransactedObject > xTrans( xRoot, uno::UNO_QUERY ); 222 if ( xTrans.is() ) 223 xTrans->commit(); 224 xRoot = 0; 225 } 226 227 if(aOldName != aPackageName) 228 { 229 try 230 { 231 xBlkRoot->renameElement ( aOldName, aPackageName ); 232 } 233 catch( const container::ElementExistException& rEx ) 234 { 235 (void)rEx; 236 } 237 } 238 uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY ); 239 if ( xTrans.is() ) 240 xTrans->commit(); 241 // No need to commit xBlkRoot here as SwTextBlocks::Rename calls 242 // WriteInfo which does the commit 243 return 0; 244 } 245 246 sal_uLong SwXMLTextBlocks::CopyBlock( SwImpBlocks& rDestImp, String& rShort, 247 const String& rLong) 248 { 249 sal_uLong nError = 0; 250 OpenFile(sal_True); 251 rDestImp.OpenFile(sal_False); 252 String aGroup( rShort ); 253 sal_Bool bTextOnly = IsOnlyTextBlock ( rShort ) ;//pImp->pBlkRoot->IsStream( aGroup ); 254 sal_uInt16 nIndex = GetIndex ( rShort ); 255 String sDestShortName( GetPackageName (nIndex) ); 256 sal_uInt16 nIdx = 0; 257 258 DBG_ASSERT( xBlkRoot.is(), "No storage set" ); 259 if(!xBlkRoot.is()) 260 return ERR_SWG_WRITE_ERROR; 261 262 uno::Reference < container::XNameAccess > xAccess( ((SwXMLTextBlocks&)rDestImp).xBlkRoot, uno::UNO_QUERY ); 263 while ( xAccess->hasByName( sDestShortName ) ) 264 { 265 ++nIdx; 266 //falls wirklich mal einer so verrueckt ist 267 if(USHRT_MAX == nIdx) 268 { 269 CloseFile(); 270 rDestImp.CloseFile(); 271 return ERR_SWG_WRITE_ERROR; 272 } 273 sDestShortName += String::CreateFromInt32( nIdx ); 274 } 275 276 try 277 { 278 uno::Reference < embed::XStorage > rSourceRoot = xBlkRoot->openStorageElement( aGroup, embed::ElementModes::READ ); 279 uno::Reference < embed::XStorage > rDestRoot = ((SwXMLTextBlocks&)rDestImp).xBlkRoot->openStorageElement( sDestShortName, embed::ElementModes::READWRITE ); 280 //if(!rSourceRoot.Is()) 281 // nError = ERR_SWG_READ_ERROR; 282 //else 283 //{ 284 rSourceRoot->copyToStorage( rDestRoot ); 285 } 286 catch ( uno::Exception& ) 287 { 288 nError = ERR_SWG_WRITE_ERROR; 289 } 290 291 /* I think this should work now that text only blocks are in sub-storages as well 292 else 293 { 294 SvStorageStreamRef rSourceStream = xBlkRoot->OpenStream( aGroup, STREAM_STGREAD ); 295 SvStorageStreamRef rDestStream = ((SwXMLTextBlocks&)rDestImp).xBlkRoot-> OpenStream( sDestShortName, STREAM_STGWRITE ); 296 if(!rDestStream.Is()) 297 nError = ERR_SWG_WRITE_ERROR; 298 else 299 { 300 if(!rSourceStream->CopyTo(&rDestStream)) 301 nError = ERR_SWG_WRITE_ERROR; 302 else 303 rDestStream->Commit(); 304 } 305 } 306 */ 307 if(!nError) 308 { 309 rShort = sDestShortName; 310 //((SwXMLTextBlocks&)rDestImp).xBlkRoot->Commit(); 311 ((SwXMLTextBlocks&)rDestImp).AddName( rShort, rLong, bTextOnly ); 312 ((SwXMLTextBlocks&)rDestImp).MakeBlockList(); 313 } 314 CloseFile(); 315 rDestImp.CloseFile(); 316 return nError; 317 } 318 319 320 sal_uLong SwXMLTextBlocks::StartPutBlock( const String& rShort, const String& rPackageName ) 321 { 322 DBG_ASSERT( xBlkRoot.is(), "No storage set" ); 323 if(!xBlkRoot.is()) 324 return 0; 325 GetIndex ( rShort ); 326 /* 327 if( xBlkRoot->IsContained( rPackageName ) ) 328 { 329 xBlkRoot->Remove( rPackageName ); 330 xBlkRoot->Commit(); 331 } 332 */ 333 try 334 { 335 xRoot = xBlkRoot->openStorageElement( rPackageName, embed::ElementModes::READWRITE ); 336 337 uno::Reference< beans::XPropertySet > xRootProps( xRoot, uno::UNO_QUERY_THROW ); 338 ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("MediaType") ); 339 ::rtl::OUString aMime( SotExchange::GetFormatMimeType( SOT_FORMATSTR_ID_STARWRITER_8 ) ); 340 xRootProps->setPropertyValue( aPropName, uno::makeAny( aMime ) ); 341 } 342 catch (uno::Exception&) 343 { 344 } 345 return 0; 346 } 347 sal_uLong SwXMLTextBlocks::BeginPutDoc( const String& rShort, const String& rLong ) 348 { 349 // In der Basisklasse ablegen! 350 aShort = rShort; 351 aLong = rLong; 352 GeneratePackageName( rShort, aPackageName ); 353 SetIsTextOnly( rShort, sal_False); 354 return StartPutBlock (rShort, aPackageName); 355 } 356 357 sal_uLong SwXMLTextBlocks::PutBlock( SwPaM& , const String& ) 358 { 359 sal_uLong nRes = 0; 360 sal_uInt16 nCommitFlags = nFlags & (SWXML_CONVBLOCK|SWXML_NOROOTCOMMIT); 361 362 nFlags |= nCommitFlags; 363 364 WriterRef xWrt; 365 ::GetXMLWriter ( aEmptyStr, GetBaseURL(), xWrt); 366 SwWriter aWriter (xRoot, *pDoc ); 367 368 xWrt->bBlock = sal_True; 369 nRes = aWriter.Write ( xWrt ); 370 xWrt->bBlock = sal_False; 371 // Save OLE objects if there are some 372 SwDocShell *pDocSh = pDoc->GetDocShell(); 373 374 sal_Bool bHasChildren = pDocSh && pDocSh->GetEmbeddedObjectContainer().HasEmbeddedObjects(); 375 if( !nRes && bHasChildren ) 376 { 377 // we have to write to the temporary storage first, since the used below functions are optimized 378 // TODO/LATER: it is only a temporary solution, that should be changed soon, the used methods should be 379 // called without optimization 380 381 sal_Bool bOK = sal_False; 382 383 if ( xRoot.is() ) 384 { 385 SfxMedium* pTmpMedium = NULL; 386 try 387 { 388 uno::Reference< embed::XStorage > xTempStorage = 389 ::comphelper::OStorageHelper::GetTemporaryStorage(); 390 391 xRoot->copyToStorage( xTempStorage ); 392 393 // TODO/LATER: no progress bar?! 394 // TODO/MBA: strange construct 395 pTmpMedium = new SfxMedium( xTempStorage, GetBaseURL() ); 396 sal_Bool bTmpOK = pDocSh->SaveAsChildren( *pTmpMedium ); 397 if( bTmpOK ) 398 bTmpOK = pDocSh->SaveCompletedChildren( sal_False ); 399 400 xTempStorage->copyToStorage( xRoot ); 401 bOK = bTmpOK; 402 } 403 catch( uno::Exception& ) 404 { 405 } 406 407 if ( pTmpMedium ) 408 DELETEZ( pTmpMedium ); 409 } 410 411 if( !bOK ) 412 nRes = ERR_SWG_WRITE_ERROR; 413 } 414 415 try 416 { 417 uno::Reference < embed::XTransactedObject > xTrans( xRoot, uno::UNO_QUERY ); 418 if ( xTrans.is() ) 419 xTrans->commit(); 420 xRoot = 0; 421 if ( !nCommitFlags ) 422 { 423 uno::Reference < embed::XTransactedObject > xTmpTrans( xBlkRoot, uno::UNO_QUERY ); 424 if ( xTmpTrans.is() ) 425 xTmpTrans->commit(); 426 } 427 } 428 catch (uno::Exception&) 429 { 430 } 431 432 //TODO/LATER: error handling 433 /* 434 sal_uLong nErr = xBlkRoot->GetError(); 435 if( nErr == SVSTREAM_DISK_FULL ) 436 nRes = ERR_W4W_WRITE_FULL; 437 else if( nErr != SVSTREAM_OK ) 438 nRes = ERR_SWG_WRITE_ERROR; 439 nFlags |= nCommitFlags; 440 return nErr;*/ 441 return 0; 442 } 443 444 sal_uLong SwXMLTextBlocks::PutDoc() 445 { 446 SwPaM* pPaM = MakePaM(); 447 sal_uLong nErr = PutBlock(*pPaM, aLong); 448 delete pPaM; 449 return nErr; 450 } 451 452 sal_uLong SwXMLTextBlocks::GetText( sal_uInt16 nIdx, String& rText ) 453 { 454 return GetBlockText( aNames[ nIdx ]->aShort, rText ); 455 } 456 457 sal_uLong SwXMLTextBlocks::GetText( const String& rShort, String& rText ) 458 { 459 return GetBlockText( rShort, rText ); 460 } 461 462 463 sal_uLong SwXMLTextBlocks::MakeBlockList() 464 { 465 WriteInfo(); 466 return 0; 467 } 468 469 sal_Bool SwXMLTextBlocks::PutMuchEntries( sal_Bool bOn ) 470 { 471 sal_Bool bRet = sal_False; 472 if( bOn ) 473 { 474 if( bInPutMuchBlocks ) 475 { 476 ASSERT( !this, "verschachtelte Aufrufe sind nicht erlaubt" ); 477 } 478 else if( !IsFileChanged() ) 479 { 480 bRet = 0 == OpenFile( sal_False ); 481 if( bRet ) 482 { 483 nFlags |= SWXML_NOROOTCOMMIT; 484 bInPutMuchBlocks = sal_True; 485 } 486 } 487 } 488 else if( bInPutMuchBlocks ) 489 { 490 nFlags &= ~SWXML_NOROOTCOMMIT; 491 if( xBlkRoot.is() ) 492 { 493 try 494 { 495 uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY ); 496 if ( xTrans.is() ) 497 xTrans->commit(); 498 MakeBlockList(); 499 CloseFile(); 500 Touch(); 501 bInPutMuchBlocks = sal_False; 502 bRet = sal_True; 503 } 504 catch (uno::Exception&) 505 { 506 } 507 } 508 } 509 return bRet; 510 } 511 512 sal_uLong SwXMLTextBlocks::OpenFile( sal_Bool bRdOnly ) 513 { 514 if( bAutocorrBlock ) 515 return 0; 516 sal_uLong nRet = 0; 517 try 518 { 519 uno::Reference < embed::XStorage > refStg = comphelper::OStorageHelper::GetStorageFromURL( aFile, 520 bRdOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE ); 521 InitBlockMode ( refStg ); 522 } 523 catch ( uno::Exception& ) 524 { 525 //TODO/LATER: error handling 526 nRet = 1; 527 } 528 529 return nRet; 530 } 531 532 void SwXMLTextBlocks::CloseFile() 533 { 534 if ( !bAutocorrBlock ) 535 { 536 if (bInfoChanged) 537 WriteInfo(); 538 ResetBlockMode(); 539 } 540 } 541 542 void SwXMLTextBlocks::SetIsTextOnly( const String& rShort, sal_Bool bNewValue ) 543 { 544 sal_uInt16 nIdx = GetIndex ( rShort ); 545 if (nIdx != (sal_uInt16) -1 && nIdx != USHRT_MAX) 546 aNames[nIdx]->bIsOnlyTxt = bNewValue; 547 } 548 549 void SwXMLTextBlocks::SetIsTextOnly( sal_uInt16 nIdx, sal_Bool bNewValue ) 550 { 551 aNames[nIdx]->bIsOnlyTxt = bNewValue; 552 } 553 554 sal_Bool SwXMLTextBlocks::IsOnlyTextBlock( const String& rShort ) const 555 { 556 sal_uInt16 nIdx = GetIndex ( rShort ); 557 sal_Bool bRet = sal_False; 558 if (nIdx != (sal_uInt16) -1 && nIdx != USHRT_MAX) 559 { 560 bRet = aNames[nIdx]->bIsOnlyTxt; 561 } 562 return bRet; 563 } 564 sal_Bool SwXMLTextBlocks::IsOnlyTextBlock( sal_uInt16 nIdx ) const 565 { 566 return aNames[nIdx]->bIsOnlyTxt; 567 } 568 569 sal_Bool SwXMLTextBlocks::IsFileUCBStorage( const String & rFileName) 570 { 571 String aName( rFileName ); 572 INetURLObject aObj( aName ); 573 if ( aObj.GetProtocol() == INET_PROT_NOT_VALID ) 574 { 575 String aURL; 576 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL ); 577 aObj.SetURL( aURL ); 578 aName = aObj.GetMainURL( INetURLObject::NO_DECODE ); 579 } 580 581 SvStream * pStm = ::utl::UcbStreamHelper::CreateStream( aName, STREAM_STD_READ ); 582 sal_Bool bRet = UCBStorage::IsStorageFile( pStm ); 583 delete pStm; 584 return bRet; 585 } 586 587 588 589 short SwXMLTextBlocks::GetFileType ( void ) const 590 { 591 return SWBLK_XML; 592 } 593 594 void SwXMLTextBlocks::GeneratePackageName ( const String& rShort, String& rPackageName ) 595 { 596 rPackageName = rShort; 597 xub_StrLen nPos = 0; 598 sal_Unicode pDelims[] = { '!', '/', ':', '.', '\\', 0 }; 599 ByteString sByte ( rPackageName, RTL_TEXTENCODING_UTF7); 600 rPackageName = String (sByte, RTL_TEXTENCODING_ASCII_US); 601 while( STRING_NOTFOUND != ( nPos = rPackageName.SearchChar( pDelims, nPos ))) 602 { 603 rPackageName.SetChar( nPos, '_' ); 604 ++nPos; 605 } 606 } 607 608 sal_uLong SwXMLTextBlocks::PutText( const String& rShort, const String& rName, 609 const String& rText ) 610 { 611 sal_uLong nRes = 0; 612 aShort = rShort; 613 aLong = rName; 614 aCur = rText; 615 SetIsTextOnly( aShort, sal_True ); 616 GeneratePackageName( rShort, aPackageName ); 617 ClearDoc(); 618 nRes = PutBlockText( rShort, rName, rText, aPackageName ); 619 return nRes; 620 } 621 622 void SwXMLTextBlocks::MakeBlockText( const String& rText ) 623 { 624 SwTxtNode* pTxtNode = pDoc->GetNodes()[ pDoc->GetNodes().GetEndOfContent(). 625 GetIndex() - 1 ]->GetTxtNode(); 626 //JP 18.09.98: Bug 56706 - Standard sollte zumindest gesetzt sein! 627 if( pTxtNode->GetTxtColl() == pDoc->GetDfltTxtFmtColl() ) 628 pTxtNode->ChgFmtColl( pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD )); 629 630 xub_StrLen nPos = 0; 631 do 632 { 633 if ( nPos ) 634 { 635 pTxtNode = (SwTxtNode*)pTxtNode->AppendNode( SwPosition( *pTxtNode ) ); 636 } 637 SwIndex aIdx( pTxtNode ); 638 String sTemp(rText.GetToken( 0, '\015', nPos ) ); 639 pTxtNode->InsertText( sTemp, aIdx ); 640 } while ( STRING_NOTFOUND != nPos ); 641 } 642