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