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