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 // --> OD 2008-02-27 #refactorlists# - removed <rDoc> 1040 void SwHistory::Add( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue, 1041 sal_uLong nNodeIdx ) 1042 // <-- 1043 { 1044 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1045 1046 sal_uInt16 nWhich = pNewValue->Which(); 1047 if( (nWhich >= POOLATTR_END) || (nWhich == RES_TXTATR_FIELD) ) 1048 return; 1049 1050 // no default Attribute? 1051 SwHistoryHint * pHt; 1052 if ( pOldValue && pOldValue != GetDfltAttr( pOldValue->Which() ) ) 1053 { 1054 pHt = new SwHistorySetFmt( pOldValue, nNodeIdx ); 1055 } 1056 else 1057 { 1058 pHt = new SwHistoryResetFmt( pNewValue, nNodeIdx ); 1059 } 1060 m_SwpHstry.Insert( pHt, Count() ); 1061 } 1062 1063 1064 void SwHistory::Add( SwTxtAttr* pHint, sal_uLong nNodeIdx, bool bNewAttr ) 1065 { 1066 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1067 1068 SwHistoryHint * pHt; 1069 sal_uInt16 nAttrWhich = pHint->Which(); 1070 1071 if( !bNewAttr ) 1072 { 1073 switch ( nAttrWhich ) 1074 { 1075 case RES_TXTATR_FTN: 1076 pHt = new SwHistorySetFootnote( 1077 static_cast<SwTxtFtn*>(pHint), nNodeIdx ); 1078 break; 1079 case RES_TXTATR_FLYCNT: 1080 pHt = new SwHistoryTxtFlyCnt( static_cast<SwTxtFlyCnt*>(pHint) 1081 ->GetFlyCnt().GetFrmFmt() ); 1082 break; 1083 case RES_TXTATR_FIELD: 1084 pHt = new SwHistorySetTxtFld( 1085 static_cast<SwTxtFld*>(pHint), nNodeIdx ); 1086 break; 1087 case RES_TXTATR_TOXMARK: 1088 pHt = new SwHistorySetTOXMark( 1089 static_cast<SwTxtTOXMark*>(pHint), nNodeIdx ); 1090 break; 1091 case RES_TXTATR_REFMARK: 1092 pHt = new SwHistorySetRefMark( 1093 static_cast<SwTxtRefMark*>(pHint), nNodeIdx ); 1094 break; 1095 default: 1096 pHt = new SwHistorySetTxt( 1097 static_cast<SwTxtAttr*>(pHint), nNodeIdx ); 1098 } 1099 } 1100 else 1101 { 1102 pHt = new SwHistoryResetTxt( pHint->Which(), *pHint->GetStart(), 1103 *pHint->GetAnyEnd(), nNodeIdx ); 1104 } 1105 m_SwpHstry.Insert( pHt, Count() ); 1106 } 1107 1108 1109 void SwHistory::Add( SwFmtColl* pColl, sal_uLong nNodeIdx, sal_uInt8 nWhichNd ) 1110 { 1111 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1112 1113 SwHistoryHint * pHt = 1114 new SwHistoryChangeFmtColl( pColl, nNodeIdx, nWhichNd ); 1115 m_SwpHstry.Insert( pHt, Count() ); 1116 } 1117 1118 1119 void SwHistory::Add(const ::sw::mark::IMark& rBkmk, bool bSavePos, bool bSaveOtherPos) 1120 { 1121 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1122 1123 SwHistoryHint * pHt = new SwHistoryBookmark(rBkmk, bSavePos, bSaveOtherPos); 1124 m_SwpHstry.Insert( pHt, Count() ); 1125 } 1126 1127 1128 void SwHistory::Add( SwFrmFmt& rFmt ) 1129 { 1130 SwHistoryHint * pHt = new SwHistoryChangeFlyAnchor( rFmt ); 1131 m_SwpHstry.Insert( pHt, Count() ); 1132 } 1133 1134 void SwHistory::Add( SwFlyFrmFmt& rFmt, sal_uInt16& rSetPos ) 1135 { 1136 ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); 1137 1138 SwHistoryHint * pHint; 1139 const sal_uInt16 nWh = rFmt.Which(); 1140 if( RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh ) 1141 { 1142 pHint = new SwHistoryTxtFlyCnt( &rFmt ); 1143 m_SwpHstry.Insert( pHint, Count() ); 1144 1145 const SwFmtChain* pChainItem; 1146 if( SFX_ITEM_SET == rFmt.GetItemState( RES_CHAIN, sal_False, 1147 (const SfxPoolItem**)&pChainItem )) 1148 { 1149 if( pChainItem->GetNext() || pChainItem->GetPrev() ) 1150 { 1151 SwHistoryHint * pHt = 1152 new SwHistoryChangeFlyChain( rFmt, *pChainItem ); 1153 m_SwpHstry.Insert( pHt, rSetPos++ ); 1154 if ( pChainItem->GetNext() ) 1155 { 1156 SwFmtChain aTmp( pChainItem->GetNext()->GetChain() ); 1157 aTmp.SetPrev( 0 ); 1158 pChainItem->GetNext()->SetFmtAttr( aTmp ); 1159 } 1160 if ( pChainItem->GetPrev() ) 1161 { 1162 SwFmtChain aTmp( pChainItem->GetPrev()->GetChain() ); 1163 aTmp.SetNext( 0 ); 1164 pChainItem->GetPrev()->SetFmtAttr( aTmp ); 1165 } 1166 } 1167 rFmt.ResetFmtAttr( RES_CHAIN ); 1168 } 1169 } 1170 } 1171 1172 void SwHistory::Add( const SwTxtFtn& rFtn ) 1173 { 1174 SwHistoryHint *pHt = new SwHistorySetFootnote( rFtn ); 1175 m_SwpHstry.Insert( pHt, Count() ); 1176 } 1177 1178 // #i27615# 1179 void SwHistory::Add(const SfxItemSet & rSet, const SwCharFmt & rFmt) 1180 { 1181 SwHistoryHint * pHt = new SwHistoryChangeCharFmt(rSet, rFmt.GetName()); 1182 m_SwpHstry.Insert(pHt, Count()); 1183 } 1184 1185 /************************************************************************* 1186 |* 1187 |* sal_Bool SwHistory::Rollback() 1188 |* 1189 |* Beschreibung Dokument 1.0 1190 |* Ersterstellung JP 18.02.91 1191 |* Letzte Aenderung JP 18.02.91 1192 |* 1193 *************************************************************************/ 1194 1195 1196 bool SwHistory::Rollback( SwDoc* pDoc, sal_uInt16 nStart ) 1197 { 1198 if ( !Count() ) 1199 return false; 1200 1201 SwHistoryHint * pHHt; 1202 sal_uInt16 i; 1203 for ( i = Count(); i > nStart ; ) 1204 { 1205 pHHt = m_SwpHstry[ --i ]; 1206 pHHt->SetInDoc( pDoc, false ); 1207 delete pHHt; 1208 } 1209 m_SwpHstry.Remove( nStart, Count() - nStart ); 1210 m_nEndDiff = 0; 1211 return true; 1212 } 1213 1214 1215 1216 bool SwHistory::TmpRollback( SwDoc* pDoc, sal_uInt16 nStart, bool bToFirst ) 1217 { 1218 sal_uInt16 nEnd = Count() - m_nEndDiff; 1219 if ( !Count() || !nEnd || nStart >= nEnd ) 1220 return false; 1221 1222 SwHistoryHint * pHHt; 1223 if ( bToFirst ) 1224 { 1225 for ( ; nEnd > nStart; ++m_nEndDiff ) 1226 { 1227 pHHt = m_SwpHstry[ --nEnd ]; 1228 pHHt->SetInDoc( pDoc, true ); 1229 } 1230 } 1231 else 1232 { 1233 for ( ; nStart < nEnd; ++m_nEndDiff, ++nStart ) 1234 { 1235 pHHt = m_SwpHstry[ nStart ]; 1236 pHHt->SetInDoc( pDoc, true ); 1237 } 1238 } 1239 return true; 1240 } 1241 1242 1243 void SwHistory::Delete( sal_uInt16 nStart ) 1244 { 1245 for ( sal_uInt16 n = Count(); n > nStart; ) 1246 { 1247 m_SwpHstry.DeleteAndDestroy( --n, 1 ); 1248 } 1249 m_nEndDiff = 0; 1250 } 1251 1252 1253 sal_uInt16 SwHistory::SetTmpEnd( sal_uInt16 nNewTmpEnd ) 1254 { 1255 ASSERT( nNewTmpEnd <= Count(), "SwHistory::SetTmpEnd: out of bounds" ); 1256 1257 sal_uInt16 nOld = Count() - m_nEndDiff; 1258 m_nEndDiff = Count() - nNewTmpEnd; 1259 1260 // for every SwHistoryFlyCnt, call the Redo of its UndoObject. 1261 // this saves the formats of the flys! 1262 for ( sal_uInt16 n = nOld; n < nNewTmpEnd; n++ ) 1263 { 1264 if ( HSTRY_FLYCNT == (*this)[ n ]->Which() ) 1265 { 1266 static_cast<SwHistoryTxtFlyCnt*>((*this)[ n ]) 1267 ->GetUDelLFmt()->RedoForRollback(); 1268 } 1269 } 1270 1271 return nOld; 1272 } 1273 1274 void SwHistory::CopyFmtAttr( const SfxItemSet& rSet, sal_uLong nNodeIdx ) 1275 { 1276 if( rSet.Count() ) 1277 { 1278 SfxItemIter aIter( rSet ); 1279 do { 1280 if( (SfxPoolItem*)-1 != aIter.GetCurItem() ) 1281 { 1282 const SfxPoolItem* pNew = aIter.GetCurItem(); 1283 Add( pNew, pNew, nNodeIdx ); 1284 } 1285 if( aIter.IsAtEnd() ) 1286 break; 1287 aIter.NextItem(); 1288 } while( sal_True ); 1289 } 1290 } 1291 1292 void SwHistory::CopyAttr( SwpHints* pHts, sal_uLong nNodeIdx, 1293 xub_StrLen nStart, xub_StrLen nEnd, bool bFields ) 1294 { 1295 if( !pHts ) 1296 return; 1297 1298 // copy all attributes of the TextNode in the area from nStart to nEnd 1299 SwTxtAttr* pHt; 1300 xub_StrLen nAttrStt; 1301 const xub_StrLen * pEndIdx; 1302 for( sal_uInt16 n = 0; n < pHts->Count(); n++ ) 1303 { 1304 // BP: nAttrStt muss auch bei !pEndIdx gesetzt werden 1305 pHt = pHts->GetTextHint(n); 1306 nAttrStt = *pHt->GetStart(); 1307 // JP: ???? wieso nAttrStt >= nEnd 1308 // if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt >= nEnd ) 1309 if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt > nEnd ) 1310 break; 1311 1312 // Flys und Ftn nie kopieren !! 1313 sal_Bool bNextAttr = sal_False; 1314 switch( pHt->Which() ) 1315 { 1316 case RES_TXTATR_FIELD: 1317 // keine Felder, .. kopieren ?? 1318 if( !bFields ) 1319 bNextAttr = sal_True; 1320 break; 1321 case RES_TXTATR_FLYCNT: 1322 case RES_TXTATR_FTN: 1323 bNextAttr = sal_True; 1324 break; 1325 } 1326 1327 if( bNextAttr ) 1328 continue; 1329 1330 // save all attributes that are somehow in this area 1331 if ( nStart <= nAttrStt ) 1332 { 1333 if ( nEnd > nAttrStt 1334 // JP: ???? wieso nAttrStt >= nEnd 1335 // || (nEnd == nAttrStt && (!pEndIdx || nEnd == pEndIdx->GetIndex())) 1336 ) 1337 { 1338 Add( pHt, nNodeIdx, false ); 1339 } 1340 } 1341 else if ( pEndIdx && nStart < *pEndIdx ) 1342 { 1343 Add( pHt, nNodeIdx, false ); 1344 } 1345 } 1346 } 1347 1348 1349 /*************************************************************************/ 1350 1351 // Klasse zum Registrieren der History am Node, Format, HintsArray, ... 1352 1353 SwRegHistory::SwRegHistory( SwHistory* pHst ) 1354 : SwClient( 0 ) 1355 , m_pHistory( pHst ) 1356 , m_nNodeIndex( ULONG_MAX ) 1357 { 1358 _MakeSetWhichIds(); 1359 } 1360 1361 SwRegHistory::SwRegHistory( SwModify* pRegIn, const SwNode& rNd, 1362 SwHistory* pHst ) 1363 : SwClient( pRegIn ) 1364 , m_pHistory( pHst ) 1365 , m_nNodeIndex( rNd.GetIndex() ) 1366 { 1367 _MakeSetWhichIds(); 1368 } 1369 1370 SwRegHistory::SwRegHistory( const SwNode& rNd, SwHistory* pHst ) 1371 : SwClient( 0 ) 1372 , m_pHistory( pHst ) 1373 , m_nNodeIndex( rNd.GetIndex() ) 1374 { 1375 _MakeSetWhichIds(); 1376 } 1377 1378 void SwRegHistory::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 1379 { 1380 // --> OD 2010-10-05 #i114861# 1381 // Do not handle a "noop" modify 1382 // - e.g. <SwTxtNode::NumRuleChgd()> uses such a "noop" modify 1383 // if ( m_pHistory && ( pOld || pNew ) ) 1384 if ( m_pHistory && ( pOld || pNew ) && 1385 pOld != pNew ) 1386 // <-- 1387 { 1388 if ( pNew->Which() < POOLATTR_END ) 1389 { 1390 m_pHistory->Add( pOld, pNew, m_nNodeIndex ); 1391 } 1392 else if ( RES_ATTRSET_CHG == pNew->Which() ) 1393 { 1394 SwHistoryHint* pNewHstr; 1395 const SfxItemSet& rSet = 1396 *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet(); 1397 if ( 1 < rSet.Count() ) 1398 { 1399 pNewHstr = 1400 new SwHistorySetAttrSet( rSet, m_nNodeIndex, m_WhichIdSet ); 1401 } 1402 else 1403 { 1404 const SfxPoolItem* pItem = SfxItemIter( rSet ).FirstItem(); 1405 if ( m_WhichIdSet.Seek_Entry( pItem->Which() ) ) 1406 { 1407 pNewHstr = new SwHistorySetFmt( pItem, m_nNodeIndex ); 1408 } 1409 else 1410 { 1411 pNewHstr = new SwHistoryResetFmt( pItem, m_nNodeIndex ); 1412 } 1413 } 1414 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() ); 1415 } 1416 } 1417 } 1418 1419 1420 1421 void SwRegHistory::AddHint( SwTxtAttr* pHt, const bool bNew ) 1422 { 1423 m_pHistory->Add( pHt, m_nNodeIndex, bNew ); 1424 } 1425 1426 1427 bool SwRegHistory::InsertItems( const SfxItemSet& rSet, 1428 xub_StrLen const nStart, xub_StrLen const nEnd, SetAttrMode const nFlags ) 1429 { 1430 if( !rSet.Count() ) 1431 return false; 1432 1433 SwTxtNode * const pTxtNode = 1434 dynamic_cast<SwTxtNode *>(const_cast<SwModify *>(GetRegisteredIn())); 1435 1436 ASSERT(pTxtNode, "SwRegHistory not registered at text node?"); 1437 if (!pTxtNode) 1438 return false; 1439 1440 if ( pTxtNode->GetpSwpHints() && m_pHistory ) 1441 { 1442 pTxtNode->GetpSwpHints()->Register( this ); 1443 } 1444 1445 const bool bInserted = pTxtNode->SetAttr( rSet, nStart, nEnd, nFlags ); 1446 1447 // Achtung: Durch das Einfuegen eines Attributs kann das Array 1448 // geloescht werden!!! Wenn das einzufuegende zunaechst ein vorhandenes 1449 // loescht, selbst aber nicht eingefuegt werden braucht, weil die 1450 // Absatzattribute identisch sind( -> bForgetAttr in SwpHints::Insert ) 1451 if ( pTxtNode->GetpSwpHints() && m_pHistory ) 1452 { 1453 pTxtNode->GetpSwpHints()->DeRegister(); 1454 } 1455 1456 if ( m_pHistory && bInserted ) 1457 { 1458 SwHistoryHint* pNewHstr = new SwHistoryResetAttrSet( rSet, 1459 pTxtNode->GetIndex(), nStart, nEnd ); 1460 // der NodeIndex kann verschoben sein !! 1461 1462 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() ); 1463 } 1464 1465 return bInserted; 1466 } 1467 1468 void SwRegHistory::RegisterInModify( SwModify* pRegIn, const SwNode& rNd ) 1469 { 1470 if ( m_pHistory && pRegIn ) 1471 { 1472 pRegIn->Add( this ); 1473 m_nNodeIndex = rNd.GetIndex(); 1474 _MakeSetWhichIds(); 1475 } 1476 else if ( m_WhichIdSet.Count() ) 1477 { 1478 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() ); 1479 } 1480 } 1481 1482 void SwRegHistory::_MakeSetWhichIds() 1483 { 1484 if (!m_pHistory) return; 1485 1486 if ( m_WhichIdSet.Count() ) 1487 { 1488 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() ); 1489 } 1490 1491 if( GetRegisteredIn() ) 1492 { 1493 const SfxItemSet* pSet = 0; 1494 if( GetRegisteredIn()->ISA( SwCntntNode ) ) 1495 { 1496 pSet = static_cast<SwCntntNode*>( 1497 const_cast<SwModify*>(GetRegisteredIn()))->GetpSwAttrSet(); 1498 } 1499 else if ( GetRegisteredIn()->ISA( SwFmt ) ) 1500 { 1501 pSet = &static_cast<SwFmt*>( 1502 const_cast<SwModify*>(GetRegisteredIn()))->GetAttrSet(); 1503 } 1504 if( pSet && pSet->Count() ) 1505 { 1506 SfxItemIter aIter( *pSet ); 1507 sal_uInt16 nW = aIter.FirstItem()->Which(); 1508 while( sal_True ) 1509 { 1510 m_WhichIdSet.Insert( nW ); 1511 if( aIter.IsAtEnd() ) 1512 break; 1513 nW = aIter.NextItem()->Which(); 1514 } 1515 } 1516 } 1517 } 1518 1519