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 <rolbck.hxx> 32 33 #include <tools/resid.hxx> 34 35 #include <svl/itemiter.hxx> 36 37 #include <editeng/brkitem.hxx> 38 39 #include <hints.hxx> 40 #include <hintids.hxx> 41 #include <fmtftn.hxx> 42 #include <fchrfmt.hxx> 43 #include <fmtflcnt.hxx> 44 #include <fmtrfmrk.hxx> 45 #include <fmtfld.hxx> 46 #include <fmtpdsc.hxx> 47 #include <txtfld.hxx> 48 #include <txtrfmrk.hxx> 49 #include <txttxmrk.hxx> 50 #include <txtftn.hxx> 51 #include <txtflcnt.hxx> 52 #include <fmtanchr.hxx> 53 #include <fmtcnct.hxx> 54 #include <frmfmt.hxx> 55 #include <ftnidx.hxx> 56 #include <doc.hxx> // SwDoc.GetNodes() 57 #include <IDocumentUndoRedo.hxx> 58 #include <docary.hxx> 59 #include <ndtxt.hxx> // SwTxtNode 60 #include <paratr.hxx> // 61 #include <cellatr.hxx> // 62 #include <fldbas.hxx> // fuer Felder 63 #include <pam.hxx> // fuer SwPaM 64 #include <swtable.hxx> 65 #include <ndgrf.hxx> // SwGrfNode 66 #include <UndoCore.hxx> 67 #include <IMark.hxx> // fuer SwBookmark 68 #include <charfmt.hxx> // #i27615# 69 #include <comcore.hrc> 70 #include <undo.hrc> 71 #include <bookmrk.hxx> 72 73 SV_IMPL_PTRARR( SwpHstry, SwHistoryHintPtr) 74 75 String SwHistoryHint::GetDescription() const 76 { 77 return String(); 78 } 79 80 81 SwHistorySetFmt::SwHistorySetFmt( const SfxPoolItem* pFmtHt, sal_uLong nNd ) 82 : SwHistoryHint( HSTRY_SETFMTHNT ) 83 , m_pAttr( pFmtHt->Clone() ) 84 , m_nNodeIndex( nNd ) 85 { 86 switch ( m_pAttr->Which() ) 87 { 88 case RES_PAGEDESC: 89 static_cast<SwFmtPageDesc&>(*m_pAttr).ChgDefinedIn( 0 ); 90 break; 91 case RES_PARATR_DROP: 92 static_cast<SwFmtDrop&>(*m_pAttr).ChgDefinedIn( 0 ); 93 break; 94 case RES_BOXATR_FORMULA: 95 { 96 //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern 97 SwTblBoxFormula& rNew = static_cast<SwTblBoxFormula&>(*m_pAttr); 98 if ( rNew.IsIntrnlName() ) 99 { 100 const SwTblBoxFormula& rOld = 101 *static_cast<const SwTblBoxFormula*>(pFmtHt); 102 const SwNode* pNd = rOld.GetNodeOfFormula(); 103 if ( pNd ) 104 { 105 const SwTableNode* pTableNode = pNd->FindTableNode(); 106 if (pTableNode) 107 { 108 SwTableFmlUpdate aMsgHnt( &pTableNode->GetTable() ); 109 aMsgHnt.eFlags = TBL_BOXNAME; 110 rNew.ChgDefinedIn( rOld.GetDefinedIn() ); 111 rNew.ChangeState( &aMsgHnt ); 112 } 113 } 114 } 115 rNew.ChgDefinedIn( 0 ); 116 } 117 break; 118 } 119 } 120 121 String SwHistorySetFmt::GetDescription() const 122 { 123 String aResult ; 124 125 sal_uInt16 nWhich = m_pAttr->Which(); 126 switch (nWhich) 127 { 128 case RES_BREAK: 129 switch ((static_cast<SvxFmtBreakItem &>(*m_pAttr)).GetBreak()) 130 { 131 case SVX_BREAK_PAGE_BEFORE: 132 case SVX_BREAK_PAGE_AFTER: 133 case SVX_BREAK_PAGE_BOTH: 134 aResult = SW_RES(STR_UNDO_PAGEBREAKS); 135 136 break; 137 case SVX_BREAK_COLUMN_BEFORE: 138 case SVX_BREAK_COLUMN_AFTER: 139 case SVX_BREAK_COLUMN_BOTH: 140 aResult = SW_RES(STR_UNDO_COLBRKS); 141 142 break; 143 default: 144 break; 145 } 146 break; 147 default: 148 break; 149 } 150 151 return aResult; 152 } 153 154 void SwHistorySetFmt::SetInDoc( SwDoc* pDoc, bool bTmpSet ) 155 { 156 SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ]; 157 if ( pNode->IsCntntNode() ) 158 { 159 static_cast<SwCntntNode*>(pNode)->SetAttr( *m_pAttr ); 160 } 161 else if ( pNode->IsTableNode() ) 162 { 163 static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()->SetFmtAttr( 164 *m_pAttr ); 165 } 166 else if ( pNode->IsStartNode() && (SwTableBoxStartNode == 167 static_cast<SwStartNode*>(pNode)->GetStartNodeType()) ) 168 { 169 SwTableNode* pTNd = pNode->FindTableNode(); 170 if ( pTNd ) 171 { 172 SwTableBox* pBox = pTNd->GetTable().GetTblBox( m_nNodeIndex ); 173 if (pBox) 174 { 175 pBox->ClaimFrmFmt()->SetFmtAttr( *m_pAttr ); 176 } 177 } 178 } 179 180 if ( !bTmpSet ) 181 { 182 m_pAttr.reset(); 183 } 184 } 185 186 SwHistorySetFmt::~SwHistorySetFmt() 187 { 188 } 189 190 191 // --> OD 2008-02-27 #refactorlists# - removed <rDoc> 192 SwHistoryResetFmt::SwHistoryResetFmt(const SfxPoolItem* pFmtHt, sal_uLong nNodeIdx) 193 // <-- 194 : SwHistoryHint( HSTRY_RESETFMTHNT ) 195 , m_nNodeIndex( nNodeIdx ) 196 , m_nWhich( pFmtHt->Which() ) 197 { 198 } 199 200 201 void SwHistoryResetFmt::SetInDoc( SwDoc* pDoc, bool ) 202 { 203 SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ]; 204 if ( pNode->IsCntntNode() ) 205 { 206 static_cast<SwCntntNode*>(pNode)->ResetAttr( m_nWhich ); 207 } 208 else if ( pNode->IsTableNode() ) 209 { 210 static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()-> 211 ResetFmtAttr( m_nWhich ); 212 } 213 } 214 215 216 SwHistorySetTxt::SwHistorySetTxt( SwTxtAttr* pTxtHt, sal_uLong nNodePos ) 217 : SwHistoryHint( HSTRY_SETTXTHNT ) 218 , m_nNodeIndex( nNodePos ) 219 , m_nStart( *pTxtHt->GetStart() ) 220 , m_nEnd( *pTxtHt->GetAnyEnd() ) 221 { 222 // !! Achtung: folgende Attribute erzeugen keine FormatAttribute: 223 // - NoLineBreak, NoHypen, Inserted, Deleted 224 // Dafuer muessen Sonderbehandlungen gemacht werden !!! 225 226 // ein bisschen kompliziert, aber ist Ok so: erst vom default 227 // eine Kopie und dann die Werte aus dem Text Attribut zuweisen 228 sal_uInt16 nWhich = pTxtHt->Which(); 229 if ( RES_TXTATR_CHARFMT == nWhich ) 230 { 231 m_pAttr.reset( new SwFmtCharFmt( pTxtHt->GetCharFmt().GetCharFmt() ) ); 232 } 233 else 234 { 235 m_pAttr.reset( pTxtHt->GetAttr().Clone() ); 236 } 237 } 238 239 240 SwHistorySetTxt::~SwHistorySetTxt() 241 { 242 } 243 244 245 void SwHistorySetTxt::SetInDoc( SwDoc* pDoc, bool ) 246 { 247 if ( !m_pAttr.get() ) 248 return; 249 250 if ( RES_TXTATR_CHARFMT == m_pAttr->Which() ) 251 { 252 // ask the Doc if the CharFmt still exists 253 if ( USHRT_MAX == pDoc->GetCharFmts()->GetPos( 254 (static_cast<SwFmtCharFmt&>(*m_pAttr)).GetCharFmt() ) ) 255 return; // do not set, format does not exist 256 } 257 258 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); 259 ASSERT( pTxtNd, "SwHistorySetTxt::SetInDoc: not a TextNode" ); 260 261 if ( pTxtNd ) 262 { 263 pTxtNd->InsertItem( *m_pAttr, m_nStart, m_nEnd, 264 nsSetAttrMode::SETATTR_NOTXTATRCHR | 265 nsSetAttrMode::SETATTR_NOHINTADJUST ); 266 } 267 } 268 269 270 SwHistorySetTxtFld::SwHistorySetTxtFld( SwTxtFld* pTxtFld, sal_uLong nNodePos ) 271 : SwHistoryHint( HSTRY_SETTXTFLDHNT ) 272 , m_pFldType( 0 ) 273 , m_pFld( new SwFmtFld( *pTxtFld->GetFld().GetFld() ) ) 274 { 275 // only copy if not Sys-FieldType 276 SwDoc* pDoc = pTxtFld->GetTxtNode().GetDoc(); 277 278 m_nFldWhich = m_pFld->GetFld()->GetTyp()->Which(); 279 if (m_nFldWhich == RES_DBFLD || 280 m_nFldWhich == RES_USERFLD || 281 m_nFldWhich == RES_SETEXPFLD || 282 m_nFldWhich == RES_DDEFLD || 283 !pDoc->GetSysFldType( m_nFldWhich )) 284 { 285 m_pFldType.reset( m_pFld->GetFld()->GetTyp()->Copy() ); 286 m_pFld->GetFld()->ChgTyp( m_pFldType.get() ); // change field type 287 } 288 m_nNodeIndex = nNodePos; 289 m_nPos = *pTxtFld->GetStart(); 290 } 291 292 String SwHistorySetTxtFld::GetDescription() const 293 { 294 return m_pFld->GetFld()->GetDescription();; 295 } 296 297 SwHistorySetTxtFld::~SwHistorySetTxtFld() 298 { 299 } 300 301 302 void SwHistorySetTxtFld::SetInDoc( SwDoc* pDoc, bool ) 303 { 304 if ( !m_pFld.get() ) 305 return; 306 307 SwFieldType* pNewFldType = m_pFldType.get(); 308 if ( !pNewFldType ) 309 { 310 pNewFldType = pDoc->GetSysFldType( m_nFldWhich ); 311 } 312 else 313 { 314 // register type with the document 315 pNewFldType = pDoc->InsertFldType( *m_pFldType ); 316 } 317 318 m_pFld->GetFld()->ChgTyp( pNewFldType ); // change field type 319 320 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); 321 ASSERT( pTxtNd, "SwHistorySetTxtFld: no TextNode" ); 322 323 if ( pTxtNd ) 324 { 325 pTxtNd->InsertItem( *m_pFld, m_nPos, m_nPos, 326 nsSetAttrMode::SETATTR_NOTXTATRCHR ); 327 } 328 } 329 330 331 332 SwHistorySetRefMark::SwHistorySetRefMark( SwTxtRefMark* pTxtHt, sal_uLong nNodePos ) 333 : SwHistoryHint( HSTRY_SETREFMARKHNT ) 334 , m_RefName( pTxtHt->GetRefMark().GetRefName() ) 335 , m_nNodeIndex( nNodePos ) 336 , m_nStart( *pTxtHt->GetStart() ) 337 , m_nEnd( *pTxtHt->GetAnyEnd() ) 338 { 339 } 340 341 342 void SwHistorySetRefMark::SetInDoc( SwDoc* pDoc, bool ) 343 { 344 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); 345 ASSERT( pTxtNd, "SwHistorySetRefMark: no TextNode" ); 346 if ( !pTxtNd ) 347 return; 348 349 SwFmtRefMark aRefMark( m_RefName ); 350 351 // if a reference mark without an end already exists here: must not insert! 352 if ( m_nStart != m_nEnd || 353 !pTxtNd->GetTxtAttrForCharAt( m_nStart, RES_TXTATR_REFMARK ) ) 354 { 355 pTxtNd->InsertItem( aRefMark, m_nStart, m_nEnd, 356 nsSetAttrMode::SETATTR_NOTXTATRCHR ); 357 } 358 } 359 360 361 SwHistorySetTOXMark::SwHistorySetTOXMark( SwTxtTOXMark* pTxtHt, sal_uLong nNodePos ) 362 : SwHistoryHint( HSTRY_SETTOXMARKHNT ) 363 , m_TOXMark( pTxtHt->GetTOXMark() ) 364 , m_TOXName( m_TOXMark.GetTOXType()->GetTypeName() ) 365 , m_eTOXTypes( m_TOXMark.GetTOXType()->GetType() ) 366 , m_nNodeIndex( nNodePos ) 367 , m_nStart( *pTxtHt->GetStart() ) 368 , m_nEnd( *pTxtHt->GetAnyEnd() ) 369 { 370 m_TOXMark.DeRegister(); 371 } 372 373 374 void SwHistorySetTOXMark::SetInDoc( SwDoc* pDoc, bool ) 375 { 376 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); 377 ASSERT( pTxtNd, "SwHistorySetTOXMark: no TextNode" ); 378 if ( !pTxtNd ) 379 return; 380 381 // search for respective TOX type 382 sal_uInt16 nCnt = pDoc->GetTOXTypeCount( m_eTOXTypes ); 383 SwTOXType* pToxType = 0; 384 for ( sal_uInt16 n = 0; n < nCnt; ++n ) 385 { 386 pToxType = const_cast<SwTOXType*>(pDoc->GetTOXType( m_eTOXTypes, n )); 387 if ( pToxType->GetTypeName() == m_TOXName ) 388 break; 389 pToxType = 0; 390 } 391 392 if ( !pToxType ) // TOX type not found, create new 393 { 394 pToxType = const_cast<SwTOXType*>( 395 pDoc->InsertTOXType( SwTOXType( m_eTOXTypes, m_TOXName ))); 396 } 397 398 SwTOXMark aNew( m_TOXMark ); 399 aNew.RegisterToTOXType( *pToxType ); 400 401 pTxtNd->InsertItem( aNew, m_nStart, m_nEnd, 402 nsSetAttrMode::SETATTR_NOTXTATRCHR ); 403 } 404 405 406 int SwHistorySetTOXMark::IsEqual( const SwTOXMark& rCmp ) const 407 { 408 return m_TOXName == rCmp.GetTOXType()->GetTypeName() && 409 m_eTOXTypes == rCmp.GetTOXType()->GetType() && 410 m_TOXMark.GetAlternativeText() == rCmp.GetAlternativeText() && 411 ( (TOX_INDEX == m_eTOXTypes) 412 ? ( m_TOXMark.GetPrimaryKey() == rCmp.GetPrimaryKey() && 413 m_TOXMark.GetSecondaryKey() == rCmp.GetSecondaryKey() ) 414 : m_TOXMark.GetLevel() == rCmp.GetLevel() 415 ); 416 } 417 418 419 SwHistoryResetTxt::SwHistoryResetTxt( sal_uInt16 nWhich, 420 xub_StrLen nAttrStart, xub_StrLen nAttrEnd, sal_uLong nNodePos ) 421 : SwHistoryHint( HSTRY_RESETTXTHNT ) 422 , m_nNodeIndex( nNodePos ), m_nStart( nAttrStart ), m_nEnd( nAttrEnd ) 423 , m_nAttr( nWhich ) 424 { 425 } 426 427 428 void SwHistoryResetTxt::SetInDoc( SwDoc* pDoc, bool ) 429 { 430 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); 431 ASSERT( pTxtNd, "SwHistoryResetTxt: no TextNode" ); 432 if ( pTxtNd ) 433 { 434 pTxtNd->DeleteAttributes( m_nAttr, m_nStart, m_nEnd ); 435 } 436 } 437 438 439 SwHistorySetFootnote::SwHistorySetFootnote( SwTxtFtn* pTxtFtn, sal_uLong nNodePos ) 440 : SwHistoryHint( HSTRY_SETFTNHNT ) 441 , m_pUndo( new SwUndoSaveSection ) 442 , m_FootnoteNumber( pTxtFtn->GetFtn().GetNumStr() ) 443 , m_nNodeIndex( nNodePos ) 444 , m_nStart( *pTxtFtn->GetStart() ) 445 , m_bEndNote( pTxtFtn->GetFtn().IsEndNote() ) 446 { 447 ASSERT( pTxtFtn->GetStartNode(), 448 "SwHistorySetFootnote: Footnote without Section" ); 449 450 // merke die alte NodePos, denn wer weiss was alles in der SaveSection 451 // gespeichert (geloescht) wird 452 SwDoc* pDoc = const_cast<SwDoc*>(pTxtFtn->GetTxtNode().GetDoc()); 453 SwNode* pSaveNd = pDoc->GetNodes()[ m_nNodeIndex ]; 454 455 //Pointer auf StartNode der FtnSection merken und erstmal den Pointer im 456 //Attribut zuruecksetzen -> Damit werden automatisch die Frms vernichtet. 457 SwNodeIndex aSttIdx( *pTxtFtn->GetStartNode() ); 458 pTxtFtn->SetStartNode( 0, sal_False ); 459 460 m_pUndo->SaveSection( pDoc, aSttIdx ); 461 m_nNodeIndex = pSaveNd->GetIndex(); 462 } 463 464 SwHistorySetFootnote::SwHistorySetFootnote( const SwTxtFtn &rTxtFtn ) 465 : SwHistoryHint( HSTRY_SETFTNHNT ) 466 , m_pUndo( 0 ) 467 , m_FootnoteNumber( rTxtFtn.GetFtn().GetNumStr() ) 468 , m_nNodeIndex( _SwTxtFtn_GetIndex( (&rTxtFtn) ) ) 469 , m_nStart( *rTxtFtn.GetStart() ) 470 , m_bEndNote( rTxtFtn.GetFtn().IsEndNote() ) 471 { 472 ASSERT( rTxtFtn.GetStartNode(), 473 "SwHistorySetFootnote: Footnote without Section" ); 474 } 475 476 String SwHistorySetFootnote::GetDescription() const 477 { 478 return SW_RES(STR_FOOTNOTE); 479 } 480 481 SwHistorySetFootnote::~SwHistorySetFootnote() 482 { 483 } 484 485 486 void SwHistorySetFootnote::SetInDoc( SwDoc* pDoc, bool ) 487 { 488 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); 489 ASSERT( pTxtNd, "SwHistorySetFootnote: no TextNode" ); 490 if ( !pTxtNd ) 491 return; 492 493 if ( m_pUndo.get() ) 494 { 495 // set the footnote in the TextNode 496 SwFmtFtn aTemp( m_bEndNote ); 497 SwFmtFtn& rNew = const_cast<SwFmtFtn&>( 498 static_cast<const SwFmtFtn&>(pDoc->GetAttrPool().Put(aTemp)) ); 499 if ( m_FootnoteNumber.Len() ) 500 { 501 rNew.SetNumStr( m_FootnoteNumber ); 502 } 503 SwTxtFtn* pTxtFtn = new SwTxtFtn( rNew, m_nStart ); 504 505 // create the section of the Footnote 506 SwNodeIndex aIdx( *pTxtNd ); 507 m_pUndo->RestoreSection( pDoc, &aIdx, SwFootnoteStartNode ); 508 pTxtFtn->SetStartNode( &aIdx ); 509 if ( m_pUndo->GetHistory() ) 510 { 511 // create frames only now 512 m_pUndo->GetHistory()->Rollback( pDoc ); 513 } 514 515 pTxtNd->InsertHint( pTxtFtn ); 516 } 517 else 518 { 519 SwTxtFtn * const pFtn = 520 const_cast<SwTxtFtn*>( static_cast<const SwTxtFtn*>( 521 pTxtNd->GetTxtAttrForCharAt( m_nStart ))); 522 SwFmtFtn &rFtn = const_cast<SwFmtFtn&>(pFtn->GetFtn()); 523 rFtn.SetNumStr( m_FootnoteNumber ); 524 if ( rFtn.IsEndNote() != m_bEndNote ) 525 { 526 rFtn.SetEndNote( m_bEndNote ); 527 pFtn->CheckCondColl(); 528 } 529 } 530 } 531 532 533 SwHistoryChangeFmtColl::SwHistoryChangeFmtColl( SwFmtColl* pFmtColl, sal_uLong nNd, 534 sal_uInt8 nNodeWhich ) 535 : SwHistoryHint( HSTRY_CHGFMTCOLL ) 536 , m_pColl( pFmtColl ) 537 , m_nNodeIndex( nNd ) 538 , m_nNodeType( nNodeWhich ) 539 { 540 } 541 542 void SwHistoryChangeFmtColl::SetInDoc( SwDoc* pDoc, bool ) 543 { 544 SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode(); 545 ASSERT( pCntntNd, "SwHistoryChangeFmtColl: no ContentNode" ); 546 547 // before setting the format, check if it is still available in the 548 // document. if it has been deleted, there is no undo! 549 if ( pCntntNd && m_nNodeType == pCntntNd->GetNodeType() ) 550 { 551 if ( ND_TEXTNODE == m_nNodeType ) 552 { 553 if ( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( 554 static_cast<SwTxtFmtColl * const>(m_pColl) )) 555 { 556 pCntntNd->ChgFmtColl( m_pColl ); 557 } 558 } 559 else if ( USHRT_MAX != pDoc->GetGrfFmtColls()->GetPos( 560 static_cast<SwGrfFmtColl * const>(m_pColl) )) 561 { 562 pCntntNd->ChgFmtColl( m_pColl ); 563 } 564 } 565 } 566 567 568 SwHistoryTxtFlyCnt::SwHistoryTxtFlyCnt( SwFrmFmt* const pFlyFmt ) 569 : SwHistoryHint( HSTRY_FLYCNT ) 570 , m_pUndo( new SwUndoDelLayFmt( pFlyFmt ) ) 571 { 572 ASSERT( pFlyFmt, "SwHistoryTxtFlyCnt: no Format" ); 573 m_pUndo->ChgShowSel( sal_False ); 574 } 575 576 577 SwHistoryTxtFlyCnt::~SwHistoryTxtFlyCnt() 578 { 579 } 580 581 582 void SwHistoryTxtFlyCnt::SetInDoc( SwDoc* pDoc, bool ) 583 { 584 ::sw::IShellCursorSupplier *const pISCS(pDoc->GetIShellCursorSupplier()); 585 OSL_ASSERT(pISCS); 586 ::sw::UndoRedoContext context(*pDoc, *pISCS); 587 m_pUndo->UndoImpl(context); 588 } 589 590 591 592 SwHistoryBookmark::SwHistoryBookmark( 593 const ::sw::mark::IMark& rBkmk, 594 bool bSavePos, 595 bool bSaveOtherPos) 596 : SwHistoryHint(HSTRY_BOOKMARK) 597 , m_aName(rBkmk.GetName()) 598 , m_aShortName() 599 , m_aKeycode() 600 , m_nNode(bSavePos ? 601 rBkmk.GetMarkPos().nNode.GetIndex() : 0) 602 , m_nOtherNode(bSaveOtherPos ? 603 rBkmk.GetOtherMarkPos().nNode.GetIndex() : 0) 604 , m_nCntnt(bSavePos ? 605 rBkmk.GetMarkPos().nContent.GetIndex() : 0) 606 , m_nOtherCntnt(bSaveOtherPos ? 607 rBkmk.GetOtherMarkPos().nContent.GetIndex() :0) 608 , m_bSavePos(bSavePos) 609 , m_bSaveOtherPos(bSaveOtherPos) 610 , m_bHadOtherPos(rBkmk.IsExpanded()) 611 , m_eBkmkType(IDocumentMarkAccess::GetType(rBkmk)) 612 { 613 const ::sw::mark::IBookmark* const pBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(&rBkmk); 614 if(pBookmark) 615 { 616 m_aKeycode = pBookmark->GetKeyCode(); 617 m_aShortName = pBookmark->GetShortName(); 618 619 ::sfx2::Metadatable const*const pMetadatable( 620 dynamic_cast< ::sfx2::Metadatable const* >(pBookmark)); 621 if (pMetadatable) 622 { 623 m_pMetadataUndo = pMetadatable->CreateUndo(); 624 } 625 } 626 } 627 628 629 void SwHistoryBookmark::SetInDoc( SwDoc* pDoc, bool ) 630 { 631 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 632 633 SwNodes& rNds = pDoc->GetNodes(); 634 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); 635 ::std::auto_ptr<SwPaM> pPam; 636 ::sw::mark::IMark* pMark = NULL; 637 638 if(m_bSavePos) 639 { 640 SwCntntNode* const pCntntNd = rNds[m_nNode]->GetCntntNode(); 641 OSL_ENSURE(pCntntNd, 642 "<SwHistoryBookmark::SetInDoc(..)>" 643 " - wrong node for a mark"); 644 645 // #111660# don't crash when nNode1 doesn't point to content node. 646 if(pCntntNd) 647 pPam = ::std::auto_ptr<SwPaM>(new SwPaM(*pCntntNd, m_nCntnt)); 648 } 649 else 650 { 651 pMark = pMarkAccess->findMark(m_aName)->get(); 652 pPam = ::std::auto_ptr<SwPaM>(new SwPaM(pMark->GetMarkPos())); 653 } 654 655 if(m_bSaveOtherPos) 656 { 657 SwCntntNode* const pCntntNd = rNds[m_nOtherNode]->GetCntntNode(); 658 OSL_ENSURE(pCntntNd, 659 "<SwHistoryBookmark::SetInDoc(..)>" 660 " - wrong node for a mark"); 661 662 if(pPam.get() != NULL && pCntntNd) 663 { 664 pPam->SetMark(); 665 pPam->GetMark()->nNode = m_nOtherNode; 666 pPam->GetMark()->nContent.Assign(pCntntNd, m_nOtherCntnt); 667 } 668 } 669 else if(m_bHadOtherPos) 670 { 671 if(!pMark) 672 pMark = pMarkAccess->findMark(m_aName)->get(); 673 OSL_ENSURE(pMark->IsExpanded(), 674 "<SwHistoryBookmark::SetInDoc(..)>" 675 " - missing pos on old mark"); 676 pPam->SetMark(); 677 *pPam->GetMark() = pMark->GetOtherMarkPos(); 678 } 679 680 if(pPam.get()) 681 { 682 if(pMark) 683 pMarkAccess->deleteMark(pMark); 684 ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >( 685 pMarkAccess->makeMark(*pPam, m_aName, m_eBkmkType)); 686 if(pBookmark) 687 { 688 pBookmark->SetKeyCode(m_aKeycode); 689 pBookmark->SetShortName(m_aShortName); 690 if (m_pMetadataUndo) 691 { 692 ::sfx2::Metadatable * const pMeta( 693 dynamic_cast< ::sfx2::Metadatable* >(pBookmark)); 694 OSL_ENSURE(pMeta, "metadata undo, but not metadatable?"); 695 if (pMeta) 696 { 697 pMeta->RestoreMetadata(m_pMetadataUndo); 698 } 699 } 700 } 701 } 702 } 703 704 705 bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark& rBkmk) 706 { 707 return m_nNode == rBkmk.GetMarkPos().nNode.GetIndex() 708 && m_nCntnt == rBkmk.GetMarkPos().nContent.GetIndex() 709 && m_aName == rBkmk.GetName(); 710 } 711 712 const ::rtl::OUString& SwHistoryBookmark::GetName() const 713 { 714 return m_aName; 715 } 716 717 /*************************************************************************/ 718 719 720 SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet& rSet, 721 sal_uLong nNodePos, const SvUShortsSort& rSetArr ) 722 : SwHistoryHint( HSTRY_SETATTRSET ) 723 , m_OldSet( rSet ) 724 , m_ResetArray( 0, 4 ) 725 , m_nNodeIndex( nNodePos ) 726 { 727 SfxItemIter aIter( m_OldSet ), aOrigIter( rSet ); 728 const SfxPoolItem* pItem = aIter.FirstItem(), 729 * pOrigItem = aOrigIter.FirstItem(); 730 do { 731 if( !rSetArr.Seek_Entry( pOrigItem->Which() )) 732 { 733 m_ResetArray.Insert( pOrigItem->Which(), m_ResetArray.Count() ); 734 m_OldSet.ClearItem( pOrigItem->Which() ); 735 } 736 else 737 { 738 switch ( pItem->Which() ) 739 { 740 case RES_PAGEDESC: 741 static_cast<SwFmtPageDesc*>( 742 const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 ); 743 break; 744 745 case RES_PARATR_DROP: 746 static_cast<SwFmtDrop*>( 747 const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 ); 748 break; 749 750 case RES_BOXATR_FORMULA: 751 { 752 //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den 753 // Value mit sichern. Der muss gegebenfalls neu 754 // errechnet werden! 755 //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern 756 m_OldSet.ClearItem( RES_BOXATR_VALUE ); 757 758 SwTblBoxFormula& rNew = 759 *static_cast<SwTblBoxFormula*>( 760 const_cast<SfxPoolItem*>(pItem)); 761 if ( rNew.IsIntrnlName() ) 762 { 763 const SwTblBoxFormula& rOld = 764 static_cast<const SwTblBoxFormula&>( 765 rSet.Get( RES_BOXATR_FORMULA )); 766 const SwNode* pNd = rOld.GetNodeOfFormula(); 767 if ( pNd ) 768 { 769 const SwTableNode* pTableNode 770 = pNd->FindTableNode(); 771 if (pTableNode) 772 { 773 SwTableFmlUpdate aMsgHnt( 774 &pTableNode->GetTable() ); 775 aMsgHnt.eFlags = TBL_BOXNAME; 776 rNew.ChgDefinedIn( rOld.GetDefinedIn() ); 777 rNew.ChangeState( &aMsgHnt ); 778 } 779 } 780 } 781 rNew.ChgDefinedIn( 0 ); 782 } 783 break; 784 } 785 } 786 787 if( aIter.IsAtEnd() ) 788 break; 789 pItem = aIter.NextItem(); 790 pOrigItem = aOrigIter.NextItem(); 791 } while( sal_True ); 792 } 793 794 void SwHistorySetAttrSet::SetInDoc( SwDoc* pDoc, bool ) 795 { 796 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 797 798 SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ]; 799 if ( pNode->IsCntntNode() ) 800 { 801 static_cast<SwCntntNode*>(pNode)->SetAttr( m_OldSet ); 802 if ( m_ResetArray.Count() ) 803 { 804 static_cast<SwCntntNode*>(pNode)->ResetAttr( m_ResetArray ); 805 } 806 } 807 else if ( pNode->IsTableNode() ) 808 { 809 SwFmt& rFmt = 810 *static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt(); 811 rFmt.SetFmtAttr( m_OldSet ); 812 if ( m_ResetArray.Count() ) 813 { 814 rFmt.ResetFmtAttr( *m_ResetArray.GetData() ); 815 } 816 } 817 } 818 819 /*************************************************************************/ 820 821 822 SwHistoryResetAttrSet::SwHistoryResetAttrSet( const SfxItemSet& rSet, 823 sal_uLong nNodePos, xub_StrLen nAttrStt, xub_StrLen nAttrEnd ) 824 : SwHistoryHint( HSTRY_RESETATTRSET ) 825 , m_nNodeIndex( nNodePos ), m_nStart( nAttrStt ), m_nEnd( nAttrEnd ) 826 , m_Array( (sal_uInt8)rSet.Count() ) 827 { 828 SfxItemIter aIter( rSet ); 829 bool bAutoStyle = false; 830 831 while( sal_True ) 832 { 833 const sal_uInt16 nWhich = aIter.GetCurItem()->Which(); 834 835 #ifndef PRODUCT 836 switch (nWhich) 837 { 838 case RES_TXTATR_REFMARK: 839 case RES_TXTATR_TOXMARK: 840 if (m_nStart != m_nEnd) break; // else: fall through! 841 case RES_TXTATR_FIELD: 842 case RES_TXTATR_FLYCNT: 843 case RES_TXTATR_FTN: 844 case RES_TXTATR_META: 845 case RES_TXTATR_METAFIELD: 846 ASSERT(rSet.Count() == 1, 847 "text attribute with CH_TXTATR, but not the only one:" 848 "\nnot such a good idea"); 849 break; 850 } 851 #endif 852 853 // Character attribute cannot be inserted into the hints array 854 // anymore. Therefore we have to treat them as one RES_TXTATR_AUTOFMT: 855 if (isCHRATR(nWhich)) 856 { 857 bAutoStyle = true; 858 } 859 else 860 { 861 m_Array.Insert( aIter.GetCurItem()->Which(), m_Array.Count() ); 862 } 863 864 if( aIter.IsAtEnd() ) 865 break; 866 867 aIter.NextItem(); 868 } 869 870 if ( bAutoStyle ) 871 { 872 m_Array.Insert( RES_TXTATR_AUTOFMT, m_Array.Count() ); 873 } 874 } 875 876 877 void SwHistoryResetAttrSet::SetInDoc( SwDoc* pDoc, bool ) 878 { 879 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 880 881 SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode(); 882 ASSERT( pCntntNd, "SwHistoryResetAttrSet: no CntntNode" ); 883 884 if (pCntntNd) 885 { 886 const sal_uInt16* pArr = m_Array.GetData(); 887 if ( USHRT_MAX == m_nEnd && USHRT_MAX == m_nStart ) 888 { 889 // no area: use ContentNode 890 for ( sal_uInt16 n = m_Array.Count(); n; --n, ++pArr ) 891 { 892 pCntntNd->ResetAttr( *pArr ); 893 } 894 } 895 else 896 { 897 // area: use TextNode 898 for ( sal_uInt16 n = m_Array.Count(); n; --n, ++pArr ) 899 { 900 static_cast<SwTxtNode*>(pCntntNd)-> 901 DeleteAttributes( *pArr, m_nStart, m_nEnd ); 902 } 903 } 904 } 905 } 906 907 908 /*************************************************************************/ 909 910 911 SwHistoryChangeFlyAnchor::SwHistoryChangeFlyAnchor( SwFrmFmt& rFmt ) 912 : SwHistoryHint( HSTRY_CHGFLYANCHOR ) 913 , m_rFmt( rFmt ) 914 , m_nOldNodeIndex( rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex() ) 915 , m_nOldContentIndex( (FLY_AT_CHAR == rFmt.GetAnchor().GetAnchorId()) 916 ? rFmt.GetAnchor().GetCntntAnchor()->nContent.GetIndex() 917 : STRING_MAXLEN ) 918 { 919 } 920 921 922 void SwHistoryChangeFlyAnchor::SetInDoc( SwDoc* pDoc, bool ) 923 { 924 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 925 926 sal_uInt16 nPos = pDoc->GetSpzFrmFmts()->GetPos( &m_rFmt ); 927 if ( USHRT_MAX != nPos ) // Format does still exist 928 { 929 SwFmtAnchor aTmp( m_rFmt.GetAnchor() ); 930 931 SwNode* pNd = pDoc->GetNodes()[ m_nOldNodeIndex ]; 932 SwCntntNode* pCNd = pNd->GetCntntNode(); 933 SwPosition aPos( *pNd ); 934 if ( STRING_MAXLEN != m_nOldContentIndex ) 935 { 936 ASSERT(pCNd, "SwHistoryChangeFlyAnchor: no ContentNode"); 937 if (pCNd) 938 { 939 aPos.nContent.Assign( pCNd, m_nOldContentIndex ); 940 } 941 } 942 aTmp.SetAnchor( &aPos ); 943 944 // so the Layout does not get confused 945 if ( !pCNd || !pCNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_False ) ) 946 { 947 m_rFmt.DelFrms(); 948 } 949 950 m_rFmt.SetFmtAttr( aTmp ); 951 } 952 } 953 954 955 /*************************************************************************/ 956 957 SwHistoryChangeFlyChain::SwHistoryChangeFlyChain( SwFlyFrmFmt& rFmt, 958 const SwFmtChain& rAttr ) 959 : SwHistoryHint( HSTRY_CHGFLYCHAIN ) 960 , m_pPrevFmt( rAttr.GetPrev() ) 961 , m_pNextFmt( rAttr.GetNext() ) 962 , m_pFlyFmt( &rFmt ) 963 { 964 } 965 966 967 void SwHistoryChangeFlyChain::SetInDoc( SwDoc* pDoc, bool ) 968 { 969 if ( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pFlyFmt ) ) 970 { 971 SwFmtChain aChain; 972 973 if ( m_pPrevFmt && 974 USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pPrevFmt ) ) 975 { 976 aChain.SetPrev( m_pPrevFmt ); 977 SwFmtChain aTmp( m_pPrevFmt->GetChain() ); 978 aTmp.SetNext( m_pFlyFmt ); 979 m_pPrevFmt->SetFmtAttr( aTmp ); 980 } 981 982 if ( m_pNextFmt && 983 USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pNextFmt ) ) 984 { 985 aChain.SetNext( m_pNextFmt ); 986 SwFmtChain aTmp( m_pNextFmt->GetChain() ); 987 aTmp.SetPrev( m_pFlyFmt ); 988 m_pNextFmt->SetFmtAttr( aTmp ); 989 } 990 991 if ( aChain.GetNext() || aChain.GetPrev() ) 992 { 993 m_pFlyFmt->SetFmtAttr( aChain ); 994 } 995 } 996 } 997 998 999 // -> #i27615# 1000 SwHistoryChangeCharFmt::SwHistoryChangeCharFmt(const SfxItemSet & rSet, 1001 const String & sFmt) 1002 : SwHistoryHint(HSTRY_CHGCHARFMT) 1003 , m_OldSet(rSet), m_Fmt(sFmt) 1004 { 1005 } 1006 1007 void SwHistoryChangeCharFmt::SetInDoc(SwDoc * pDoc, bool ) 1008 { 1009 SwCharFmt * pCharFmt = pDoc->FindCharFmtByName(m_Fmt); 1010 1011 if (pCharFmt) 1012 { 1013 pCharFmt->SetFmtAttr(m_OldSet); 1014 } 1015 } 1016 // <- #i27615# 1017 1018 /* */ 1019 1020 1021 SwHistory::SwHistory( sal_uInt16 nInitSz, sal_uInt16 nGrowSz ) 1022 : m_SwpHstry( (sal_uInt8)nInitSz, (sal_uInt8)nGrowSz ) 1023 , m_nEndDiff( 0 ) 1024 {} 1025 1026 1027 SwHistory::~SwHistory() 1028 { 1029 Delete( 0 ); 1030 } 1031 1032 1033 /************************************************************************* 1034 |* 1035 |* void SwHistory::Add() 1036 |* 1037 |* Beschreibung Dokument 1.0 1038 |* Ersterstellung JP 18.02.91 1039 |* Letzte Aenderung JP 18.02.91 1040 |* 1041 *************************************************************************/ 1042 1043 // --> OD 2008-02-27 #refactorlists# - removed <rDoc> 1044 void SwHistory::Add( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue, 1045 sal_uLong nNodeIdx ) 1046 // <-- 1047 { 1048 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1049 1050 sal_uInt16 nWhich = pNewValue->Which(); 1051 if( (nWhich >= POOLATTR_END) || (nWhich == RES_TXTATR_FIELD) ) 1052 return; 1053 1054 // no default Attribute? 1055 SwHistoryHint * pHt; 1056 if ( pOldValue && pOldValue != GetDfltAttr( pOldValue->Which() ) ) 1057 { 1058 pHt = new SwHistorySetFmt( pOldValue, nNodeIdx ); 1059 } 1060 else 1061 { 1062 pHt = new SwHistoryResetFmt( pNewValue, nNodeIdx ); 1063 } 1064 m_SwpHstry.Insert( pHt, Count() ); 1065 } 1066 1067 1068 void SwHistory::Add( SwTxtAttr* pHint, sal_uLong nNodeIdx, bool bNewAttr ) 1069 { 1070 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1071 1072 SwHistoryHint * pHt; 1073 sal_uInt16 nAttrWhich = pHint->Which(); 1074 1075 if( !bNewAttr ) 1076 { 1077 switch ( nAttrWhich ) 1078 { 1079 case RES_TXTATR_FTN: 1080 pHt = new SwHistorySetFootnote( 1081 static_cast<SwTxtFtn*>(pHint), nNodeIdx ); 1082 break; 1083 case RES_TXTATR_FLYCNT: 1084 pHt = new SwHistoryTxtFlyCnt( static_cast<SwTxtFlyCnt*>(pHint) 1085 ->GetFlyCnt().GetFrmFmt() ); 1086 break; 1087 case RES_TXTATR_FIELD: 1088 pHt = new SwHistorySetTxtFld( 1089 static_cast<SwTxtFld*>(pHint), nNodeIdx ); 1090 break; 1091 case RES_TXTATR_TOXMARK: 1092 pHt = new SwHistorySetTOXMark( 1093 static_cast<SwTxtTOXMark*>(pHint), nNodeIdx ); 1094 break; 1095 case RES_TXTATR_REFMARK: 1096 pHt = new SwHistorySetRefMark( 1097 static_cast<SwTxtRefMark*>(pHint), nNodeIdx ); 1098 break; 1099 default: 1100 pHt = new SwHistorySetTxt( 1101 static_cast<SwTxtAttr*>(pHint), nNodeIdx ); 1102 } 1103 } 1104 else 1105 { 1106 pHt = new SwHistoryResetTxt( pHint->Which(), *pHint->GetStart(), 1107 *pHint->GetAnyEnd(), nNodeIdx ); 1108 } 1109 m_SwpHstry.Insert( pHt, Count() ); 1110 } 1111 1112 1113 void SwHistory::Add( SwFmtColl* pColl, sal_uLong nNodeIdx, sal_uInt8 nWhichNd ) 1114 { 1115 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1116 1117 SwHistoryHint * pHt = 1118 new SwHistoryChangeFmtColl( pColl, nNodeIdx, nWhichNd ); 1119 m_SwpHstry.Insert( pHt, Count() ); 1120 } 1121 1122 1123 void SwHistory::Add(const ::sw::mark::IMark& rBkmk, bool bSavePos, bool bSaveOtherPos) 1124 { 1125 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1126 1127 SwHistoryHint * pHt = new SwHistoryBookmark(rBkmk, bSavePos, bSaveOtherPos); 1128 m_SwpHstry.Insert( pHt, Count() ); 1129 } 1130 1131 1132 void SwHistory::Add( SwFrmFmt& rFmt ) 1133 { 1134 SwHistoryHint * pHt = new SwHistoryChangeFlyAnchor( rFmt ); 1135 m_SwpHstry.Insert( pHt, Count() ); 1136 } 1137 1138 void SwHistory::Add( SwFlyFrmFmt& rFmt, sal_uInt16& rSetPos ) 1139 { 1140 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1141 1142 SwHistoryHint * pHint; 1143 const sal_uInt16 nWh = rFmt.Which(); 1144 if( RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh ) 1145 { 1146 pHint = new SwHistoryTxtFlyCnt( &rFmt ); 1147 m_SwpHstry.Insert( pHint, Count() ); 1148 1149 const SwFmtChain* pChainItem; 1150 if( SFX_ITEM_SET == rFmt.GetItemState( RES_CHAIN, sal_False, 1151 (const SfxPoolItem**)&pChainItem )) 1152 { 1153 if( pChainItem->GetNext() || pChainItem->GetPrev() ) 1154 { 1155 SwHistoryHint * pHt = 1156 new SwHistoryChangeFlyChain( rFmt, *pChainItem ); 1157 m_SwpHstry.Insert( pHt, rSetPos++ ); 1158 if ( pChainItem->GetNext() ) 1159 { 1160 SwFmtChain aTmp( pChainItem->GetNext()->GetChain() ); 1161 aTmp.SetPrev( 0 ); 1162 pChainItem->GetNext()->SetFmtAttr( aTmp ); 1163 } 1164 if ( pChainItem->GetPrev() ) 1165 { 1166 SwFmtChain aTmp( pChainItem->GetPrev()->GetChain() ); 1167 aTmp.SetNext( 0 ); 1168 pChainItem->GetPrev()->SetFmtAttr( aTmp ); 1169 } 1170 } 1171 rFmt.ResetFmtAttr( RES_CHAIN ); 1172 } 1173 } 1174 } 1175 1176 void SwHistory::Add( const SwTxtFtn& rFtn ) 1177 { 1178 SwHistoryHint *pHt = new SwHistorySetFootnote( rFtn ); 1179 m_SwpHstry.Insert( pHt, Count() ); 1180 } 1181 1182 // #i27615# 1183 void SwHistory::Add(const SfxItemSet & rSet, const SwCharFmt & rFmt) 1184 { 1185 SwHistoryHint * pHt = new SwHistoryChangeCharFmt(rSet, rFmt.GetName()); 1186 m_SwpHstry.Insert(pHt, Count()); 1187 } 1188 1189 /************************************************************************* 1190 |* 1191 |* sal_Bool SwHistory::Rollback() 1192 |* 1193 |* Beschreibung Dokument 1.0 1194 |* Ersterstellung JP 18.02.91 1195 |* Letzte Aenderung JP 18.02.91 1196 |* 1197 *************************************************************************/ 1198 1199 1200 bool SwHistory::Rollback( SwDoc* pDoc, sal_uInt16 nStart ) 1201 { 1202 if ( !Count() ) 1203 return false; 1204 1205 SwHistoryHint * pHHt; 1206 sal_uInt16 i; 1207 for ( i = Count(); i > nStart ; ) 1208 { 1209 pHHt = m_SwpHstry[ --i ]; 1210 pHHt->SetInDoc( pDoc, false ); 1211 delete pHHt; 1212 } 1213 m_SwpHstry.Remove( nStart, Count() - nStart ); 1214 m_nEndDiff = 0; 1215 return true; 1216 } 1217 1218 1219 1220 bool SwHistory::TmpRollback( SwDoc* pDoc, sal_uInt16 nStart, bool bToFirst ) 1221 { 1222 sal_uInt16 nEnd = Count() - m_nEndDiff; 1223 if ( !Count() || !nEnd || nStart >= nEnd ) 1224 return false; 1225 1226 SwHistoryHint * pHHt; 1227 if ( bToFirst ) 1228 { 1229 for ( ; nEnd > nStart; ++m_nEndDiff ) 1230 { 1231 pHHt = m_SwpHstry[ --nEnd ]; 1232 pHHt->SetInDoc( pDoc, true ); 1233 } 1234 } 1235 else 1236 { 1237 for ( ; nStart < nEnd; ++m_nEndDiff, ++nStart ) 1238 { 1239 pHHt = m_SwpHstry[ nStart ]; 1240 pHHt->SetInDoc( pDoc, true ); 1241 } 1242 } 1243 return true; 1244 } 1245 1246 1247 void SwHistory::Delete( sal_uInt16 nStart ) 1248 { 1249 for ( sal_uInt16 n = Count(); n > nStart; ) 1250 { 1251 m_SwpHstry.DeleteAndDestroy( --n, 1 ); 1252 } 1253 m_nEndDiff = 0; 1254 } 1255 1256 1257 sal_uInt16 SwHistory::SetTmpEnd( sal_uInt16 nNewTmpEnd ) 1258 { 1259 ASSERT( nNewTmpEnd <= Count(), "SwHistory::SetTmpEnd: out of bounds" ); 1260 1261 sal_uInt16 nOld = Count() - m_nEndDiff; 1262 m_nEndDiff = Count() - nNewTmpEnd; 1263 1264 // for every SwHistoryFlyCnt, call the Redo of its UndoObject. 1265 // this saves the formats of the flys! 1266 for ( sal_uInt16 n = nOld; n < nNewTmpEnd; n++ ) 1267 { 1268 if ( HSTRY_FLYCNT == (*this)[ n ]->Which() ) 1269 { 1270 static_cast<SwHistoryTxtFlyCnt*>((*this)[ n ]) 1271 ->GetUDelLFmt()->RedoForRollback(); 1272 } 1273 } 1274 1275 return nOld; 1276 } 1277 1278 void SwHistory::CopyFmtAttr( const SfxItemSet& rSet, sal_uLong nNodeIdx ) 1279 { 1280 if( rSet.Count() ) 1281 { 1282 SfxItemIter aIter( rSet ); 1283 do { 1284 if( (SfxPoolItem*)-1 != aIter.GetCurItem() ) 1285 { 1286 const SfxPoolItem* pNew = aIter.GetCurItem(); 1287 Add( pNew, pNew, nNodeIdx ); 1288 } 1289 if( aIter.IsAtEnd() ) 1290 break; 1291 aIter.NextItem(); 1292 } while( sal_True ); 1293 } 1294 } 1295 1296 void SwHistory::CopyAttr( SwpHints* pHts, sal_uLong nNodeIdx, 1297 xub_StrLen nStart, xub_StrLen nEnd, bool bFields ) 1298 { 1299 if( !pHts ) 1300 return; 1301 1302 // copy all attributes of the TextNode in the area from nStart to nEnd 1303 SwTxtAttr* pHt; 1304 xub_StrLen nAttrStt; 1305 const xub_StrLen * pEndIdx; 1306 for( sal_uInt16 n = 0; n < pHts->Count(); n++ ) 1307 { 1308 // BP: nAttrStt muss auch bei !pEndIdx gesetzt werden 1309 pHt = pHts->GetTextHint(n); 1310 nAttrStt = *pHt->GetStart(); 1311 // JP: ???? wieso nAttrStt >= nEnd 1312 // if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt >= nEnd ) 1313 if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt > nEnd ) 1314 break; 1315 1316 // Flys und Ftn nie kopieren !! 1317 sal_Bool bNextAttr = sal_False; 1318 switch( pHt->Which() ) 1319 { 1320 case RES_TXTATR_FIELD: 1321 // keine Felder, .. kopieren ?? 1322 if( !bFields ) 1323 bNextAttr = sal_True; 1324 break; 1325 case RES_TXTATR_FLYCNT: 1326 case RES_TXTATR_FTN: 1327 bNextAttr = sal_True; 1328 break; 1329 } 1330 1331 if( bNextAttr ) 1332 continue; 1333 1334 // save all attributes that are somehow in this area 1335 if ( nStart <= nAttrStt ) 1336 { 1337 if ( nEnd > nAttrStt 1338 // JP: ???? wieso nAttrStt >= nEnd 1339 // || (nEnd == nAttrStt && (!pEndIdx || nEnd == pEndIdx->GetIndex())) 1340 ) 1341 { 1342 Add( pHt, nNodeIdx, false ); 1343 } 1344 } 1345 else if ( pEndIdx && nStart < *pEndIdx ) 1346 { 1347 Add( pHt, nNodeIdx, false ); 1348 } 1349 } 1350 } 1351 1352 1353 /*************************************************************************/ 1354 1355 // Klasse zum Registrieren der History am Node, Format, HintsArray, ... 1356 1357 SwRegHistory::SwRegHistory( SwHistory* pHst ) 1358 : SwClient( 0 ) 1359 , m_pHistory( pHst ) 1360 , m_nNodeIndex( ULONG_MAX ) 1361 { 1362 _MakeSetWhichIds(); 1363 } 1364 1365 SwRegHistory::SwRegHistory( SwModify* pRegIn, const SwNode& rNd, 1366 SwHistory* pHst ) 1367 : SwClient( pRegIn ) 1368 , m_pHistory( pHst ) 1369 , m_nNodeIndex( rNd.GetIndex() ) 1370 { 1371 _MakeSetWhichIds(); 1372 } 1373 1374 SwRegHistory::SwRegHistory( const SwNode& rNd, SwHistory* pHst ) 1375 : SwClient( 0 ) 1376 , m_pHistory( pHst ) 1377 , m_nNodeIndex( rNd.GetIndex() ) 1378 { 1379 _MakeSetWhichIds(); 1380 } 1381 1382 void SwRegHistory::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 1383 { 1384 // --> OD 2010-10-05 #i114861# 1385 // Do not handle a "noop" modify 1386 // - e.g. <SwTxtNode::NumRuleChgd()> uses such a "noop" modify 1387 // if ( m_pHistory && ( pOld || pNew ) ) 1388 if ( m_pHistory && ( pOld || pNew ) && 1389 pOld != pNew ) 1390 // <-- 1391 { 1392 if ( pNew->Which() < POOLATTR_END ) 1393 { 1394 m_pHistory->Add( pOld, pNew, m_nNodeIndex ); 1395 } 1396 else if ( RES_ATTRSET_CHG == pNew->Which() ) 1397 { 1398 SwHistoryHint* pNewHstr; 1399 const SfxItemSet& rSet = 1400 *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet(); 1401 if ( 1 < rSet.Count() ) 1402 { 1403 pNewHstr = 1404 new SwHistorySetAttrSet( rSet, m_nNodeIndex, m_WhichIdSet ); 1405 } 1406 else 1407 { 1408 const SfxPoolItem* pItem = SfxItemIter( rSet ).FirstItem(); 1409 if ( m_WhichIdSet.Seek_Entry( pItem->Which() ) ) 1410 { 1411 pNewHstr = new SwHistorySetFmt( pItem, m_nNodeIndex ); 1412 } 1413 else 1414 { 1415 pNewHstr = new SwHistoryResetFmt( pItem, m_nNodeIndex ); 1416 } 1417 } 1418 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() ); 1419 } 1420 } 1421 } 1422 1423 1424 1425 void SwRegHistory::AddHint( SwTxtAttr* pHt, const bool bNew ) 1426 { 1427 m_pHistory->Add( pHt, m_nNodeIndex, bNew ); 1428 } 1429 1430 1431 bool SwRegHistory::InsertItems( const SfxItemSet& rSet, 1432 xub_StrLen const nStart, xub_StrLen const nEnd, SetAttrMode const nFlags ) 1433 { 1434 if( !rSet.Count() ) 1435 return false; 1436 1437 SwTxtNode * const pTxtNode = 1438 dynamic_cast<SwTxtNode *>(const_cast<SwModify *>(GetRegisteredIn())); 1439 1440 ASSERT(pTxtNode, "SwRegHistory not registered at text node?"); 1441 if (!pTxtNode) 1442 return false; 1443 1444 if ( pTxtNode->GetpSwpHints() && m_pHistory ) 1445 { 1446 pTxtNode->GetpSwpHints()->Register( this ); 1447 } 1448 1449 const bool bInserted = pTxtNode->SetAttr( rSet, nStart, nEnd, nFlags ); 1450 1451 // Achtung: Durch das Einfuegen eines Attributs kann das Array 1452 // geloescht werden!!! Wenn das einzufuegende zunaechst ein vorhandenes 1453 // loescht, selbst aber nicht eingefuegt werden braucht, weil die 1454 // Absatzattribute identisch sind( -> bForgetAttr in SwpHints::Insert ) 1455 if ( pTxtNode->GetpSwpHints() && m_pHistory ) 1456 { 1457 pTxtNode->GetpSwpHints()->DeRegister(); 1458 } 1459 1460 if ( m_pHistory && bInserted ) 1461 { 1462 SwHistoryHint* pNewHstr = new SwHistoryResetAttrSet( rSet, 1463 pTxtNode->GetIndex(), nStart, nEnd ); 1464 // der NodeIndex kann verschoben sein !! 1465 1466 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() ); 1467 } 1468 1469 return bInserted; 1470 } 1471 1472 void SwRegHistory::RegisterInModify( SwModify* pRegIn, const SwNode& rNd ) 1473 { 1474 if ( m_pHistory && pRegIn ) 1475 { 1476 pRegIn->Add( this ); 1477 m_nNodeIndex = rNd.GetIndex(); 1478 _MakeSetWhichIds(); 1479 } 1480 else if ( m_WhichIdSet.Count() ) 1481 { 1482 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() ); 1483 } 1484 } 1485 1486 void SwRegHistory::_MakeSetWhichIds() 1487 { 1488 if (!m_pHistory) return; 1489 1490 if ( m_WhichIdSet.Count() ) 1491 { 1492 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() ); 1493 } 1494 1495 if( GetRegisteredIn() ) 1496 { 1497 const SfxItemSet* pSet = 0; 1498 if( GetRegisteredIn()->ISA( SwCntntNode ) ) 1499 { 1500 pSet = static_cast<SwCntntNode*>( 1501 const_cast<SwModify*>(GetRegisteredIn()))->GetpSwAttrSet(); 1502 } 1503 else if ( GetRegisteredIn()->ISA( SwFmt ) ) 1504 { 1505 pSet = &static_cast<SwFmt*>( 1506 const_cast<SwModify*>(GetRegisteredIn()))->GetAttrSet(); 1507 } 1508 if( pSet && pSet->Count() ) 1509 { 1510 SfxItemIter aIter( *pSet ); 1511 sal_uInt16 nW = aIter.FirstItem()->Which(); 1512 while( sal_True ) 1513 { 1514 m_WhichIdSet.Insert( nW ); 1515 if( aIter.IsAtEnd() ) 1516 break; 1517 nW = aIter.NextItem()->Which(); 1518 } 1519 } 1520 } 1521 } 1522 1523