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) 679 pMarkAccess->deleteMark(pMark); 680 ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >( 681 pMarkAccess->makeMark(*pPam, m_aName, m_eBkmkType)); 682 if(pBookmark) 683 { 684 pBookmark->SetKeyCode(m_aKeycode); 685 pBookmark->SetShortName(m_aShortName); 686 if (m_pMetadataUndo) 687 { 688 ::sfx2::Metadatable * const pMeta( 689 dynamic_cast< ::sfx2::Metadatable* >(pBookmark)); 690 OSL_ENSURE(pMeta, "metadata undo, but not metadatable?"); 691 if (pMeta) 692 { 693 pMeta->RestoreMetadata(m_pMetadataUndo); 694 } 695 } 696 } 697 } 698 } 699 700 701 bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark& rBkmk) 702 { 703 return m_nNode == rBkmk.GetMarkPos().nNode.GetIndex() 704 && m_nCntnt == rBkmk.GetMarkPos().nContent.GetIndex() 705 && m_aName == rBkmk.GetName(); 706 } 707 708 const ::rtl::OUString& SwHistoryBookmark::GetName() const 709 { 710 return m_aName; 711 } 712 713 /*************************************************************************/ 714 715 716 SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet& rSet, 717 sal_uLong nNodePos, const SvUShortsSort& rSetArr ) 718 : SwHistoryHint( HSTRY_SETATTRSET ) 719 , m_OldSet( rSet ) 720 , m_ResetArray( 0, 4 ) 721 , m_nNodeIndex( nNodePos ) 722 { 723 SfxItemIter aIter( m_OldSet ), aOrigIter( rSet ); 724 const SfxPoolItem* pItem = aIter.FirstItem(), 725 * pOrigItem = aOrigIter.FirstItem(); 726 do { 727 if( !rSetArr.Seek_Entry( pOrigItem->Which() )) 728 { 729 m_ResetArray.Insert( pOrigItem->Which(), m_ResetArray.Count() ); 730 m_OldSet.ClearItem( pOrigItem->Which() ); 731 } 732 else 733 { 734 switch ( pItem->Which() ) 735 { 736 case RES_PAGEDESC: 737 static_cast<SwFmtPageDesc*>( 738 const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 ); 739 break; 740 741 case RES_PARATR_DROP: 742 static_cast<SwFmtDrop*>( 743 const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 ); 744 break; 745 746 case RES_BOXATR_FORMULA: 747 { 748 //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den 749 // Value mit sichern. Der muss gegebenfalls neu 750 // errechnet werden! 751 //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern 752 m_OldSet.ClearItem( RES_BOXATR_VALUE ); 753 754 SwTblBoxFormula& rNew = 755 *static_cast<SwTblBoxFormula*>( 756 const_cast<SfxPoolItem*>(pItem)); 757 if ( rNew.IsIntrnlName() ) 758 { 759 const SwTblBoxFormula& rOld = 760 static_cast<const SwTblBoxFormula&>( 761 rSet.Get( RES_BOXATR_FORMULA )); 762 const SwNode* pNd = rOld.GetNodeOfFormula(); 763 if ( pNd ) 764 { 765 const SwTableNode* pTableNode 766 = pNd->FindTableNode(); 767 if (pTableNode) 768 { 769 SwTableFmlUpdate aMsgHnt( 770 &pTableNode->GetTable() ); 771 aMsgHnt.eFlags = TBL_BOXNAME; 772 rNew.ChgDefinedIn( rOld.GetDefinedIn() ); 773 rNew.ChangeState( &aMsgHnt ); 774 } 775 } 776 } 777 rNew.ChgDefinedIn( 0 ); 778 } 779 break; 780 } 781 } 782 783 if( aIter.IsAtEnd() ) 784 break; 785 pItem = aIter.NextItem(); 786 pOrigItem = aOrigIter.NextItem(); 787 } while( sal_True ); 788 } 789 790 void SwHistorySetAttrSet::SetInDoc( SwDoc* pDoc, bool ) 791 { 792 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 793 794 SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ]; 795 if ( pNode->IsCntntNode() ) 796 { 797 static_cast<SwCntntNode*>(pNode)->SetAttr( m_OldSet ); 798 if ( m_ResetArray.Count() ) 799 { 800 static_cast<SwCntntNode*>(pNode)->ResetAttr( m_ResetArray ); 801 } 802 } 803 else if ( pNode->IsTableNode() ) 804 { 805 SwFmt& rFmt = 806 *static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt(); 807 rFmt.SetFmtAttr( m_OldSet ); 808 if ( m_ResetArray.Count() ) 809 { 810 rFmt.ResetFmtAttr( *m_ResetArray.GetData() ); 811 } 812 } 813 } 814 815 /*************************************************************************/ 816 817 818 SwHistoryResetAttrSet::SwHistoryResetAttrSet( const SfxItemSet& rSet, 819 sal_uLong nNodePos, xub_StrLen nAttrStt, xub_StrLen nAttrEnd ) 820 : SwHistoryHint( HSTRY_RESETATTRSET ) 821 , m_nNodeIndex( nNodePos ), m_nStart( nAttrStt ), m_nEnd( nAttrEnd ) 822 , m_Array( (sal_uInt8)rSet.Count() ) 823 { 824 SfxItemIter aIter( rSet ); 825 bool bAutoStyle = false; 826 827 while( sal_True ) 828 { 829 const sal_uInt16 nWhich = aIter.GetCurItem()->Which(); 830 831 #ifndef PRODUCT 832 switch (nWhich) 833 { 834 case RES_TXTATR_REFMARK: 835 case RES_TXTATR_TOXMARK: 836 if (m_nStart != m_nEnd) break; // else: fall through! 837 case RES_TXTATR_FIELD: 838 case RES_TXTATR_FLYCNT: 839 case RES_TXTATR_FTN: 840 case RES_TXTATR_META: 841 case RES_TXTATR_METAFIELD: 842 ASSERT(rSet.Count() == 1, 843 "text attribute with CH_TXTATR, but not the only one:" 844 "\nnot such a good idea"); 845 break; 846 } 847 #endif 848 849 // Character attribute cannot be inserted into the hints array 850 // anymore. Therefore we have to treat them as one RES_TXTATR_AUTOFMT: 851 if (isCHRATR(nWhich)) 852 { 853 bAutoStyle = true; 854 } 855 else 856 { 857 m_Array.Insert( aIter.GetCurItem()->Which(), m_Array.Count() ); 858 } 859 860 if( aIter.IsAtEnd() ) 861 break; 862 863 aIter.NextItem(); 864 } 865 866 if ( bAutoStyle ) 867 { 868 m_Array.Insert( RES_TXTATR_AUTOFMT, m_Array.Count() ); 869 } 870 } 871 872 873 void SwHistoryResetAttrSet::SetInDoc( SwDoc* pDoc, bool ) 874 { 875 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 876 877 SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode(); 878 ASSERT( pCntntNd, "SwHistoryResetAttrSet: no CntntNode" ); 879 880 if (pCntntNd) 881 { 882 const sal_uInt16* pArr = m_Array.GetData(); 883 if ( USHRT_MAX == m_nEnd && USHRT_MAX == m_nStart ) 884 { 885 // no area: use ContentNode 886 for ( sal_uInt16 n = m_Array.Count(); n; --n, ++pArr ) 887 { 888 pCntntNd->ResetAttr( *pArr ); 889 } 890 } 891 else 892 { 893 // area: use TextNode 894 for ( sal_uInt16 n = m_Array.Count(); n; --n, ++pArr ) 895 { 896 static_cast<SwTxtNode*>(pCntntNd)-> 897 DeleteAttributes( *pArr, m_nStart, m_nEnd ); 898 } 899 } 900 } 901 } 902 903 904 /*************************************************************************/ 905 906 907 SwHistoryChangeFlyAnchor::SwHistoryChangeFlyAnchor( SwFrmFmt& rFmt ) 908 : SwHistoryHint( HSTRY_CHGFLYANCHOR ) 909 , m_rFmt( rFmt ) 910 , m_nOldNodeIndex( rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex() ) 911 , m_nOldContentIndex( (FLY_AT_CHAR == rFmt.GetAnchor().GetAnchorId()) 912 ? rFmt.GetAnchor().GetCntntAnchor()->nContent.GetIndex() 913 : STRING_MAXLEN ) 914 { 915 } 916 917 918 void SwHistoryChangeFlyAnchor::SetInDoc( SwDoc* pDoc, bool ) 919 { 920 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 921 922 sal_uInt16 nPos = pDoc->GetSpzFrmFmts()->GetPos( &m_rFmt ); 923 if ( USHRT_MAX != nPos ) // Format does still exist 924 { 925 SwFmtAnchor aTmp( m_rFmt.GetAnchor() ); 926 927 SwNode* pNd = pDoc->GetNodes()[ m_nOldNodeIndex ]; 928 SwCntntNode* pCNd = pNd->GetCntntNode(); 929 SwPosition aPos( *pNd ); 930 if ( STRING_MAXLEN != m_nOldContentIndex ) 931 { 932 ASSERT(pCNd, "SwHistoryChangeFlyAnchor: no ContentNode"); 933 if (pCNd) 934 { 935 aPos.nContent.Assign( pCNd, m_nOldContentIndex ); 936 } 937 } 938 aTmp.SetAnchor( &aPos ); 939 940 // so the Layout does not get confused 941 if ( !pCNd || !pCNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_False ) ) 942 { 943 m_rFmt.DelFrms(); 944 } 945 946 m_rFmt.SetFmtAttr( aTmp ); 947 } 948 } 949 950 951 /*************************************************************************/ 952 953 SwHistoryChangeFlyChain::SwHistoryChangeFlyChain( SwFlyFrmFmt& rFmt, 954 const SwFmtChain& rAttr ) 955 : SwHistoryHint( HSTRY_CHGFLYCHAIN ) 956 , m_pPrevFmt( rAttr.GetPrev() ) 957 , m_pNextFmt( rAttr.GetNext() ) 958 , m_pFlyFmt( &rFmt ) 959 { 960 } 961 962 963 void SwHistoryChangeFlyChain::SetInDoc( SwDoc* pDoc, bool ) 964 { 965 if ( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pFlyFmt ) ) 966 { 967 SwFmtChain aChain; 968 969 if ( m_pPrevFmt && 970 USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pPrevFmt ) ) 971 { 972 aChain.SetPrev( m_pPrevFmt ); 973 SwFmtChain aTmp( m_pPrevFmt->GetChain() ); 974 aTmp.SetNext( m_pFlyFmt ); 975 m_pPrevFmt->SetFmtAttr( aTmp ); 976 } 977 978 if ( m_pNextFmt && 979 USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pNextFmt ) ) 980 { 981 aChain.SetNext( m_pNextFmt ); 982 SwFmtChain aTmp( m_pNextFmt->GetChain() ); 983 aTmp.SetPrev( m_pFlyFmt ); 984 m_pNextFmt->SetFmtAttr( aTmp ); 985 } 986 987 if ( aChain.GetNext() || aChain.GetPrev() ) 988 { 989 m_pFlyFmt->SetFmtAttr( aChain ); 990 } 991 } 992 } 993 994 995 // -> #i27615# 996 SwHistoryChangeCharFmt::SwHistoryChangeCharFmt(const SfxItemSet & rSet, 997 const String & sFmt) 998 : SwHistoryHint(HSTRY_CHGCHARFMT) 999 , m_OldSet(rSet), m_Fmt(sFmt) 1000 { 1001 } 1002 1003 void SwHistoryChangeCharFmt::SetInDoc(SwDoc * pDoc, bool ) 1004 { 1005 SwCharFmt * pCharFmt = pDoc->FindCharFmtByName(m_Fmt); 1006 1007 if (pCharFmt) 1008 { 1009 pCharFmt->SetFmtAttr(m_OldSet); 1010 } 1011 } 1012 // <- #i27615# 1013 1014 /* */ 1015 1016 1017 SwHistory::SwHistory( sal_uInt16 nInitSz, sal_uInt16 nGrowSz ) 1018 : m_SwpHstry( (sal_uInt8)nInitSz, (sal_uInt8)nGrowSz ) 1019 , m_nEndDiff( 0 ) 1020 {} 1021 1022 1023 SwHistory::~SwHistory() 1024 { 1025 Delete( 0 ); 1026 } 1027 1028 1029 /************************************************************************* 1030 |* 1031 |* void SwHistory::Add() 1032 |* 1033 |* Beschreibung Dokument 1.0 1034 |* Ersterstellung JP 18.02.91 1035 |* Letzte Aenderung JP 18.02.91 1036 |* 1037 *************************************************************************/ 1038 1039 void SwHistory::Add( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue, 1040 sal_uLong nNodeIdx ) 1041 { 1042 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1043 1044 sal_uInt16 nWhich = pNewValue->Which(); 1045 if( (nWhich >= POOLATTR_END) || (nWhich == RES_TXTATR_FIELD) ) 1046 return; 1047 1048 // no default Attribute? 1049 SwHistoryHint * pHt; 1050 if ( pOldValue && pOldValue != GetDfltAttr( pOldValue->Which() ) ) 1051 { 1052 pHt = new SwHistorySetFmt( pOldValue, nNodeIdx ); 1053 } 1054 else 1055 { 1056 pHt = new SwHistoryResetFmt( pNewValue, nNodeIdx ); 1057 } 1058 m_SwpHstry.Insert( pHt, Count() ); 1059 } 1060 1061 1062 void SwHistory::Add( SwTxtAttr* pHint, sal_uLong nNodeIdx, bool bNewAttr ) 1063 { 1064 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1065 1066 SwHistoryHint * pHt; 1067 sal_uInt16 nAttrWhich = pHint->Which(); 1068 1069 if( !bNewAttr ) 1070 { 1071 switch ( nAttrWhich ) 1072 { 1073 case RES_TXTATR_FTN: 1074 pHt = new SwHistorySetFootnote( 1075 static_cast<SwTxtFtn*>(pHint), nNodeIdx ); 1076 break; 1077 case RES_TXTATR_FLYCNT: 1078 pHt = new SwHistoryTxtFlyCnt( static_cast<SwTxtFlyCnt*>(pHint) 1079 ->GetFlyCnt().GetFrmFmt() ); 1080 break; 1081 case RES_TXTATR_FIELD: 1082 pHt = new SwHistorySetTxtFld( 1083 static_cast<SwTxtFld*>(pHint), nNodeIdx ); 1084 break; 1085 case RES_TXTATR_TOXMARK: 1086 pHt = new SwHistorySetTOXMark( 1087 static_cast<SwTxtTOXMark*>(pHint), nNodeIdx ); 1088 break; 1089 case RES_TXTATR_REFMARK: 1090 pHt = new SwHistorySetRefMark( 1091 static_cast<SwTxtRefMark*>(pHint), nNodeIdx ); 1092 break; 1093 default: 1094 pHt = new SwHistorySetTxt( 1095 static_cast<SwTxtAttr*>(pHint), nNodeIdx ); 1096 } 1097 } 1098 else 1099 { 1100 pHt = new SwHistoryResetTxt( pHint->Which(), *pHint->GetStart(), 1101 *pHint->GetAnyEnd(), nNodeIdx ); 1102 } 1103 m_SwpHstry.Insert( pHt, Count() ); 1104 } 1105 1106 1107 void SwHistory::Add( SwFmtColl* pColl, sal_uLong nNodeIdx, sal_uInt8 nWhichNd ) 1108 { 1109 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1110 1111 SwHistoryHint * pHt = 1112 new SwHistoryChangeFmtColl( pColl, nNodeIdx, nWhichNd ); 1113 m_SwpHstry.Insert( pHt, Count() ); 1114 } 1115 1116 1117 void SwHistory::Add(const ::sw::mark::IMark& rBkmk, bool bSavePos, bool bSaveOtherPos) 1118 { 1119 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1120 1121 SwHistoryHint * pHt = new SwHistoryBookmark(rBkmk, bSavePos, bSaveOtherPos); 1122 m_SwpHstry.Insert( pHt, Count() ); 1123 } 1124 1125 1126 void SwHistory::Add( SwFrmFmt& rFmt ) 1127 { 1128 SwHistoryHint * pHt = new SwHistoryChangeFlyAnchor( rFmt ); 1129 m_SwpHstry.Insert( pHt, Count() ); 1130 } 1131 1132 void SwHistory::Add( SwFlyFrmFmt& rFmt, sal_uInt16& rSetPos ) 1133 { 1134 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1135 1136 SwHistoryHint * pHint; 1137 const sal_uInt16 nWh = rFmt.Which(); 1138 if( RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh ) 1139 { 1140 pHint = new SwHistoryTxtFlyCnt( &rFmt ); 1141 m_SwpHstry.Insert( pHint, Count() ); 1142 1143 const SwFmtChain* pChainItem; 1144 if( SFX_ITEM_SET == rFmt.GetItemState( RES_CHAIN, sal_False, 1145 (const SfxPoolItem**)&pChainItem )) 1146 { 1147 if( pChainItem->GetNext() || pChainItem->GetPrev() ) 1148 { 1149 SwHistoryHint * pHt = 1150 new SwHistoryChangeFlyChain( rFmt, *pChainItem ); 1151 m_SwpHstry.Insert( pHt, rSetPos++ ); 1152 if ( pChainItem->GetNext() ) 1153 { 1154 SwFmtChain aTmp( pChainItem->GetNext()->GetChain() ); 1155 aTmp.SetPrev( 0 ); 1156 pChainItem->GetNext()->SetFmtAttr( aTmp ); 1157 } 1158 if ( pChainItem->GetPrev() ) 1159 { 1160 SwFmtChain aTmp( pChainItem->GetPrev()->GetChain() ); 1161 aTmp.SetNext( 0 ); 1162 pChainItem->GetPrev()->SetFmtAttr( aTmp ); 1163 } 1164 } 1165 rFmt.ResetFmtAttr( RES_CHAIN ); 1166 } 1167 } 1168 } 1169 1170 void SwHistory::Add( const SwTxtFtn& rFtn ) 1171 { 1172 SwHistoryHint *pHt = new SwHistorySetFootnote( rFtn ); 1173 m_SwpHstry.Insert( pHt, Count() ); 1174 } 1175 1176 // #i27615# 1177 void SwHistory::Add(const SfxItemSet & rSet, const SwCharFmt & rFmt) 1178 { 1179 SwHistoryHint * pHt = new SwHistoryChangeCharFmt(rSet, rFmt.GetName()); 1180 m_SwpHstry.Insert(pHt, Count()); 1181 } 1182 1183 /************************************************************************* 1184 |* 1185 |* sal_Bool SwHistory::Rollback() 1186 |* 1187 |* Beschreibung Dokument 1.0 1188 |* Ersterstellung JP 18.02.91 1189 |* Letzte Aenderung JP 18.02.91 1190 |* 1191 *************************************************************************/ 1192 1193 1194 bool SwHistory::Rollback( SwDoc* pDoc, sal_uInt16 nStart ) 1195 { 1196 if ( !Count() ) 1197 return false; 1198 1199 SwHistoryHint * pHHt; 1200 sal_uInt16 i; 1201 for ( i = Count(); i > nStart ; ) 1202 { 1203 pHHt = m_SwpHstry[ --i ]; 1204 pHHt->SetInDoc( pDoc, false ); 1205 delete pHHt; 1206 } 1207 m_SwpHstry.Remove( nStart, Count() - nStart ); 1208 m_nEndDiff = 0; 1209 return true; 1210 } 1211 1212 1213 1214 bool SwHistory::TmpRollback( SwDoc* pDoc, sal_uInt16 nStart, bool bToFirst ) 1215 { 1216 sal_uInt16 nEnd = Count() - m_nEndDiff; 1217 if ( !Count() || !nEnd || nStart >= nEnd ) 1218 return false; 1219 1220 SwHistoryHint * pHHt; 1221 if ( bToFirst ) 1222 { 1223 for ( ; nEnd > nStart; ++m_nEndDiff ) 1224 { 1225 pHHt = m_SwpHstry[ --nEnd ]; 1226 pHHt->SetInDoc( pDoc, true ); 1227 } 1228 } 1229 else 1230 { 1231 for ( ; nStart < nEnd; ++m_nEndDiff, ++nStart ) 1232 { 1233 pHHt = m_SwpHstry[ nStart ]; 1234 pHHt->SetInDoc( pDoc, true ); 1235 } 1236 } 1237 return true; 1238 } 1239 1240 1241 void SwHistory::Delete( sal_uInt16 nStart ) 1242 { 1243 for ( sal_uInt16 n = Count(); n > nStart; ) 1244 { 1245 m_SwpHstry.DeleteAndDestroy( --n, 1 ); 1246 } 1247 m_nEndDiff = 0; 1248 } 1249 1250 1251 sal_uInt16 SwHistory::SetTmpEnd( sal_uInt16 nNewTmpEnd ) 1252 { 1253 ASSERT( nNewTmpEnd <= Count(), "SwHistory::SetTmpEnd: out of bounds" ); 1254 1255 sal_uInt16 nOld = Count() - m_nEndDiff; 1256 m_nEndDiff = Count() - nNewTmpEnd; 1257 1258 // for every SwHistoryFlyCnt, call the Redo of its UndoObject. 1259 // this saves the formats of the flys! 1260 for ( sal_uInt16 n = nOld; n < nNewTmpEnd; n++ ) 1261 { 1262 if ( HSTRY_FLYCNT == (*this)[ n ]->Which() ) 1263 { 1264 static_cast<SwHistoryTxtFlyCnt*>((*this)[ n ]) 1265 ->GetUDelLFmt()->RedoForRollback(); 1266 } 1267 } 1268 1269 return nOld; 1270 } 1271 1272 void SwHistory::CopyFmtAttr( const SfxItemSet& rSet, sal_uLong nNodeIdx ) 1273 { 1274 if( rSet.Count() ) 1275 { 1276 SfxItemIter aIter( rSet ); 1277 do { 1278 if( (SfxPoolItem*)-1 != aIter.GetCurItem() ) 1279 { 1280 const SfxPoolItem* pNew = aIter.GetCurItem(); 1281 Add( pNew, pNew, nNodeIdx ); 1282 } 1283 if( aIter.IsAtEnd() ) 1284 break; 1285 aIter.NextItem(); 1286 } while( sal_True ); 1287 } 1288 } 1289 1290 void SwHistory::CopyAttr( 1291 SwpHints* pHts, 1292 const sal_uLong nNodeIdx, 1293 const xub_StrLen nStart, 1294 const xub_StrLen nEnd, 1295 const bool bCopyFields ) 1296 { 1297 if( !pHts ) 1298 return; 1299 1300 // copy all attributes of the TextNode in the area from nStart to nEnd 1301 SwTxtAttr* pHt; 1302 xub_StrLen nAttrStt; 1303 const xub_StrLen * pEndIdx; 1304 for( sal_uInt16 n = 0; n < pHts->Count(); n++ ) 1305 { 1306 pHt = pHts->GetTextHint(n); 1307 nAttrStt = *pHt->GetStart(); 1308 if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt > nEnd ) 1309 break; 1310 1311 // Flys und Ftn nie kopieren !! 1312 sal_Bool bNextAttr = sal_False; 1313 switch( pHt->Which() ) 1314 { 1315 case RES_TXTATR_FIELD: 1316 case RES_TXTATR_INPUTFIELD: 1317 if( !bCopyFields ) 1318 bNextAttr = sal_True; 1319 break; 1320 case RES_TXTATR_FLYCNT: 1321 case RES_TXTATR_FTN: 1322 bNextAttr = sal_True; 1323 break; 1324 } 1325 1326 if( bNextAttr ) 1327 continue; 1328 1329 // save all attributes that are somehow in this area 1330 if ( nStart <= nAttrStt ) 1331 { 1332 if ( nEnd > nAttrStt ) 1333 { 1334 Add( pHt, nNodeIdx, false ); 1335 } 1336 } 1337 else if ( pEndIdx && nStart < *pEndIdx ) 1338 { 1339 Add( pHt, nNodeIdx, false ); 1340 } 1341 } 1342 } 1343 1344 1345 /*************************************************************************/ 1346 1347 // Klasse zum Registrieren der History am Node, Format, HintsArray, ... 1348 1349 SwRegHistory::SwRegHistory( SwHistory* pHst ) 1350 : SwClient( 0 ) 1351 , m_pHistory( pHst ) 1352 , m_nNodeIndex( ULONG_MAX ) 1353 { 1354 _MakeSetWhichIds(); 1355 } 1356 1357 SwRegHistory::SwRegHistory( SwModify* pRegIn, const SwNode& rNd, 1358 SwHistory* pHst ) 1359 : SwClient( pRegIn ) 1360 , m_pHistory( pHst ) 1361 , m_nNodeIndex( rNd.GetIndex() ) 1362 { 1363 _MakeSetWhichIds(); 1364 } 1365 1366 SwRegHistory::SwRegHistory( const SwNode& rNd, SwHistory* pHst ) 1367 : SwClient( 0 ) 1368 , m_pHistory( pHst ) 1369 , m_nNodeIndex( rNd.GetIndex() ) 1370 { 1371 _MakeSetWhichIds(); 1372 } 1373 1374 void SwRegHistory::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 1375 { 1376 // --> OD 2010-10-05 #i114861# 1377 // Do not handle a "noop" modify 1378 // - e.g. <SwTxtNode::NumRuleChgd()> uses such a "noop" modify 1379 // if ( m_pHistory && ( pOld || pNew ) ) 1380 if ( m_pHistory && ( pOld || pNew ) && 1381 pOld != pNew ) 1382 // <-- 1383 { 1384 if ( pNew->Which() < POOLATTR_END ) 1385 { 1386 m_pHistory->Add( pOld, pNew, m_nNodeIndex ); 1387 } 1388 else if ( RES_ATTRSET_CHG == pNew->Which() ) 1389 { 1390 SwHistoryHint* pNewHstr; 1391 const SfxItemSet& rSet = 1392 *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet(); 1393 if ( 1 < rSet.Count() ) 1394 { 1395 pNewHstr = 1396 new SwHistorySetAttrSet( rSet, m_nNodeIndex, m_WhichIdSet ); 1397 } 1398 else 1399 { 1400 const SfxPoolItem* pItem = SfxItemIter( rSet ).FirstItem(); 1401 if ( m_WhichIdSet.Seek_Entry( pItem->Which() ) ) 1402 { 1403 pNewHstr = new SwHistorySetFmt( pItem, m_nNodeIndex ); 1404 } 1405 else 1406 { 1407 pNewHstr = new SwHistoryResetFmt( pItem, m_nNodeIndex ); 1408 } 1409 } 1410 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() ); 1411 } 1412 } 1413 } 1414 1415 1416 1417 void SwRegHistory::AddHint( SwTxtAttr* pHt, const bool bNew ) 1418 { 1419 m_pHistory->Add( pHt, m_nNodeIndex, bNew ); 1420 } 1421 1422 1423 bool SwRegHistory::InsertItems( const SfxItemSet& rSet, 1424 xub_StrLen const nStart, xub_StrLen const nEnd, SetAttrMode const nFlags ) 1425 { 1426 if( !rSet.Count() ) 1427 return false; 1428 1429 SwTxtNode * const pTxtNode = 1430 dynamic_cast<SwTxtNode *>(const_cast<SwModify *>(GetRegisteredIn())); 1431 1432 ASSERT(pTxtNode, "SwRegHistory not registered at text node?"); 1433 if (!pTxtNode) 1434 return false; 1435 1436 if ( pTxtNode->GetpSwpHints() && m_pHistory ) 1437 { 1438 pTxtNode->GetpSwpHints()->Register( this ); 1439 } 1440 1441 const bool bInserted = pTxtNode->SetAttr( rSet, nStart, nEnd, nFlags ); 1442 1443 // Achtung: Durch das Einfuegen eines Attributs kann das Array 1444 // geloescht werden!!! Wenn das einzufuegende zunaechst ein vorhandenes 1445 // loescht, selbst aber nicht eingefuegt werden braucht, weil die 1446 // Absatzattribute identisch sind( -> bForgetAttr in SwpHints::Insert ) 1447 if ( pTxtNode->GetpSwpHints() && m_pHistory ) 1448 { 1449 pTxtNode->GetpSwpHints()->DeRegister(); 1450 } 1451 1452 if ( m_pHistory && bInserted ) 1453 { 1454 SwHistoryHint* pNewHstr = new SwHistoryResetAttrSet( rSet, 1455 pTxtNode->GetIndex(), nStart, nEnd ); 1456 // der NodeIndex kann verschoben sein !! 1457 1458 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() ); 1459 } 1460 1461 return bInserted; 1462 } 1463 1464 void SwRegHistory::RegisterInModify( SwModify* pRegIn, const SwNode& rNd ) 1465 { 1466 if ( m_pHistory && pRegIn ) 1467 { 1468 pRegIn->Add( this ); 1469 m_nNodeIndex = rNd.GetIndex(); 1470 _MakeSetWhichIds(); 1471 } 1472 else if ( m_WhichIdSet.Count() ) 1473 { 1474 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() ); 1475 } 1476 } 1477 1478 void SwRegHistory::_MakeSetWhichIds() 1479 { 1480 if (!m_pHistory) return; 1481 1482 if ( m_WhichIdSet.Count() ) 1483 { 1484 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() ); 1485 } 1486 1487 if( GetRegisteredIn() ) 1488 { 1489 const SfxItemSet* pSet = 0; 1490 if( GetRegisteredIn()->ISA( SwCntntNode ) ) 1491 { 1492 pSet = static_cast<SwCntntNode*>( 1493 const_cast<SwModify*>(GetRegisteredIn()))->GetpSwAttrSet(); 1494 } 1495 else if ( GetRegisteredIn()->ISA( SwFmt ) ) 1496 { 1497 pSet = &static_cast<SwFmt*>( 1498 const_cast<SwModify*>(GetRegisteredIn()))->GetAttrSet(); 1499 } 1500 if( pSet && pSet->Count() ) 1501 { 1502 SfxItemIter aIter( *pSet ); 1503 sal_uInt16 nW = aIter.FirstItem()->Which(); 1504 while( sal_True ) 1505 { 1506 m_WhichIdSet.Insert( nW ); 1507 if( aIter.IsAtEnd() ) 1508 break; 1509 nW = aIter.NextItem()->Which(); 1510 } 1511 } 1512 } 1513 } 1514 1515