merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / undo / rolbck.cxx
blob44ac5f49c40ea782acd8cdb5d12a001584dbe01f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rolbck.cxx,v $
10 * $Revision: 1.24 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <svtools/itemiter.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 <docary.hxx>
54 #include <ndtxt.hxx> // SwTxtNode
55 #include <paratr.hxx> //
56 #include <cellatr.hxx> //
57 #include <fldbas.hxx> // fuer Felder
58 #include <pam.hxx> // fuer SwPaM
59 #include <swtable.hxx>
60 #include <rolbck.hxx>
61 #include <ndgrf.hxx> // SwGrfNode
62 #include <undobj.hxx> // fuer UndoDelete
63 #include <IMark.hxx> // fuer SwBookmark
64 #include <charfmt.hxx> // #i27615#
65 #ifndef _COMCORE_HRC
66 #include <comcore.hrc>
67 #endif
68 #include <tools/resid.hxx>
69 #ifndef _UNDO_HRC
70 #include <undo.hrc>
71 #endif
72 #include <svx/brkitem.hxx>
73 #include <bookmrk.hxx>
75 SV_IMPL_PTRARR( SwpHstry, SwHistoryHintPtr)
77 String SwHistoryHint::GetDescription() const
79 return String();
83 SwHistorySetFmt::SwHistorySetFmt( const SfxPoolItem* pFmtHt, ULONG nNd )
84 : SwHistoryHint( HSTRY_SETFMTHNT )
85 , m_pAttr( pFmtHt->Clone() )
86 , m_nNodeIndex( nNd )
88 switch ( m_pAttr->Which() )
90 case RES_PAGEDESC:
91 static_cast<SwFmtPageDesc&>(*m_pAttr).ChgDefinedIn( 0 );
92 break;
93 case RES_PARATR_DROP:
94 static_cast<SwFmtDrop&>(*m_pAttr).ChgDefinedIn( 0 );
95 break;
96 case RES_BOXATR_FORMULA:
98 //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern
99 SwTblBoxFormula& rNew = static_cast<SwTblBoxFormula&>(*m_pAttr);
100 if ( rNew.IsIntrnlName() )
102 const SwTblBoxFormula& rOld =
103 *static_cast<const SwTblBoxFormula*>(pFmtHt);
104 const SwNode* pNd = rOld.GetNodeOfFormula();
105 if ( pNd )
107 const SwTableNode* pTableNode = pNd->FindTableNode();
108 if (pTableNode)
110 SwTableFmlUpdate aMsgHnt( &pTableNode->GetTable() );
111 aMsgHnt.eFlags = TBL_BOXNAME;
112 rNew.ChgDefinedIn( rOld.GetDefinedIn() );
113 rNew.ChangeState( &aMsgHnt );
117 rNew.ChgDefinedIn( 0 );
119 break;
123 String SwHistorySetFmt::GetDescription() const
125 String aResult ;
127 USHORT nWhich = m_pAttr->Which();
128 switch (nWhich)
130 case RES_BREAK:
131 switch ((static_cast<SvxFmtBreakItem &>(*m_pAttr)).GetBreak())
133 case SVX_BREAK_PAGE_BEFORE:
134 case SVX_BREAK_PAGE_AFTER:
135 case SVX_BREAK_PAGE_BOTH:
136 aResult = SW_RES(STR_UNDO_PAGEBREAKS);
138 break;
139 case SVX_BREAK_COLUMN_BEFORE:
140 case SVX_BREAK_COLUMN_AFTER:
141 case SVX_BREAK_COLUMN_BOTH:
142 aResult = SW_RES(STR_UNDO_COLBRKS);
144 break;
145 default:
146 break;
148 break;
149 default:
150 break;
153 return aResult;
156 void SwHistorySetFmt::SetInDoc( SwDoc* pDoc, bool bTmpSet )
158 SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
159 if ( pNode->IsCntntNode() )
161 static_cast<SwCntntNode*>(pNode)->SetAttr( *m_pAttr );
163 else if ( pNode->IsTableNode() )
165 static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()->SetFmtAttr(
166 *m_pAttr );
168 else if ( pNode->IsStartNode() && (SwTableBoxStartNode ==
169 static_cast<SwStartNode*>(pNode)->GetStartNodeType()) )
171 SwTableNode* pTNd = pNode->FindTableNode();
172 if ( pTNd )
174 SwTableBox* pBox = pTNd->GetTable().GetTblBox( m_nNodeIndex );
175 if (pBox)
177 pBox->ClaimFrmFmt()->SetFmtAttr( *m_pAttr );
182 if ( !bTmpSet )
184 m_pAttr.reset();
188 SwHistorySetFmt::~SwHistorySetFmt()
193 // --> OD 2008-02-27 #refactorlists# - removed <rDoc>
194 SwHistoryResetFmt::SwHistoryResetFmt(const SfxPoolItem* pFmtHt, ULONG nNodeIdx)
195 // <--
196 : SwHistoryHint( HSTRY_RESETFMTHNT )
197 , m_nNodeIndex( nNodeIdx )
198 , m_nWhich( pFmtHt->Which() )
203 void SwHistoryResetFmt::SetInDoc( SwDoc* pDoc, bool )
205 SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
206 if ( pNode->IsCntntNode() )
208 static_cast<SwCntntNode*>(pNode)->ResetAttr( m_nWhich );
210 else if ( pNode->IsTableNode() )
212 static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()->
213 ResetFmtAttr( m_nWhich );
218 SwHistorySetTxt::SwHistorySetTxt( SwTxtAttr* pTxtHt, ULONG nNodePos )
219 : SwHistoryHint( HSTRY_SETTXTHNT )
220 , m_nNodeIndex( nNodePos )
221 , m_nStart( *pTxtHt->GetStart() )
222 , m_nEnd( *pTxtHt->GetAnyEnd() )
224 // !! Achtung: folgende Attribute erzeugen keine FormatAttribute:
225 // - NoLineBreak, NoHypen, Inserted, Deleted
226 // Dafuer muessen Sonderbehandlungen gemacht werden !!!
228 // ein bisschen kompliziert, aber ist Ok so: erst vom default
229 // eine Kopie und dann die Werte aus dem Text Attribut zuweisen
230 USHORT nWhich = pTxtHt->Which();
231 if ( RES_TXTATR_CHARFMT == nWhich )
233 m_pAttr.reset( new SwFmtCharFmt( pTxtHt->GetCharFmt().GetCharFmt() ) );
235 else
237 m_pAttr.reset( pTxtHt->GetAttr().Clone() );
242 SwHistorySetTxt::~SwHistorySetTxt()
247 void SwHistorySetTxt::SetInDoc( SwDoc* pDoc, bool )
249 if ( !m_pAttr.get() )
250 return;
252 if ( RES_TXTATR_CHARFMT == m_pAttr->Which() )
254 // ask the Doc if the CharFmt still exists
255 if ( USHRT_MAX == pDoc->GetCharFmts()->GetPos(
256 (static_cast<SwFmtCharFmt&>(*m_pAttr)).GetCharFmt() ) )
257 return; // do not set, format does not exist
260 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
261 ASSERT( pTxtNd, "SwHistorySetTxt::SetInDoc: not a TextNode" );
263 if ( pTxtNd )
265 pTxtNd->InsertItem( *m_pAttr, m_nStart, m_nEnd,
266 nsSetAttrMode::SETATTR_NOTXTATRCHR |
267 nsSetAttrMode::SETATTR_NOHINTADJUST );
272 SwHistorySetTxtFld::SwHistorySetTxtFld( SwTxtFld* pTxtFld, ULONG nNodePos )
273 : SwHistoryHint( HSTRY_SETTXTFLDHNT )
274 , m_pFldType( 0 )
275 , m_pFld( new SwFmtFld( *pTxtFld->GetFld().GetFld() ) )
277 // only copy if not Sys-FieldType
278 SwDoc* pDoc = pTxtFld->GetTxtNode().GetDoc();
280 m_nFldWhich = m_pFld->GetFld()->GetTyp()->Which();
281 if (m_nFldWhich == RES_DBFLD ||
282 m_nFldWhich == RES_USERFLD ||
283 m_nFldWhich == RES_SETEXPFLD ||
284 m_nFldWhich == RES_DDEFLD ||
285 !pDoc->GetSysFldType( m_nFldWhich ))
287 m_pFldType.reset( m_pFld->GetFld()->GetTyp()->Copy() );
288 m_pFld->GetFld()->ChgTyp( m_pFldType.get() ); // change field type
290 m_nNodeIndex = nNodePos;
291 m_nPos = *pTxtFld->GetStart();
294 String SwHistorySetTxtFld::GetDescription() const
296 return m_pFld->GetFld()->GetDescription();;
299 SwHistorySetTxtFld::~SwHistorySetTxtFld()
304 void SwHistorySetTxtFld::SetInDoc( SwDoc* pDoc, bool )
306 if ( !m_pFld.get() )
307 return;
309 SwFieldType* pNewFldType = m_pFldType.get();
310 if ( !pNewFldType )
312 pNewFldType = pDoc->GetSysFldType( m_nFldWhich );
314 else
316 // register type with the document
317 pNewFldType = pDoc->InsertFldType( *m_pFldType );
320 m_pFld->GetFld()->ChgTyp( pNewFldType ); // change field type
322 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
323 ASSERT( pTxtNd, "SwHistorySetTxtFld: no TextNode" );
325 if ( pTxtNd )
327 pTxtNd->InsertItem( *m_pFld, m_nPos, m_nPos,
328 nsSetAttrMode::SETATTR_NOTXTATRCHR );
334 SwHistorySetRefMark::SwHistorySetRefMark( SwTxtRefMark* pTxtHt, ULONG nNodePos )
335 : SwHistoryHint( HSTRY_SETREFMARKHNT )
336 , m_RefName( pTxtHt->GetRefMark().GetRefName() )
337 , m_nNodeIndex( nNodePos )
338 , m_nStart( *pTxtHt->GetStart() )
339 , m_nEnd( *pTxtHt->GetAnyEnd() )
344 void SwHistorySetRefMark::SetInDoc( SwDoc* pDoc, bool )
346 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
347 ASSERT( pTxtNd, "SwHistorySetRefMark: no TextNode" );
348 if ( !pTxtNd )
349 return;
351 SwFmtRefMark aRefMark( m_RefName );
353 // if a reference mark without an end already exists here: must not insert!
354 if ( m_nStart != m_nEnd ||
355 !pTxtNd->GetTxtAttrForCharAt( m_nStart, RES_TXTATR_REFMARK ) )
357 pTxtNd->InsertItem( aRefMark, m_nStart, m_nEnd,
358 nsSetAttrMode::SETATTR_NOTXTATRCHR );
363 SwHistorySetTOXMark::SwHistorySetTOXMark( SwTxtTOXMark* pTxtHt, ULONG nNodePos )
364 : SwHistoryHint( HSTRY_SETTOXMARKHNT )
365 , m_TOXMark( pTxtHt->GetTOXMark() )
366 , m_TOXName( m_TOXMark.GetTOXType()->GetTypeName() )
367 , m_eTOXTypes( m_TOXMark.GetTOXType()->GetType() )
368 , m_nNodeIndex( nNodePos )
369 , m_nStart( *pTxtHt->GetStart() )
370 , m_nEnd( *pTxtHt->GetAnyEnd() )
372 const_cast<SwModify*>(m_TOXMark.GetRegisteredIn())->Remove( &m_TOXMark );
376 void SwHistorySetTOXMark::SetInDoc( SwDoc* pDoc, bool )
378 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
379 ASSERT( pTxtNd, "SwHistorySetTOXMark: no TextNode" );
380 if ( !pTxtNd )
381 return;
383 // search for respective TOX type
384 USHORT nCnt = pDoc->GetTOXTypeCount( m_eTOXTypes );
385 SwTOXType* pToxType = 0;
386 for ( USHORT n = 0; n < nCnt; ++n )
388 pToxType = const_cast<SwTOXType*>(pDoc->GetTOXType( m_eTOXTypes, n ));
389 if ( pToxType->GetTypeName() == m_TOXName )
390 break;
391 pToxType = 0;
394 if ( !pToxType ) // TOX type not found, create new
396 pToxType = const_cast<SwTOXType*>(
397 pDoc->InsertTOXType( SwTOXType( m_eTOXTypes, m_TOXName )));
400 SwTOXMark aNew( m_TOXMark );
401 pToxType->Add( &aNew );
403 pTxtNd->InsertItem( aNew, m_nStart, m_nEnd,
404 nsSetAttrMode::SETATTR_NOTXTATRCHR );
408 int SwHistorySetTOXMark::IsEqual( const SwTOXMark& rCmp ) const
410 return m_TOXName == rCmp.GetTOXType()->GetTypeName() &&
411 m_eTOXTypes == rCmp.GetTOXType()->GetType() &&
412 m_TOXMark.GetAlternativeText() == rCmp.GetAlternativeText() &&
413 ( (TOX_INDEX == m_eTOXTypes)
414 ? ( m_TOXMark.GetPrimaryKey() == rCmp.GetPrimaryKey() &&
415 m_TOXMark.GetSecondaryKey() == rCmp.GetSecondaryKey() )
416 : m_TOXMark.GetLevel() == rCmp.GetLevel()
421 SwHistoryResetTxt::SwHistoryResetTxt( USHORT nWhich,
422 xub_StrLen nAttrStart, xub_StrLen nAttrEnd, ULONG nNodePos )
423 : SwHistoryHint( HSTRY_RESETTXTHNT )
424 , m_nNodeIndex( nNodePos ), m_nStart( nAttrStart ), m_nEnd( nAttrEnd )
425 , m_nAttr( nWhich )
430 void SwHistoryResetTxt::SetInDoc( SwDoc* pDoc, bool )
432 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
433 ASSERT( pTxtNd, "SwHistoryResetTxt: no TextNode" );
434 if ( pTxtNd )
436 pTxtNd->DeleteAttributes( m_nAttr, m_nStart, m_nEnd );
441 SwHistorySetFootnote::SwHistorySetFootnote( SwTxtFtn* pTxtFtn, ULONG nNodePos )
442 : SwHistoryHint( HSTRY_SETFTNHNT )
443 , m_pUndo( new SwUndoSaveSection )
444 , m_FootnoteNumber( pTxtFtn->GetFtn().GetNumStr() )
445 , m_nNodeIndex( nNodePos )
446 , m_nStart( *pTxtFtn->GetStart() )
447 , m_bEndNote( pTxtFtn->GetFtn().IsEndNote() )
449 ASSERT( pTxtFtn->GetStartNode(),
450 "SwHistorySetFootnote: Footnote without Section" );
452 // merke die alte NodePos, denn wer weiss was alles in der SaveSection
453 // gespeichert (geloescht) wird
454 SwDoc* pDoc = const_cast<SwDoc*>(pTxtFtn->GetTxtNode().GetDoc());
455 SwNode* pSaveNd = pDoc->GetNodes()[ m_nNodeIndex ];
457 //Pointer auf StartNode der FtnSection merken und erstmal den Pointer im
458 //Attribut zuruecksetzen -> Damit werden automatisch die Frms vernichtet.
459 SwNodeIndex aSttIdx( *pTxtFtn->GetStartNode() );
460 pTxtFtn->SetStartNode( 0, FALSE );
462 m_pUndo->SaveSection( pDoc, aSttIdx );
463 m_nNodeIndex = pSaveNd->GetIndex();
466 SwHistorySetFootnote::SwHistorySetFootnote( const SwTxtFtn &rTxtFtn )
467 : SwHistoryHint( HSTRY_SETFTNHNT )
468 , m_pUndo( 0 )
469 , m_FootnoteNumber( rTxtFtn.GetFtn().GetNumStr() )
470 , m_nNodeIndex( _SwTxtFtn_GetIndex( (&rTxtFtn) ) )
471 , m_nStart( *rTxtFtn.GetStart() )
472 , m_bEndNote( rTxtFtn.GetFtn().IsEndNote() )
474 ASSERT( rTxtFtn.GetStartNode(),
475 "SwHistorySetFootnote: Footnote without Section" );
478 String SwHistorySetFootnote::GetDescription() const
480 return SW_RES(STR_FOOTNOTE);
483 SwHistorySetFootnote::~SwHistorySetFootnote()
488 void SwHistorySetFootnote::SetInDoc( SwDoc* pDoc, bool )
490 SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
491 ASSERT( pTxtNd, "SwHistorySetFootnote: no TextNode" );
492 if ( !pTxtNd )
493 return;
495 if ( m_pUndo.get() )
497 // set the footnote in the TextNode
498 SwFmtFtn aTemp( m_bEndNote );
499 SwFmtFtn& rNew = const_cast<SwFmtFtn&>(
500 static_cast<const SwFmtFtn&>(pDoc->GetAttrPool().Put(aTemp)) );
501 if ( m_FootnoteNumber.Len() )
503 rNew.SetNumStr( m_FootnoteNumber );
505 SwTxtFtn* pTxtFtn = new SwTxtFtn( rNew, m_nStart );
507 // create the section of the Footnote
508 SwNodeIndex aIdx( *pTxtNd );
509 m_pUndo->RestoreSection( pDoc, &aIdx, SwFootnoteStartNode );
510 pTxtFtn->SetStartNode( &aIdx );
511 if ( m_pUndo->GetHistory() )
513 // create frames only now
514 m_pUndo->GetHistory()->Rollback( pDoc );
517 pTxtNd->InsertHint( pTxtFtn );
519 else
521 SwTxtFtn * const pFtn =
522 const_cast<SwTxtFtn*>( static_cast<const SwTxtFtn*>(
523 pTxtNd->GetTxtAttrForCharAt( m_nStart )));
524 SwFmtFtn &rFtn = const_cast<SwFmtFtn&>(pFtn->GetFtn());
525 rFtn.SetNumStr( m_FootnoteNumber );
526 if ( rFtn.IsEndNote() != m_bEndNote )
528 rFtn.SetEndNote( m_bEndNote );
529 pFtn->CheckCondColl();
535 SwHistoryChangeFmtColl::SwHistoryChangeFmtColl( SwFmtColl* pFmtColl, ULONG nNd,
536 BYTE nNodeWhich )
537 : SwHistoryHint( HSTRY_CHGFMTCOLL )
538 , m_pColl( pFmtColl )
539 , m_nNodeIndex( nNd )
540 , m_nNodeType( nNodeWhich )
544 void SwHistoryChangeFmtColl::SetInDoc( SwDoc* pDoc, bool )
546 SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode();
547 ASSERT( pCntntNd, "SwHistoryChangeFmtColl: no ContentNode" );
549 // before setting the format, check if it is still available in the
550 // document. if it has been deleted, there is no undo!
551 if ( pCntntNd && m_nNodeType == pCntntNd->GetNodeType() )
553 if ( ND_TEXTNODE == m_nNodeType )
555 if ( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos(
556 static_cast<SwTxtFmtColl * const>(m_pColl) ))
558 pCntntNd->ChgFmtColl( m_pColl );
561 else if ( USHRT_MAX != pDoc->GetGrfFmtColls()->GetPos(
562 static_cast<SwGrfFmtColl * const>(m_pColl) ))
564 pCntntNd->ChgFmtColl( m_pColl );
570 SwHistoryTxtFlyCnt::SwHistoryTxtFlyCnt( SwFrmFmt* const pFlyFmt )
571 : SwHistoryHint( HSTRY_FLYCNT )
572 , m_pUndo( new SwUndoDelLayFmt( pFlyFmt ) )
574 ASSERT( pFlyFmt, "SwHistoryTxtFlyCnt: no Format" );
575 m_pUndo->ChgShowSel( FALSE );
579 SwHistoryTxtFlyCnt::~SwHistoryTxtFlyCnt()
584 void SwHistoryTxtFlyCnt::SetInDoc( SwDoc* pDoc, bool )
586 SwPaM aPam( pDoc->GetNodes().GetEndOfPostIts() );
587 SwUndoIter aUndoIter( &aPam );
588 m_pUndo->Undo( aUndoIter );
593 SwHistoryBookmark::SwHistoryBookmark(
594 const ::sw::mark::IMark& rBkmk,
595 bool bSavePos,
596 bool bSaveOtherPos)
597 : SwHistoryHint(HSTRY_BOOKMARK)
598 , m_aName(rBkmk.GetName())
599 , m_aShortName()
600 , m_aKeycode()
601 , m_nNode(bSavePos ?
602 rBkmk.GetMarkPos().nNode.GetIndex() : 0)
603 , m_nOtherNode(bSaveOtherPos ?
604 rBkmk.GetOtherMarkPos().nNode.GetIndex() : 0)
605 , m_nCntnt(bSavePos ?
606 rBkmk.GetMarkPos().nContent.GetIndex() : 0)
607 , m_nOtherCntnt(bSaveOtherPos ?
608 rBkmk.GetOtherMarkPos().nContent.GetIndex() :0)
609 , m_bSavePos(bSavePos)
610 , m_bSaveOtherPos(bSaveOtherPos)
611 , m_bHadOtherPos(rBkmk.IsExpanded())
612 , m_eBkmkType(IDocumentMarkAccess::GetType(rBkmk))
614 const ::sw::mark::IBookmark* const pBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(&rBkmk);
615 if(pBookmark)
617 m_aKeycode = pBookmark->GetKeyCode();
618 m_aShortName = pBookmark->GetShortName();
620 ::sfx2::Metadatable * const pMetadatable(
621 const_cast< ::sfx2::Metadatable * >( // CreateUndo should be const?
622 dynamic_cast< ::sfx2::Metadatable const* >(pBookmark)));
623 if (pMetadatable)
625 m_pMetadataUndo = pMetadatable->CreateUndo();
631 void SwHistoryBookmark::SetInDoc( SwDoc* pDoc, bool )
633 bool bDoesUndo = pDoc->DoesUndo();
634 pDoc->DoUndo(false);
636 SwNodes& rNds = pDoc->GetNodes();
637 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
638 ::std::auto_ptr<SwPaM> pPam;
639 ::sw::mark::IMark* pMark = NULL;
641 if(m_bSavePos)
643 SwCntntNode* const pCntntNd = rNds[m_nNode]->GetCntntNode();
644 OSL_ENSURE(pCntntNd,
645 "<SwHistoryBookmark::SetInDoc(..)>"
646 " - wrong node for a mark");
648 // #111660# don't crash when nNode1 doesn't point to content node.
649 if(pCntntNd)
650 pPam = ::std::auto_ptr<SwPaM>(new SwPaM(*pCntntNd, m_nCntnt));
652 else
654 pMark = pMarkAccess->findMark(m_aName)->get();
655 pPam = ::std::auto_ptr<SwPaM>(new SwPaM(pMark->GetMarkPos()));
658 if(m_bSaveOtherPos)
660 SwCntntNode* const pCntntNd = rNds[m_nOtherNode]->GetCntntNode();
661 OSL_ENSURE(pCntntNd,
662 "<SwHistoryBookmark::SetInDoc(..)>"
663 " - wrong node for a mark");
665 if(pPam.get() != NULL && pCntntNd)
667 pPam->SetMark();
668 pPam->GetMark()->nNode = m_nOtherNode;
669 pPam->GetMark()->nContent.Assign(pCntntNd, m_nOtherCntnt);
672 else if(m_bHadOtherPos)
674 if(!pMark)
675 pMark = pMarkAccess->findMark(m_aName)->get();
676 OSL_ENSURE(pMark->IsExpanded(),
677 "<SwHistoryBookmark::SetInDoc(..)>"
678 " - missing pos on old mark");
679 pPam->SetMark();
680 *pPam->GetMark() = pMark->GetOtherMarkPos();
683 if(pPam.get())
685 if(pMark)
686 pMarkAccess->deleteMark(pMark);
687 ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(
688 pMarkAccess->makeMark(*pPam, m_aName, m_eBkmkType));
689 if(pBookmark)
691 pBookmark->SetKeyCode(m_aKeycode);
692 pBookmark->SetShortName(m_aShortName);
693 if (m_pMetadataUndo)
695 ::sfx2::Metadatable * const pMeta(
696 dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
697 OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
698 if (pMeta)
700 pMeta->RestoreMetadata(m_pMetadataUndo);
705 pDoc->DoUndo(bDoesUndo);
709 bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark& rBkmk)
711 return m_nNode == rBkmk.GetMarkPos().nNode.GetIndex()
712 && m_nCntnt == rBkmk.GetMarkPos().nContent.GetIndex()
713 && m_aName == rBkmk.GetName();
716 const ::rtl::OUString& SwHistoryBookmark::GetName() const
718 return m_aName;
721 /*************************************************************************/
724 SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet& rSet,
725 ULONG nNodePos, const SvUShortsSort& rSetArr )
726 : SwHistoryHint( HSTRY_SETATTRSET )
727 , m_OldSet( rSet )
728 , m_ResetArray( 0, 4 )
729 , m_nNodeIndex( nNodePos )
731 SfxItemIter aIter( m_OldSet ), aOrigIter( rSet );
732 const SfxPoolItem* pItem = aIter.FirstItem(),
733 * pOrigItem = aOrigIter.FirstItem();
734 do {
735 if( !rSetArr.Seek_Entry( pOrigItem->Which() ))
737 m_ResetArray.Insert( pOrigItem->Which(), m_ResetArray.Count() );
738 m_OldSet.ClearItem( pOrigItem->Which() );
740 else
742 switch ( pItem->Which() )
744 case RES_PAGEDESC:
745 static_cast<SwFmtPageDesc*>(
746 const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 );
747 break;
749 case RES_PARATR_DROP:
750 static_cast<SwFmtDrop*>(
751 const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 );
752 break;
754 case RES_BOXATR_FORMULA:
756 //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den
757 // Value mit sichern. Der muss gegebenfalls neu
758 // errechnet werden!
759 //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern
760 m_OldSet.ClearItem( RES_BOXATR_VALUE );
762 SwTblBoxFormula& rNew =
763 *static_cast<SwTblBoxFormula*>(
764 const_cast<SfxPoolItem*>(pItem));
765 if ( rNew.IsIntrnlName() )
767 const SwTblBoxFormula& rOld =
768 static_cast<const SwTblBoxFormula&>(
769 rSet.Get( RES_BOXATR_FORMULA ));
770 const SwNode* pNd = rOld.GetNodeOfFormula();
771 if ( pNd )
773 const SwTableNode* pTableNode
774 = pNd->FindTableNode();
775 if (pTableNode)
777 SwTableFmlUpdate aMsgHnt(
778 &pTableNode->GetTable() );
779 aMsgHnt.eFlags = TBL_BOXNAME;
780 rNew.ChgDefinedIn( rOld.GetDefinedIn() );
781 rNew.ChangeState( &aMsgHnt );
785 rNew.ChgDefinedIn( 0 );
787 break;
791 if( aIter.IsAtEnd() )
792 break;
793 pItem = aIter.NextItem();
794 pOrigItem = aOrigIter.NextItem();
795 } while( TRUE );
798 void SwHistorySetAttrSet::SetInDoc( SwDoc* pDoc, bool )
800 BOOL bDoesUndo = pDoc->DoesUndo();
801 pDoc->DoUndo( FALSE );
803 SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
804 if ( pNode->IsCntntNode() )
806 static_cast<SwCntntNode*>(pNode)->SetAttr( m_OldSet );
807 if ( m_ResetArray.Count() )
809 static_cast<SwCntntNode*>(pNode)->ResetAttr( m_ResetArray );
812 else if ( pNode->IsTableNode() )
814 SwFmt& rFmt =
815 *static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt();
816 rFmt.SetFmtAttr( m_OldSet );
817 if ( m_ResetArray.Count() )
819 rFmt.ResetFmtAttr( *m_ResetArray.GetData() );
823 pDoc->DoUndo( bDoesUndo );
826 /*************************************************************************/
829 SwHistoryResetAttrSet::SwHistoryResetAttrSet( const SfxItemSet& rSet,
830 ULONG nNodePos, xub_StrLen nAttrStt, xub_StrLen nAttrEnd )
831 : SwHistoryHint( HSTRY_RESETATTRSET )
832 , m_nNodeIndex( nNodePos ), m_nStart( nAttrStt ), m_nEnd( nAttrEnd )
833 , m_Array( (BYTE)rSet.Count() )
835 SfxItemIter aIter( rSet );
836 bool bAutoStyle = true;
838 while( TRUE )
840 const USHORT nWhich = aIter.GetCurItem()->Which();
842 #ifndef PRODUCT
843 switch (nWhich)
845 case RES_TXTATR_REFMARK:
846 case RES_TXTATR_TOXMARK:
847 if (m_nStart != m_nEnd) break; // else: fall through!
848 case RES_TXTATR_FIELD:
849 case RES_TXTATR_FLYCNT:
850 case RES_TXTATR_FTN:
851 case RES_TXTATR_META:
852 case RES_TXTATR_METAFIELD:
853 ASSERT(rSet.Count() == 1,
854 "text attribute with CH_TXTATR, but not the only one:"
855 "\nnot such a good idea");
856 break;
858 #endif
860 // Character attribute cannot be inserted into the hints array
861 // anymore. Therefore we have to treat them as one RES_TXTATR_AUTOFMT:
862 if (isCHRATR(nWhich))
864 bAutoStyle = true;
866 else
868 m_Array.Insert( aIter.GetCurItem()->Which(), m_Array.Count() );
871 if( aIter.IsAtEnd() )
872 break;
874 aIter.NextItem();
877 if ( bAutoStyle )
879 m_Array.Insert( RES_TXTATR_AUTOFMT, m_Array.Count() );
884 void SwHistoryResetAttrSet::SetInDoc( SwDoc* pDoc, bool )
886 BOOL bDoesUndo = pDoc->DoesUndo();
887 pDoc->DoUndo( FALSE );
889 SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode();
890 ASSERT( pCntntNd, "SwHistoryResetAttrSet: no CntntNode" );
892 if (pCntntNd)
894 const USHORT* pArr = m_Array.GetData();
895 if ( USHRT_MAX == m_nEnd && USHRT_MAX == m_nStart )
897 // no area: use ContentNode
898 for ( USHORT n = m_Array.Count(); n; --n, ++pArr )
900 pCntntNd->ResetAttr( *pArr );
903 else
905 // area: use TextNode
906 for ( USHORT n = m_Array.Count(); n; --n, ++pArr )
908 static_cast<SwTxtNode*>(pCntntNd)->
909 DeleteAttributes( *pArr, m_nStart, m_nEnd );
914 pDoc->DoUndo( bDoesUndo );
918 /*************************************************************************/
921 SwHistoryChangeFlyAnchor::SwHistoryChangeFlyAnchor( SwFrmFmt& rFmt )
922 : SwHistoryHint( HSTRY_CHGFLYANCHOR )
923 , m_rFmt( rFmt )
924 , m_nOldNodeIndex( rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex() )
925 , m_nOldContentIndex( ( FLY_AUTO_CNTNT == rFmt.GetAnchor().GetAnchorId() )
926 ? rFmt.GetAnchor().GetCntntAnchor()->nContent.GetIndex()
927 : STRING_MAXLEN )
932 void SwHistoryChangeFlyAnchor::SetInDoc( SwDoc* pDoc, bool )
934 BOOL bDoesUndo = pDoc->DoesUndo();
935 pDoc->DoUndo( FALSE );
937 USHORT nPos = pDoc->GetSpzFrmFmts()->GetPos( &m_rFmt );
938 if ( USHRT_MAX != nPos ) // Format does still exist
940 SwFmtAnchor aTmp( m_rFmt.GetAnchor() );
942 SwNode* pNd = pDoc->GetNodes()[ m_nOldNodeIndex ];
943 SwCntntNode* pCNd = pNd->GetCntntNode();
944 SwPosition aPos( *pNd );
945 if ( STRING_MAXLEN != m_nOldContentIndex )
947 ASSERT(pCNd, "SwHistoryChangeFlyAnchor: no ContentNode");
948 if (pCNd)
950 aPos.nContent.Assign( pCNd, m_nOldContentIndex );
953 aTmp.SetAnchor( &aPos );
955 // so the Layout does not get confused
956 if ( !pCNd || !pCNd->GetFrm( 0, 0, FALSE ) )
958 m_rFmt.DelFrms();
961 m_rFmt.SetFmtAttr( aTmp );
963 pDoc->DoUndo( bDoesUndo );
967 /*************************************************************************/
969 SwHistoryChangeFlyChain::SwHistoryChangeFlyChain( SwFlyFrmFmt& rFmt,
970 const SwFmtChain& rAttr )
971 : SwHistoryHint( HSTRY_CHGFLYCHAIN )
972 , m_pPrevFmt( rAttr.GetPrev() )
973 , m_pNextFmt( rAttr.GetNext() )
974 , m_pFlyFmt( &rFmt )
979 void SwHistoryChangeFlyChain::SetInDoc( SwDoc* pDoc, bool )
981 if ( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pFlyFmt ) )
983 SwFmtChain aChain;
985 if ( m_pPrevFmt &&
986 USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pPrevFmt ) )
988 aChain.SetPrev( m_pPrevFmt );
989 SwFmtChain aTmp( m_pPrevFmt->GetChain() );
990 aTmp.SetNext( m_pFlyFmt );
991 m_pPrevFmt->SetFmtAttr( aTmp );
994 if ( m_pNextFmt &&
995 USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pNextFmt ) )
997 aChain.SetNext( m_pNextFmt );
998 SwFmtChain aTmp( m_pNextFmt->GetChain() );
999 aTmp.SetPrev( m_pFlyFmt );
1000 m_pNextFmt->SetFmtAttr( aTmp );
1003 if ( aChain.GetNext() || aChain.GetPrev() )
1005 m_pFlyFmt->SetFmtAttr( aChain );
1011 // -> #i27615#
1012 SwHistoryChangeCharFmt::SwHistoryChangeCharFmt(const SfxItemSet & rSet,
1013 const String & sFmt)
1014 : SwHistoryHint(HSTRY_CHGCHARFMT)
1015 , m_OldSet(rSet), m_Fmt(sFmt)
1019 void SwHistoryChangeCharFmt::SetInDoc(SwDoc * pDoc, bool )
1021 SwCharFmt * pCharFmt = pDoc->FindCharFmtByName(m_Fmt);
1023 if (pCharFmt)
1025 pCharFmt->SetFmtAttr(m_OldSet);
1028 // <- #i27615#
1030 /* \f */
1033 SwHistory::SwHistory( USHORT nInitSz, USHORT nGrowSz )
1034 : m_SwpHstry( (BYTE)nInitSz, (BYTE)nGrowSz )
1035 , m_nEndDiff( 0 )
1039 SwHistory::~SwHistory()
1041 Delete( 0 );
1045 /*************************************************************************
1047 |* void SwHistory::Add()
1049 |* Beschreibung Dokument 1.0
1050 |* Ersterstellung JP 18.02.91
1051 |* Letzte Aenderung JP 18.02.91
1053 *************************************************************************/
1055 // --> OD 2008-02-27 #refactorlists# - removed <rDoc>
1056 void SwHistory::Add( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue,
1057 ULONG nNodeIdx )
1058 // <--
1060 ASSERT( !m_nEndDiff, "History was not deleted after REDO" );
1062 USHORT nWhich = pNewValue->Which();
1063 if( (nWhich >= POOLATTR_END) || (nWhich == RES_TXTATR_FIELD) )
1064 return;
1066 // no default Attribute?
1067 SwHistoryHint * pHt;
1068 if ( pOldValue && pOldValue != GetDfltAttr( pOldValue->Which() ) )
1070 pHt = new SwHistorySetFmt( pOldValue, nNodeIdx );
1072 else
1074 pHt = new SwHistoryResetFmt( pNewValue, nNodeIdx );
1076 m_SwpHstry.Insert( pHt, Count() );
1080 void SwHistory::Add( SwTxtAttr* pHint, ULONG nNodeIdx, bool bNewAttr )
1082 ASSERT( !m_nEndDiff, "History was not deleted after REDO" );
1084 SwHistoryHint * pHt;
1085 USHORT nAttrWhich = pHint->Which();
1087 if( !bNewAttr )
1089 switch ( nAttrWhich )
1091 case RES_TXTATR_FTN:
1092 pHt = new SwHistorySetFootnote(
1093 static_cast<SwTxtFtn*>(pHint), nNodeIdx );
1094 break;
1095 case RES_TXTATR_FLYCNT:
1096 pHt = new SwHistoryTxtFlyCnt( static_cast<SwTxtFlyCnt*>(pHint)
1097 ->GetFlyCnt().GetFrmFmt() );
1098 break;
1099 case RES_TXTATR_FIELD:
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 );
1116 else
1118 pHt = new SwHistoryResetTxt( pHint->Which(), *pHint->GetStart(),
1119 *pHint->GetAnyEnd(), nNodeIdx );
1121 m_SwpHstry.Insert( pHt, Count() );
1125 void SwHistory::Add( SwFmtColl* pColl, ULONG nNodeIdx, BYTE nWhichNd )
1127 ASSERT( !m_nEndDiff, "History was not deleted after REDO" );
1129 SwHistoryHint * pHt =
1130 new SwHistoryChangeFmtColl( pColl, nNodeIdx, nWhichNd );
1131 m_SwpHstry.Insert( pHt, Count() );
1135 void SwHistory::Add(const ::sw::mark::IMark& rBkmk, bool bSavePos, bool bSaveOtherPos)
1137 ASSERT( !m_nEndDiff, "History was not deleted after REDO" );
1139 SwHistoryHint * pHt = new SwHistoryBookmark(rBkmk, bSavePos, bSaveOtherPos);
1140 m_SwpHstry.Insert( pHt, Count() );
1144 void SwHistory::Add( SwFrmFmt& rFmt )
1146 SwHistoryHint * pHt = new SwHistoryChangeFlyAnchor( rFmt );
1147 m_SwpHstry.Insert( pHt, Count() );
1150 void SwHistory::Add( SwFlyFrmFmt& rFmt, USHORT& rSetPos )
1152 ASSERT( !m_nEndDiff, "History was not deleted after REDO" );
1154 SwHistoryHint * pHint;
1155 const USHORT nWh = rFmt.Which();
1156 if( RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh )
1158 pHint = new SwHistoryTxtFlyCnt( &rFmt );
1159 m_SwpHstry.Insert( pHint, Count() );
1161 const SwFmtChain* pChainItem;
1162 if( SFX_ITEM_SET == rFmt.GetItemState( RES_CHAIN, FALSE,
1163 (const SfxPoolItem**)&pChainItem ))
1165 if( pChainItem->GetNext() || pChainItem->GetPrev() )
1167 SwHistoryHint * pHt =
1168 new SwHistoryChangeFlyChain( rFmt, *pChainItem );
1169 m_SwpHstry.Insert( pHt, rSetPos++ );
1170 if ( pChainItem->GetNext() )
1172 SwFmtChain aTmp( pChainItem->GetNext()->GetChain() );
1173 aTmp.SetPrev( 0 );
1174 pChainItem->GetNext()->SetFmtAttr( aTmp );
1176 if ( pChainItem->GetPrev() )
1178 SwFmtChain aTmp( pChainItem->GetPrev()->GetChain() );
1179 aTmp.SetNext( 0 );
1180 pChainItem->GetPrev()->SetFmtAttr( aTmp );
1183 rFmt.ResetFmtAttr( RES_CHAIN );
1188 void SwHistory::Add( const SwTxtFtn& rFtn )
1190 SwHistoryHint *pHt = new SwHistorySetFootnote( rFtn );
1191 m_SwpHstry.Insert( pHt, Count() );
1194 // #i27615#
1195 void SwHistory::Add(const SfxItemSet & rSet, const SwCharFmt & rFmt)
1197 SwHistoryHint * pHt = new SwHistoryChangeCharFmt(rSet, rFmt.GetName());
1198 m_SwpHstry.Insert(pHt, Count());
1201 /*************************************************************************
1203 |* BOOL SwHistory::Rollback()
1205 |* Beschreibung Dokument 1.0
1206 |* Ersterstellung JP 18.02.91
1207 |* Letzte Aenderung JP 18.02.91
1209 *************************************************************************/
1212 bool SwHistory::Rollback( SwDoc* pDoc, USHORT nStart )
1214 if ( !Count() )
1215 return false;
1217 SwHistoryHint * pHHt;
1218 USHORT i;
1219 for ( i = Count(); i > nStart ; )
1221 pHHt = m_SwpHstry[ --i ];
1222 pHHt->SetInDoc( pDoc, false );
1223 delete pHHt;
1225 m_SwpHstry.Remove( nStart, Count() - nStart );
1226 m_nEndDiff = 0;
1227 return true;
1232 bool SwHistory::TmpRollback( SwDoc* pDoc, USHORT nStart, bool bToFirst )
1234 USHORT nEnd = Count() - m_nEndDiff;
1235 if ( !Count() || !nEnd || nStart >= nEnd )
1236 return false;
1238 SwHistoryHint * pHHt;
1239 if ( bToFirst )
1241 for ( ; nEnd > nStart; ++m_nEndDiff )
1243 pHHt = m_SwpHstry[ --nEnd ];
1244 pHHt->SetInDoc( pDoc, true );
1247 else
1249 for ( ; nStart < nEnd; ++m_nEndDiff, ++nStart )
1251 pHHt = m_SwpHstry[ nStart ];
1252 pHHt->SetInDoc( pDoc, true );
1255 return true;
1259 void SwHistory::Delete( USHORT nStart )
1261 for ( USHORT n = Count(); n > nStart; )
1263 m_SwpHstry.DeleteAndDestroy( --n, 1 );
1265 m_nEndDiff = 0;
1269 USHORT SwHistory::SetTmpEnd( USHORT nNewTmpEnd )
1271 ASSERT( nNewTmpEnd <= Count(), "SwHistory::SetTmpEnd: out of bounds" );
1273 USHORT nOld = Count() - m_nEndDiff;
1274 m_nEndDiff = Count() - nNewTmpEnd;
1276 // for every SwHistoryFlyCnt, call the Redo of its UndoObject.
1277 // this saves the formats of the flys!
1278 for ( USHORT n = nOld; n < nNewTmpEnd; n++ )
1280 if ( HSTRY_FLYCNT == (*this)[ n ]->Which() )
1282 static_cast<SwHistoryTxtFlyCnt*>((*this)[ n ])
1283 ->GetUDelLFmt()->Redo();
1287 return nOld;
1290 void SwHistory::CopyFmtAttr( const SfxItemSet& rSet, ULONG nNodeIdx )
1292 if( rSet.Count() )
1294 SfxItemIter aIter( rSet );
1295 do {
1296 if( (SfxPoolItem*)-1 != aIter.GetCurItem() )
1298 const SfxPoolItem* pNew = aIter.GetCurItem();
1299 Add( pNew, pNew, nNodeIdx );
1301 if( aIter.IsAtEnd() )
1302 break;
1303 aIter.NextItem();
1304 } while( TRUE );
1308 void SwHistory::CopyAttr( SwpHints* pHts, ULONG nNodeIdx,
1309 xub_StrLen nStart, xub_StrLen nEnd, bool bFields )
1311 if( !pHts )
1312 return;
1314 // copy all attributes of the TextNode in the area from nStart to nEnd
1315 SwTxtAttr* pHt;
1316 xub_StrLen nAttrStt;
1317 const xub_StrLen * pEndIdx;
1318 for( USHORT n = 0; n < pHts->Count(); n++ )
1320 // BP: nAttrStt muss auch bei !pEndIdx gesetzt werden
1321 pHt = pHts->GetTextHint(n);
1322 nAttrStt = *pHt->GetStart();
1323 // JP: ???? wieso nAttrStt >= nEnd
1324 // if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt >= nEnd )
1325 if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt > nEnd )
1326 break;
1328 // Flys und Ftn nie kopieren !!
1329 BOOL bNextAttr = FALSE;
1330 switch( pHt->Which() )
1332 case RES_TXTATR_FIELD:
1333 // keine Felder, .. kopieren ??
1334 if( !bFields )
1335 bNextAttr = TRUE;
1336 break;
1337 case RES_TXTATR_FLYCNT:
1338 case RES_TXTATR_FTN:
1339 bNextAttr = TRUE;
1340 break;
1343 if( bNextAttr )
1344 continue;
1346 // save all attributes that are somehow in this area
1347 if ( nStart <= nAttrStt )
1349 if ( nEnd > nAttrStt
1350 // JP: ???? wieso nAttrStt >= nEnd
1351 // || (nEnd == nAttrStt && (!pEndIdx || nEnd == pEndIdx->GetIndex()))
1354 Add( pHt, nNodeIdx, false );
1357 else if ( pEndIdx && nStart < *pEndIdx )
1359 Add( pHt, nNodeIdx, false );
1365 /*************************************************************************/
1367 // Klasse zum Registrieren der History am Node, Format, HintsArray, ...
1369 SwRegHistory::SwRegHistory( SwHistory* pHst )
1370 : SwClient( 0 )
1371 , m_pHistory( pHst )
1372 , m_nNodeIndex( ULONG_MAX )
1374 _MakeSetWhichIds();
1377 SwRegHistory::SwRegHistory( SwModify* pRegIn, const SwNode& rNd,
1378 SwHistory* pHst )
1379 : SwClient( pRegIn )
1380 , m_pHistory( pHst )
1381 , m_nNodeIndex( rNd.GetIndex() )
1383 _MakeSetWhichIds();
1386 SwRegHistory::SwRegHistory( const SwNode& rNd, SwHistory* pHst )
1387 : SwClient( 0 )
1388 , m_pHistory( pHst )
1389 , m_nNodeIndex( rNd.GetIndex() )
1391 _MakeSetWhichIds();
1394 void SwRegHistory::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
1396 if ( m_pHistory && ( pOld || pNew ) )
1398 if ( pNew->Which() < POOLATTR_END )
1400 m_pHistory->Add( pOld, pNew, m_nNodeIndex );
1402 else if ( RES_ATTRSET_CHG == pNew->Which() )
1404 SwHistoryHint* pNewHstr;
1405 const SfxItemSet& rSet =
1406 *static_cast<SwAttrSetChg*>(pOld)->GetChgSet();
1407 if ( 1 < rSet.Count() )
1409 pNewHstr =
1410 new SwHistorySetAttrSet( rSet, m_nNodeIndex, m_WhichIdSet );
1412 else
1414 const SfxPoolItem* pItem = SfxItemIter( rSet ).FirstItem();
1415 if ( m_WhichIdSet.Seek_Entry( pItem->Which() ) )
1417 pNewHstr = new SwHistorySetFmt( pItem, m_nNodeIndex );
1419 else
1421 pNewHstr = new SwHistoryResetFmt( pItem, m_nNodeIndex );
1424 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() );
1431 void SwRegHistory::AddHint( SwTxtAttr* pHt, const bool bNew )
1433 m_pHistory->Add( pHt, m_nNodeIndex, bNew );
1437 bool SwRegHistory::InsertItems( const SfxItemSet& rSet,
1438 xub_StrLen const nStart, xub_StrLen const nEnd, SetAttrMode const nFlags )
1440 if( !rSet.Count() )
1441 return false;
1443 SwTxtNode * const pTxtNode =
1444 dynamic_cast<SwTxtNode *>(const_cast<SwModify *>(GetRegisteredIn()));
1446 ASSERT(pTxtNode, "SwRegHistory not registered at text node?");
1447 if (!pTxtNode)
1448 return false;
1450 if ( pTxtNode->GetpSwpHints() && m_pHistory )
1452 pTxtNode->GetpSwpHints()->Register( this );
1455 const bool bInserted = pTxtNode->SetAttr( rSet, nStart, nEnd, nFlags );
1457 // Achtung: Durch das Einfuegen eines Attributs kann das Array
1458 // geloescht werden!!! Wenn das einzufuegende zunaechst ein vorhandenes
1459 // loescht, selbst aber nicht eingefuegt werden braucht, weil die
1460 // Absatzattribute identisch sind( -> bForgetAttr in SwpHints::Insert )
1461 if ( pTxtNode->GetpSwpHints() && m_pHistory )
1463 pTxtNode->GetpSwpHints()->DeRegister();
1466 if ( m_pHistory && bInserted )
1468 SwHistoryHint* pNewHstr = new SwHistoryResetAttrSet( rSet,
1469 pTxtNode->GetIndex(), nStart, nEnd );
1470 // der NodeIndex kann verschoben sein !!
1472 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() );
1475 return bInserted;
1478 void SwRegHistory::RegisterInModify( SwModify* pRegIn, const SwNode& rNd )
1480 if ( m_pHistory && pRegIn )
1482 pRegIn->Add( this );
1483 m_nNodeIndex = rNd.GetIndex();
1484 _MakeSetWhichIds();
1486 else if ( m_WhichIdSet.Count() )
1488 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() );
1492 void SwRegHistory::_MakeSetWhichIds()
1494 if (!m_pHistory) return;
1496 if ( m_WhichIdSet.Count() )
1498 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() );
1501 if( GetRegisteredIn() )
1503 const SfxItemSet* pSet = 0;
1504 if( GetRegisteredIn()->ISA( SwCntntNode ) )
1506 pSet = static_cast<SwCntntNode*>(
1507 const_cast<SwModify*>(GetRegisteredIn()))->GetpSwAttrSet();
1509 else if ( GetRegisteredIn()->ISA( SwFmt ) )
1511 pSet = &static_cast<SwFmt*>(
1512 const_cast<SwModify*>(GetRegisteredIn()))->GetAttrSet();
1514 if( pSet && pSet->Count() )
1516 SfxItemIter aIter( *pSet );
1517 USHORT nW = aIter.FirstItem()->Which();
1518 while( TRUE )
1520 m_WhichIdSet.Insert( nW );
1521 if( aIter.IsAtEnd() )
1522 break;
1523 nW = aIter.NextItem()->Which();