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