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 <UndoInsert.hxx> 32 33 #include <hintids.hxx> 34 #include <unotools/charclass.hxx> 35 #include <sot/storage.hxx> 36 #include <editeng/keepitem.hxx> 37 #include <svx/svdobj.hxx> 38 39 #include <docsh.hxx> 40 #include <fmtcntnt.hxx> 41 #include <fmtanchr.hxx> 42 #include <frmfmt.hxx> 43 #include <doc.hxx> 44 #include <IDocumentUndoRedo.hxx> 45 #include <swundo.hxx> // fuer die UndoIds 46 #include <pam.hxx> 47 #include <ndtxt.hxx> 48 #include <UndoCore.hxx> 49 #include <UndoDelete.hxx> 50 #include <UndoAttribute.hxx> 51 #include <rolbck.hxx> 52 #include <ndgrf.hxx> 53 #include <ndole.hxx> 54 #include <grfatr.hxx> 55 #include <cntfrm.hxx> 56 #include <flyfrm.hxx> 57 #include <fesh.hxx> 58 #include <swtable.hxx> 59 #include <redline.hxx> 60 #include <docary.hxx> 61 #include <acorrect.hxx> 62 #include <dcontact.hxx> 63 64 #include <comcore.hrc> // #111827# 65 #include <undo.hrc> 66 67 using namespace ::com::sun::star; 68 69 70 //------------------------------------------------------------ 71 72 // INSERT 73 74 String * SwUndoInsert::GetTxtFromDoc() const 75 { 76 String * pResult = NULL; 77 78 SwNodeIndex aNd( pDoc->GetNodes(), nNode); 79 SwCntntNode* pCNd = aNd.GetNode().GetCntntNode(); 80 SwPaM aPaM( *pCNd, nCntnt ); 81 82 aPaM.SetMark(); 83 84 if( pCNd->IsTxtNode() ) 85 { 86 pResult = new String( ((SwTxtNode*)pCNd)->GetTxt().Copy(nCntnt-nLen, 87 nLen ) ); 88 89 } 90 91 return pResult; 92 } 93 94 void SwUndoInsert::Init(const SwNodeIndex & rNd) 95 { 96 // Redline beachten 97 pDoc = rNd.GetNode().GetDoc(); 98 if( pDoc->IsRedlineOn() ) 99 { 100 pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, 101 pDoc->GetRedlineAuthor() ); 102 SetRedlineMode( pDoc->GetRedlineMode() ); 103 } 104 105 pUndoTxt = GetTxtFromDoc(); 106 107 bCacheComment = false; 108 } 109 110 // #111827# 111 SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd, xub_StrLen nCnt, 112 xub_StrLen nL, 113 const IDocumentContentOperations::InsertFlags nInsertFlags, 114 sal_Bool bWDelim ) 115 : SwUndo(UNDO_TYPING), pPos( 0 ), pTxt( 0 ), pRedlData( 0 ), 116 nNode( rNd.GetIndex() ), nCntnt(nCnt), nLen(nL), 117 bIsWordDelim( bWDelim ), bIsAppend( sal_False ) 118 , m_nInsertFlags(nInsertFlags) 119 { 120 Init(rNd); 121 } 122 123 // #111827# 124 SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd ) 125 : SwUndo(UNDO_SPLITNODE), pPos( 0 ), pTxt( 0 ), 126 pRedlData( 0 ), nNode( rNd.GetIndex() ), nCntnt(0), nLen(1), 127 bIsWordDelim( sal_False ), bIsAppend( sal_True ) 128 , m_nInsertFlags(IDocumentContentOperations::INS_EMPTYEXPAND) 129 { 130 Init(rNd); 131 } 132 133 // stelle fest, ob das naechste Insert mit dem aktuellen zusammengefasst 134 // werden kann. Wenn ja, dann aender die Laenge und die InsPos. 135 // Dann wird von SwDoc::Insert kein neues Object in die Undoliste gestellt. 136 137 sal_Bool SwUndoInsert::CanGrouping( sal_Unicode cIns ) 138 { 139 if( !bIsAppend && bIsWordDelim == 140 !GetAppCharClass().isLetterNumeric( String( cIns )) ) 141 { 142 nLen++; 143 nCntnt++; 144 145 if (pUndoTxt) 146 pUndoTxt->Insert(cIns); 147 148 return sal_True; 149 } 150 return sal_False; 151 } 152 153 sal_Bool SwUndoInsert::CanGrouping( const SwPosition& rPos ) 154 { 155 sal_Bool bRet = sal_False; 156 if( nNode == rPos.nNode.GetIndex() && 157 nCntnt == rPos.nContent.GetIndex() ) 158 { 159 // Redline beachten 160 SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc(); 161 if( ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & rDoc.GetRedlineMode() ) == 162 ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & GetRedlineMode() ) ) 163 { 164 bRet = sal_True; 165 166 // dann war oder ist noch Redline an: 167 // pruefe, ob an der InsPosition ein anderer Redline 168 // rumsteht. Wenn der gleiche nur einmalig vorhanden ist, 169 // kann zusammen gefasst werden. 170 const SwRedlineTbl& rTbl = rDoc.GetRedlineTbl(); 171 if( rTbl.Count() ) 172 { 173 SwRedlineData aRData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() ); 174 const SwIndexReg* pIReg = rPos.nContent.GetIdxReg(); 175 SwIndex* pIdx; 176 for( sal_uInt16 i = 0; i < rTbl.Count(); ++i ) 177 { 178 SwRedline* pRedl = rTbl[ i ]; 179 if( pIReg == (pIdx = &pRedl->End()->nContent)->GetIdxReg() && 180 nCntnt == pIdx->GetIndex() ) 181 { 182 if( !pRedl->HasMark() || !pRedlData || 183 *pRedl != *pRedlData || *pRedl != aRData ) 184 { 185 bRet = sal_False; 186 break; 187 } 188 } 189 } 190 } 191 } 192 } 193 return bRet; 194 } 195 196 SwUndoInsert::~SwUndoInsert() 197 { 198 if( pPos ) // loesche noch den Bereich aus dem UndoNodes Array 199 { 200 // Insert speichert den Inhalt in der IconSection 201 SwNodes& rUNds = pPos->nNode.GetNode().GetNodes(); 202 if( pPos->nContent.GetIndex() ) // nicht den gesamten Node loeschen 203 { 204 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode(); 205 ASSERT( pTxtNd, "kein TextNode, aus dem geloescht werden soll" ); 206 pTxtNd->EraseText( pPos->nContent ); 207 pPos->nNode++; 208 } 209 pPos->nContent.Assign( 0, 0 ); 210 rUNds.Delete( pPos->nNode, rUNds.GetEndOfExtras().GetIndex() - 211 pPos->nNode.GetIndex() ); 212 delete pPos; 213 } 214 else if( pTxt ) // der eingefuegte Text 215 delete pTxt; 216 delete pRedlData; 217 } 218 219 220 221 void SwUndoInsert::UndoImpl(::sw::UndoRedoContext & rContext) 222 { 223 SwDoc *const pTmpDoc = & rContext.GetDoc(); 224 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 225 226 if( bIsAppend ) 227 { 228 pPam->GetPoint()->nNode = nNode; 229 230 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) 231 { 232 pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 ); 233 pPam->SetMark(); 234 pPam->Move( fnMoveBackward ); 235 pPam->Exchange(); 236 pTmpDoc->DeleteRedline( *pPam, true, USHRT_MAX ); 237 } 238 pPam->DeleteMark(); 239 pTmpDoc->DelFullPara( *pPam ); 240 pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 ); 241 } 242 else 243 { 244 sal_uLong nNd = nNode; 245 xub_StrLen nCnt = nCntnt; 246 if( nLen ) 247 { 248 SwNodeIndex aNd( pTmpDoc->GetNodes(), nNode); 249 SwCntntNode* pCNd = aNd.GetNode().GetCntntNode(); 250 SwPaM aPaM( *pCNd, nCntnt ); 251 252 aPaM.SetMark(); 253 254 SwTxtNode * const pTxtNode( pCNd->GetTxtNode() ); 255 if ( pTxtNode ) 256 { 257 aPaM.GetPoint()->nContent -= nLen; 258 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) 259 pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX ); 260 RemoveIdxFromRange( aPaM, sal_False ); 261 pTxt = new String( pTxtNode->GetTxt().Copy(nCntnt-nLen, nLen) ); 262 pTxtNode->EraseText( aPaM.GetPoint()->nContent, nLen ); 263 } 264 else // ansonsten Grafik/OLE/Text/... 265 { 266 aPaM.Move(fnMoveBackward); 267 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) 268 pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX ); 269 RemoveIdxFromRange( aPaM, sal_False ); 270 } 271 272 nNd = aPaM.GetPoint()->nNode.GetIndex(); 273 nCnt = aPaM.GetPoint()->nContent.GetIndex(); 274 275 if( !pTxt ) 276 { 277 pPos = new SwPosition( *aPaM.GetPoint() ); 278 MoveToUndoNds( aPaM, &pPos->nNode, &pPos->nContent ); 279 } 280 nNode = aPaM.GetPoint()->nNode.GetIndex(); 281 nCntnt = aPaM.GetPoint()->nContent.GetIndex(); 282 } 283 284 // set cursor to Undo range 285 pPam->DeleteMark(); 286 287 pPam->GetPoint()->nNode = nNd; 288 pPam->GetPoint()->nContent.Assign( 289 pPam->GetPoint()->nNode.GetNode().GetCntntNode(), nCnt ); 290 } 291 292 DELETEZ(pUndoTxt); 293 } 294 295 296 void SwUndoInsert::RedoImpl(::sw::UndoRedoContext & rContext) 297 { 298 SwDoc *const pTmpDoc = & rContext.GetDoc(); 299 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 300 pPam->DeleteMark(); 301 302 if( bIsAppend ) 303 { 304 pPam->GetPoint()->nNode = nNode - 1; 305 pTmpDoc->AppendTxtNode( *pPam->GetPoint() ); 306 307 pPam->SetMark(); 308 pPam->Move( fnMoveBackward ); 309 pPam->Exchange(); 310 311 if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) 312 { 313 RedlineMode_t eOld = pTmpDoc->GetRedlineMode(); 314 pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE)); 315 pTmpDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true); 316 pTmpDoc->SetRedlineMode_intern( eOld ); 317 } 318 else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) && 319 pTmpDoc->GetRedlineTbl().Count() ) 320 pTmpDoc->SplitRedline( *pPam ); 321 322 pPam->DeleteMark(); 323 } 324 else 325 { 326 pPam->GetPoint()->nNode = nNode; 327 SwCntntNode *const pCNd = 328 pPam->GetPoint()->nNode.GetNode().GetCntntNode(); 329 pPam->GetPoint()->nContent.Assign( pCNd, nCntnt ); 330 331 if( nLen ) 332 { 333 sal_Bool bMvBkwrd = MovePtBackward( *pPam ); 334 335 if( pTxt ) 336 { 337 SwTxtNode *const pTxtNode = pCNd->GetTxtNode(); 338 ASSERT( pTxtNode, "where is my textnode ?" ); 339 pTxtNode->InsertText( *pTxt, pPam->GetMark()->nContent, 340 m_nInsertFlags ); 341 DELETEZ( pTxt ); 342 } 343 else 344 { 345 // Inhalt wieder einfuegen. (erst pPos abmelden !!) 346 sal_uLong nMvNd = pPos->nNode.GetIndex(); 347 xub_StrLen nMvCnt = pPos->nContent.GetIndex(); 348 DELETEZ( pPos ); 349 MoveFromUndoNds( *pTmpDoc, nMvNd, nMvCnt, *pPam->GetMark() ); 350 } 351 nNode = pPam->GetMark()->nNode.GetIndex(); 352 nCntnt = pPam->GetMark()->nContent.GetIndex(); 353 354 MovePtForward( *pPam, bMvBkwrd ); 355 pPam->Exchange(); 356 if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) 357 { 358 RedlineMode_t eOld = pTmpDoc->GetRedlineMode(); 359 pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE)); 360 pTmpDoc->AppendRedline( new SwRedline( *pRedlData, 361 *pPam ), true); 362 pTmpDoc->SetRedlineMode_intern( eOld ); 363 } 364 else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) && 365 pTmpDoc->GetRedlineTbl().Count() ) 366 pTmpDoc->SplitRedline(*pPam); 367 } 368 } 369 370 pUndoTxt = GetTxtFromDoc(); 371 } 372 373 374 void SwUndoInsert::RepeatImpl(::sw::RepeatContext & rContext) 375 { 376 if( !nLen ) 377 return; 378 379 SwDoc & rDoc = rContext.GetDoc(); 380 SwNodeIndex aNd( rDoc.GetNodes(), nNode ); 381 SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();; 382 383 if( !bIsAppend && 1 == nLen ) // >1 dann immer nur Text, ansonsten Grafik/OLE/Text/... 384 { 385 SwPaM aPaM( *pCNd, nCntnt ); 386 aPaM.SetMark(); 387 aPaM.Move(fnMoveBackward); 388 pCNd = aPaM.GetCntntNode(); 389 } 390 391 // Was passiert mit dem evt. selektierten Bereich ??? 392 393 switch( pCNd->GetNodeType() ) 394 { 395 case ND_TEXTNODE: 396 if( bIsAppend ) 397 { 398 rDoc.AppendTxtNode( *rContext.GetRepeatPaM().GetPoint() ); 399 } 400 else 401 { 402 String aTxt( ((SwTxtNode*)pCNd)->GetTxt() ); 403 ::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo()); 404 rDoc.InsertString( rContext.GetRepeatPaM(), 405 aTxt.Copy( nCntnt - nLen, nLen ) ); 406 } 407 break; 408 case ND_GRFNODE: 409 { 410 SwGrfNode* pGrfNd = (SwGrfNode*)pCNd; 411 String sFile, sFilter; 412 if( pGrfNd->IsGrfLink() ) 413 pGrfNd->GetFileFilterNms( &sFile, &sFilter ); 414 415 rDoc.Insert( rContext.GetRepeatPaM(), sFile, sFilter, 416 &pGrfNd->GetGrf(), 417 0/* Grafik-Collection*/, NULL, NULL ); 418 } 419 break; 420 421 case ND_OLENODE: 422 { 423 // StarView bietet noch nicht die Moeglichkeit ein StarOBJ zu kopieren 424 SvStorageRef aRef = new SvStorage( aEmptyStr ); 425 SwOLEObj& rSwOLE = (SwOLEObj&)((SwOLENode*)pCNd)->GetOLEObj(); 426 427 // temporary storage until object is inserted 428 // TODO/MBA: seems that here a physical copy is done - not as in drawing layer! Testing! 429 // TODO/LATER: Copying through the container would copy the replacement image as well 430 comphelper::EmbeddedObjectContainer aCnt; 431 ::rtl::OUString aName = aCnt.CreateUniqueObjectName(); 432 if ( aCnt.StoreEmbeddedObject( rSwOLE.GetOleRef(), aName, sal_True ) ) 433 { 434 uno::Reference < embed::XEmbeddedObject > aNew = aCnt.GetEmbeddedObject( aName ); 435 rDoc.Insert( rContext.GetRepeatPaM(), 436 svt::EmbeddedObjectRef( aNew, 437 static_cast<SwOLENode*>(pCNd)->GetAspect() ), 438 NULL, NULL, NULL ); 439 } 440 441 break; 442 } 443 } 444 } 445 446 // #111827# 447 SwRewriter SwUndoInsert::GetRewriter() const 448 { 449 SwRewriter aResult; 450 String * pStr = NULL; 451 bool bDone = false; 452 453 if (pTxt) 454 pStr = pTxt; 455 else if (pUndoTxt) 456 pStr = pUndoTxt; 457 458 if (pStr) 459 { 460 String aString = ShortenString(DenoteSpecialCharacters(*pStr), 461 nUndoStringLength, 462 String(SW_RES(STR_LDOTS))); 463 464 aResult.AddRule(UNDO_ARG1, aString); 465 466 bDone = true; 467 } 468 469 if ( ! bDone ) 470 { 471 aResult.AddRule(UNDO_ARG1, String("??", RTL_TEXTENCODING_ASCII_US)); 472 } 473 474 return aResult; 475 } 476 477 478 // SwUndoReplace ///////////////////////////////////////////////////////// 479 480 481 class SwUndoReplace::Impl 482 : private SwUndoSaveCntnt 483 { 484 ::rtl::OUString m_sOld; 485 ::rtl::OUString m_sIns; 486 sal_uLong m_nSttNd, m_nEndNd, m_nOffset; 487 xub_StrLen m_nSttCnt, m_nEndCnt, m_nSetPos, m_nSelEnd; 488 bool m_bSplitNext : 1; 489 bool m_bRegExp : 1; 490 // metadata references for paragraph and following para (if m_bSplitNext) 491 ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart; 492 ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd; 493 494 public: 495 Impl(SwPaM const& rPam, ::rtl::OUString const& rIns, bool const bRegExp); 496 virtual ~Impl() 497 { 498 } 499 500 virtual void UndoImpl( ::sw::UndoRedoContext & ); 501 virtual void RedoImpl( ::sw::UndoRedoContext & ); 502 503 void SetEnd(SwPaM const& rPam); 504 505 ::rtl::OUString const& GetOld() const { return m_sOld; } 506 ::rtl::OUString const& GetIns() const { return m_sIns; } 507 }; 508 509 510 SwUndoReplace::SwUndoReplace(SwPaM const& rPam, 511 ::rtl::OUString const& rIns, bool const bRegExp) 512 : SwUndo( UNDO_REPLACE ) 513 , m_pImpl(new Impl(rPam, rIns, bRegExp)) 514 { 515 } 516 517 SwUndoReplace::~SwUndoReplace() 518 { 519 } 520 521 void SwUndoReplace::UndoImpl(::sw::UndoRedoContext & rContext) 522 { 523 m_pImpl->UndoImpl(rContext); 524 } 525 526 void SwUndoReplace::RedoImpl(::sw::UndoRedoContext & rContext) 527 { 528 m_pImpl->RedoImpl(rContext); 529 } 530 531 SwRewriter 532 MakeUndoReplaceRewriter(sal_uLong const occurrences, 533 ::rtl::OUString const& sOld, ::rtl::OUString const& sNew) 534 { 535 SwRewriter aResult; 536 537 if (1 < occurrences) 538 { 539 aResult.AddRule(UNDO_ARG1, String::CreateFromInt32(occurrences)); 540 aResult.AddRule(UNDO_ARG2, String(SW_RES(STR_OCCURRENCES_OF))); 541 542 String aTmpStr; 543 aTmpStr += String(SW_RES(STR_START_QUOTE)); 544 aTmpStr += ShortenString(sOld, nUndoStringLength, 545 SW_RES(STR_LDOTS)); 546 aTmpStr += String(SW_RES(STR_END_QUOTE)); 547 aResult.AddRule(UNDO_ARG3, aTmpStr); 548 } 549 else if (1 == occurrences) 550 { 551 { 552 String aTmpStr; 553 554 aTmpStr += String(SW_RES(STR_START_QUOTE)); 555 // #i33488 # 556 aTmpStr += ShortenString(sOld, nUndoStringLength, 557 SW_RES(STR_LDOTS)); 558 aTmpStr += String(SW_RES(STR_END_QUOTE)); 559 aResult.AddRule(UNDO_ARG1, aTmpStr); 560 } 561 562 aResult.AddRule(UNDO_ARG2, String(SW_RES(STR_YIELDS))); 563 564 { 565 String aTmpStr; 566 567 aTmpStr += String(SW_RES(STR_START_QUOTE)); 568 // #i33488 # 569 aTmpStr += ShortenString(sNew, nUndoStringLength, 570 SW_RES(STR_LDOTS)); 571 aTmpStr += String(SW_RES(STR_END_QUOTE)); 572 aResult.AddRule(UNDO_ARG3, aTmpStr); 573 } 574 } 575 576 return aResult; 577 } 578 579 // #111827# 580 SwRewriter SwUndoReplace::GetRewriter() const 581 { 582 return MakeUndoReplaceRewriter(1, m_pImpl->GetOld(), m_pImpl->GetIns()); 583 } 584 585 void SwUndoReplace::SetEnd(SwPaM const& rPam) 586 { 587 m_pImpl->SetEnd(rPam); 588 } 589 590 SwUndoReplace::Impl::Impl( 591 SwPaM const& rPam, ::rtl::OUString const& rIns, bool const bRegExp) 592 : m_sIns( rIns ) 593 , m_nOffset( 0 ) 594 , m_bRegExp(bRegExp) 595 { 596 597 const SwPosition * pStt( rPam.Start() ); 598 const SwPosition * pEnd( rPam.End() ); 599 600 m_nSttNd = m_nEndNd = pStt->nNode.GetIndex(); 601 m_nSttCnt = pStt->nContent.GetIndex(); 602 m_nSelEnd = m_nEndCnt = pEnd->nContent.GetIndex(); 603 604 m_bSplitNext = m_nSttNd != pEnd->nNode.GetIndex(); 605 606 SwTxtNode* pNd = pStt->nNode.GetNode().GetTxtNode(); 607 ASSERT( pNd, "wo ist der TextNode" ); 608 609 pHistory = new SwHistory; 610 DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() ); 611 612 m_nSetPos = pHistory->Count(); 613 614 sal_uLong nNewPos = pStt->nNode.GetIndex(); 615 m_nOffset = m_nSttNd - nNewPos; 616 617 if ( pNd->GetpSwpHints() ) 618 { 619 pHistory->CopyAttr( pNd->GetpSwpHints(), nNewPos, 0, 620 pNd->GetTxt().Len(), true ); 621 } 622 623 if ( m_bSplitNext ) 624 { 625 if( pNd->HasSwAttrSet() ) 626 pHistory->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNewPos ); 627 pHistory->Add( pNd->GetTxtColl(), nNewPos, ND_TEXTNODE ); 628 629 SwTxtNode* pNext = pEnd->nNode.GetNode().GetTxtNode(); 630 sal_uLong nTmp = pNext->GetIndex(); 631 pHistory->CopyAttr( pNext->GetpSwpHints(), nTmp, 0, 632 pNext->GetTxt().Len(), true ); 633 if( pNext->HasSwAttrSet() ) 634 pHistory->CopyFmtAttr( *pNext->GetpSwAttrSet(), nTmp ); 635 pHistory->Add( pNext->GetTxtColl(),nTmp, ND_TEXTNODE ); 636 // METADATA: store 637 m_pMetadataUndoStart = pNd ->CreateUndo(); 638 m_pMetadataUndoEnd = pNext->CreateUndo(); 639 } 640 641 if( !pHistory->Count() ) 642 delete pHistory, pHistory = 0; 643 644 xub_StrLen nECnt = m_bSplitNext ? pNd->GetTxt().Len() 645 : pEnd->nContent.GetIndex(); 646 m_sOld = pNd->GetTxt().Copy( m_nSttCnt, nECnt - m_nSttCnt ); 647 } 648 649 void SwUndoReplace::Impl::UndoImpl(::sw::UndoRedoContext & rContext) 650 { 651 SwDoc *const pDoc = & rContext.GetDoc(); 652 SwPaM & rPam(rContext.GetCursorSupplier().CreateNewShellCursor()); 653 rPam.DeleteMark(); 654 655 SwTxtNode* pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode(); 656 ASSERT( pNd, "Wo ist der TextNode geblieben?" ) 657 658 SwAutoCorrExceptWord* pACEWord = pDoc->GetAutoCorrExceptWord(); 659 if( pACEWord ) 660 { 661 if ((1 == m_sIns.getLength()) && (1 == m_sOld.getLength())) 662 { 663 SwPosition aPos( *pNd ); aPos.nContent.Assign( pNd, m_nSttCnt ); 664 pACEWord->CheckChar( aPos, m_sOld[ 0 ] ); 665 } 666 pDoc->SetAutoCorrExceptWord( 0 ); 667 } 668 669 SwIndex aIdx( pNd, sal_uInt16( m_nSttCnt ) ); 670 if( m_nSttNd == m_nEndNd ) 671 { 672 pNd->EraseText( aIdx, sal_uInt16( m_sIns.getLength() ) ); 673 } 674 else 675 { 676 rPam.GetPoint()->nNode = *pNd; 677 rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt ); 678 rPam.SetMark(); 679 rPam.GetPoint()->nNode = m_nEndNd - m_nOffset; 680 rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), m_nEndCnt ); 681 682 pDoc->DeleteAndJoin( rPam ); 683 rPam.DeleteMark(); 684 pNd = rPam.GetNode()->GetTxtNode(); 685 ASSERT( pNd, "Wo ist der TextNode geblieben?" ); 686 aIdx.Assign( pNd, m_nSttCnt ); 687 } 688 689 if( m_bSplitNext ) 690 { 691 SwPosition aPos( *pNd, aIdx ); 692 pDoc->SplitNode( aPos, false ); 693 pNd->RestoreMetadata(m_pMetadataUndoEnd); 694 pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode(); 695 aIdx.Assign( pNd, m_nSttCnt ); 696 // METADATA: restore 697 pNd->RestoreMetadata(m_pMetadataUndoStart); 698 } 699 700 if (m_sOld.getLength()) 701 { 702 pNd->InsertText( m_sOld, aIdx ); 703 } 704 705 if( pHistory ) 706 { 707 if( pNd->GetpSwpHints() ) 708 pNd->ClearSwpHintsArr( true ); 709 710 pHistory->TmpRollback( pDoc, m_nSetPos, false ); 711 if ( m_nSetPos ) // there were footnotes/FlyFrames 712 { 713 // gibts ausser diesen noch andere ? 714 if( m_nSetPos < pHistory->Count() ) 715 { 716 // dann sicher die Attribute anderen Attribute 717 SwHistory aHstr; 718 aHstr.Move( 0, pHistory, m_nSetPos ); 719 pHistory->Rollback( pDoc ); 720 pHistory->Move( 0, &aHstr ); 721 } 722 else 723 { 724 pHistory->Rollback( pDoc ); 725 DELETEZ( pHistory ); 726 } 727 } 728 } 729 730 rPam.GetPoint()->nNode = m_nSttNd; 731 rPam.GetPoint()->nContent = aIdx; 732 } 733 734 void SwUndoReplace::Impl::RedoImpl(::sw::UndoRedoContext & rContext) 735 { 736 SwDoc & rDoc = rContext.GetDoc(); 737 SwPaM & rPam(rContext.GetCursorSupplier().CreateNewShellCursor()); 738 rPam.DeleteMark(); 739 rPam.GetPoint()->nNode = m_nSttNd; 740 741 SwTxtNode* pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode(); 742 ASSERT( pNd, "Wo ist der TextNode geblieben?" ) 743 rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt ); 744 rPam.SetMark(); 745 if( m_bSplitNext ) 746 { 747 rPam.GetPoint()->nNode = m_nSttNd + 1; 748 pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode(); 749 } 750 rPam.GetPoint()->nContent.Assign( pNd, m_nSelEnd ); 751 752 if( pHistory ) 753 { 754 SwHistory* pSave = pHistory; 755 SwHistory aHst; 756 pHistory = &aHst; 757 DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() ); 758 m_nSetPos = pHistory->Count(); 759 760 pHistory = pSave; 761 pHistory->Move( 0, &aHst ); 762 } 763 else 764 { 765 pHistory = new SwHistory; 766 DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() ); 767 m_nSetPos = pHistory->Count(); 768 if( !m_nSetPos ) 769 delete pHistory, pHistory = 0; 770 } 771 772 rDoc.ReplaceRange( rPam, m_sIns, m_bRegExp ); 773 rPam.DeleteMark(); 774 } 775 776 void SwUndoReplace::Impl::SetEnd(SwPaM const& rPam) 777 { 778 if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode ) 779 { 780 // multiple paragraphs were inserted 781 const SwPosition* pEnd = rPam.End(); 782 m_nEndNd = m_nOffset + pEnd->nNode.GetIndex(); 783 m_nEndCnt = pEnd->nContent.GetIndex(); 784 } 785 } 786 787 788 // SwUndoReRead ////////////////////////////////////////////////////////// 789 790 791 SwUndoReRead::SwUndoReRead( const SwPaM& rPam, const SwGrfNode& rGrfNd ) 792 : SwUndo( UNDO_REREAD ), nPos( rPam.GetPoint()->nNode.GetIndex() ) 793 { 794 SaveGraphicData( rGrfNd ); 795 } 796 797 798 SwUndoReRead::~SwUndoReRead() 799 { 800 delete pGrf; 801 delete pNm; 802 delete pFltr; 803 } 804 805 806 void SwUndoReRead::SetAndSave(::sw::UndoRedoContext & rContext) 807 { 808 SwDoc & rDoc = rContext.GetDoc(); 809 SwGrfNode* pGrfNd = rDoc.GetNodes()[ nPos ]->GetGrfNode(); 810 811 if( !pGrfNd ) 812 return ; 813 814 // die alten Werte zwischen speichern 815 Graphic* pOldGrf = pGrf; 816 String* pOldNm = pNm; 817 String* pOldFltr = pFltr; 818 sal_uInt16 nOldMirr = nMirr; 819 820 SaveGraphicData( *pGrfNd ); 821 if( pOldNm ) 822 { 823 pGrfNd->ReRead( *pOldNm, pFltr ? *pFltr : aEmptyStr, 0, 0, sal_True ); 824 delete pOldNm; 825 delete pOldFltr; 826 } 827 else 828 { 829 pGrfNd->ReRead( aEmptyStr, aEmptyStr, pOldGrf, 0, sal_True ); 830 delete pOldGrf; 831 } 832 833 if( RES_MIRROR_GRAPH_DONT != nOldMirr ) 834 pGrfNd->SetAttr( SwMirrorGrf() ); 835 836 rContext.SetSelections(pGrfNd->GetFlyFmt(), 0); 837 } 838 839 840 void SwUndoReRead::UndoImpl(::sw::UndoRedoContext & rContext) 841 { 842 SetAndSave(rContext); 843 } 844 845 846 void SwUndoReRead::RedoImpl(::sw::UndoRedoContext & rContext) 847 { 848 SetAndSave(rContext); 849 } 850 851 852 void SwUndoReRead::SaveGraphicData( const SwGrfNode& rGrfNd ) 853 { 854 if( rGrfNd.IsGrfLink() ) 855 { 856 pNm = new String; 857 pFltr = new String; 858 rGrfNd.GetFileFilterNms( pNm, pFltr ); 859 pGrf = 0; 860 } 861 else 862 { 863 ((SwGrfNode&)rGrfNd).SwapIn( sal_True ); 864 pGrf = new Graphic( rGrfNd.GetGrf() ); 865 pNm = pFltr = 0; 866 } 867 nMirr = rGrfNd.GetSwAttrSet().GetMirrorGrf().GetValue(); 868 } 869 870 /* */ 871 872 SwUndoInsertLabel::SwUndoInsertLabel( const SwLabelType eTyp, 873 const String &rTxt, 874 const String& rSeparator, 875 const String& rNumberSeparator, 876 const sal_Bool bBef, 877 const sal_uInt16 nInitId, 878 const String& rCharacterStyle, 879 const sal_Bool bCpyBorder ) 880 : SwUndo( UNDO_INSERTLABEL ), 881 sText( rTxt ), 882 sSeparator( rSeparator ), 883 sNumberSeparator( rNumberSeparator ),//#i61007# order of captions 884 sCharacterStyle( rCharacterStyle ), 885 nFldId( nInitId ), 886 eType( eTyp ), 887 nLayerId( 0 ), 888 bBefore( bBef ), 889 bCpyBrd( bCpyBorder ) 890 { 891 bUndoKeep = sal_False; 892 OBJECT.pUndoFly = 0; 893 OBJECT.pUndoAttr = 0; 894 } 895 896 SwUndoInsertLabel::~SwUndoInsertLabel() 897 { 898 if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType ) 899 { 900 delete OBJECT.pUndoFly; 901 delete OBJECT.pUndoAttr; 902 } 903 else 904 delete NODE.pUndoInsNd; 905 } 906 907 void SwUndoInsertLabel::UndoImpl(::sw::UndoRedoContext & rContext) 908 { 909 SwDoc & rDoc = rContext.GetDoc(); 910 911 if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType ) 912 { 913 ASSERT( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer nicht initialisiert" ) 914 SwFrmFmt* pFmt; 915 SdrObject *pSdrObj = 0; 916 if( OBJECT.pUndoAttr && 917 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) && 918 ( LTYPE_DRAW != eType || 919 0 != (pSdrObj = pFmt->FindSdrObject()) ) ) 920 { 921 OBJECT.pUndoAttr->UndoImpl(rContext); 922 OBJECT.pUndoFly->UndoImpl(rContext); 923 if( LTYPE_DRAW == eType ) 924 { 925 pSdrObj->SetLayer( nLayerId ); 926 } 927 } 928 } 929 else if( NODE.nNode ) 930 { 931 if ( eType == LTYPE_TABLE && bUndoKeep ) 932 { 933 SwTableNode *pNd = rDoc.GetNodes()[ 934 rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode(); 935 if ( pNd ) 936 pNd->GetTable().GetFrmFmt()->ResetFmtAttr( RES_KEEP ); 937 } 938 SwPaM aPam( rDoc.GetNodes().GetEndOfContent() ); 939 aPam.GetPoint()->nNode = NODE.nNode; 940 aPam.SetMark(); 941 aPam.GetPoint()->nNode = NODE.nNode + 1; 942 NODE.pUndoInsNd = new SwUndoDelete( aPam, sal_True ); 943 } 944 } 945 946 947 void SwUndoInsertLabel::RedoImpl(::sw::UndoRedoContext & rContext) 948 { 949 SwDoc & rDoc = rContext.GetDoc(); 950 951 if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType ) 952 { 953 ASSERT( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer nicht initialisiert" ) 954 SwFrmFmt* pFmt; 955 SdrObject *pSdrObj = 0; 956 if( OBJECT.pUndoAttr && 957 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) && 958 ( LTYPE_DRAW != eType || 959 0 != (pSdrObj = pFmt->FindSdrObject()) ) ) 960 { 961 OBJECT.pUndoFly->RedoImpl(rContext); 962 OBJECT.pUndoAttr->RedoImpl(rContext); 963 if( LTYPE_DRAW == eType ) 964 { 965 pSdrObj->SetLayer( nLayerId ); 966 if( pSdrObj->GetLayer() == rDoc.GetHellId() ) 967 pSdrObj->SetLayer( rDoc.GetHeavenId() ); 968 // OD 02.07.2003 #108784# 969 else if( pSdrObj->GetLayer() == rDoc.GetInvisibleHellId() ) 970 pSdrObj->SetLayer( rDoc.GetInvisibleHeavenId() ); 971 } 972 } 973 } 974 else if( NODE.pUndoInsNd ) 975 { 976 if ( eType == LTYPE_TABLE && bUndoKeep ) 977 { 978 SwTableNode *pNd = rDoc.GetNodes()[ 979 rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode(); 980 if ( pNd ) 981 pNd->GetTable().GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem(sal_True, RES_KEEP) ); 982 } 983 NODE.pUndoInsNd->UndoImpl(rContext); 984 delete NODE.pUndoInsNd, NODE.pUndoInsNd = 0; 985 } 986 } 987 988 void SwUndoInsertLabel::RepeatImpl(::sw::RepeatContext & rContext) 989 { 990 SwDoc & rDoc = rContext.GetDoc(); 991 const SwPosition& rPos = *rContext.GetRepeatPaM().GetPoint(); 992 993 sal_uLong nIdx = 0; 994 995 SwCntntNode* pCNd = rPos.nNode.GetNode().GetCntntNode(); 996 if( pCNd ) 997 switch( eType ) 998 { 999 case LTYPE_TABLE: 1000 { 1001 const SwTableNode* pTNd = pCNd->FindTableNode(); 1002 if( pTNd ) 1003 nIdx = pTNd->GetIndex(); 1004 } 1005 break; 1006 1007 case LTYPE_FLY: 1008 case LTYPE_OBJECT: 1009 { 1010 SwFlyFrm* pFly; 1011 SwCntntFrm *pCnt = pCNd->getLayoutFrm( rDoc.GetCurrentLayout() ); 1012 if( pCnt && 0 != ( pFly = pCnt->FindFlyFrm() ) ) 1013 nIdx = pFly->GetFmt()->GetCntnt().GetCntntIdx()->GetIndex(); 1014 } 1015 break; 1016 case LTYPE_DRAW: 1017 break; 1018 } 1019 1020 if( nIdx ) 1021 { 1022 rDoc.InsertLabel( eType, sText, sSeparator, sNumberSeparator, bBefore, 1023 nFldId, nIdx, sCharacterStyle, bCpyBrd ); 1024 } 1025 } 1026 1027 // #111827# 1028 SwRewriter SwUndoInsertLabel::GetRewriter() const 1029 { 1030 SwRewriter aRewriter; 1031 1032 String aTmpStr; 1033 1034 aTmpStr += String(SW_RES(STR_START_QUOTE)); 1035 aTmpStr += ShortenString(sText, nUndoStringLength, 1036 String(SW_RES(STR_LDOTS))); 1037 aTmpStr += String(SW_RES(STR_END_QUOTE)); 1038 1039 aRewriter.AddRule(UNDO_ARG1, aTmpStr); 1040 1041 return aRewriter; 1042 } 1043 1044 void SwUndoInsertLabel::SetFlys( SwFrmFmt& rOldFly, SfxItemSet& rChgSet, 1045 SwFrmFmt& rNewFly ) 1046 { 1047 if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType ) 1048 { 1049 SwUndoFmtAttrHelper aTmp( rOldFly, false ); 1050 rOldFly.SetFmtAttr( rChgSet ); 1051 if ( aTmp.GetUndo() ) 1052 { 1053 OBJECT.pUndoAttr = aTmp.ReleaseUndo(); 1054 } 1055 OBJECT.pUndoFly = new SwUndoInsLayFmt( &rNewFly,0,0 ); 1056 } 1057 } 1058 1059 void SwUndoInsertLabel::SetDrawObj( sal_uInt8 nLId ) 1060 { 1061 if( LTYPE_DRAW == eType ) 1062 { 1063 nLayerId = nLId; 1064 } 1065 } 1066 1067