/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sw.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // SwDoc.GetNodes() #include #include // SwTxtNode #include // #include // #include // fuer Felder #include // fuer SwPaM #include #include #include // SwGrfNode #include // fuer UndoDelete #include // fuer SwBookmark #include // #i27615# #ifndef _COMCORE_HRC #include #endif #include #ifndef _UNDO_HRC #include #endif #include #include SV_IMPL_PTRARR( SwpHstry, SwHistoryHintPtr) String SwHistoryHint::GetDescription() const { return String(); } SwHistorySetFmt::SwHistorySetFmt( const SfxPoolItem* pFmtHt, ULONG nNd ) : SwHistoryHint( HSTRY_SETFMTHNT ) , m_pAttr( pFmtHt->Clone() ) , m_nNodeIndex( nNd ) { switch ( m_pAttr->Which() ) { case RES_PAGEDESC: static_cast(*m_pAttr).ChgDefinedIn( 0 ); break; case RES_PARATR_DROP: static_cast(*m_pAttr).ChgDefinedIn( 0 ); break; case RES_BOXATR_FORMULA: { //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern SwTblBoxFormula& rNew = static_cast(*m_pAttr); if ( rNew.IsIntrnlName() ) { const SwTblBoxFormula& rOld = *static_cast(pFmtHt); const SwNode* pNd = rOld.GetNodeOfFormula(); if ( pNd ) { const SwTableNode* pTableNode = pNd->FindTableNode(); if (pTableNode) { SwTableFmlUpdate aMsgHnt( &pTableNode->GetTable() ); aMsgHnt.eFlags = TBL_BOXNAME; rNew.ChgDefinedIn( rOld.GetDefinedIn() ); rNew.ChangeState( &aMsgHnt ); } } } rNew.ChgDefinedIn( 0 ); } break; } } String SwHistorySetFmt::GetDescription() const { String aResult ; USHORT nWhich = m_pAttr->Which(); switch (nWhich) { case RES_BREAK: switch ((static_cast(*m_pAttr)).GetBreak()) { case SVX_BREAK_PAGE_BEFORE: case SVX_BREAK_PAGE_AFTER: case SVX_BREAK_PAGE_BOTH: aResult = SW_RES(STR_UNDO_PAGEBREAKS); break; case SVX_BREAK_COLUMN_BEFORE: case SVX_BREAK_COLUMN_AFTER: case SVX_BREAK_COLUMN_BOTH: aResult = SW_RES(STR_UNDO_COLBRKS); break; default: break; } break; default: break; } return aResult; } void SwHistorySetFmt::SetInDoc( SwDoc* pDoc, bool bTmpSet ) { SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ]; if ( pNode->IsCntntNode() ) { static_cast(pNode)->SetAttr( *m_pAttr ); } else if ( pNode->IsTableNode() ) { static_cast(pNode)->GetTable().GetFrmFmt()->SetFmtAttr( *m_pAttr ); } else if ( pNode->IsStartNode() && (SwTableBoxStartNode == static_cast(pNode)->GetStartNodeType()) ) { SwTableNode* pTNd = pNode->FindTableNode(); if ( pTNd ) { SwTableBox* pBox = pTNd->GetTable().GetTblBox( m_nNodeIndex ); if (pBox) { pBox->ClaimFrmFmt()->SetFmtAttr( *m_pAttr ); } } } if ( !bTmpSet ) { m_pAttr.reset(); } } SwHistorySetFmt::~SwHistorySetFmt() { } // --> OD 2008-02-27 #refactorlists# - removed SwHistoryResetFmt::SwHistoryResetFmt(const SfxPoolItem* pFmtHt, ULONG nNodeIdx) // <-- : SwHistoryHint( HSTRY_RESETFMTHNT ) , m_nNodeIndex( nNodeIdx ) , m_nWhich( pFmtHt->Which() ) { } void SwHistoryResetFmt::SetInDoc( SwDoc* pDoc, bool ) { SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ]; if ( pNode->IsCntntNode() ) { static_cast(pNode)->ResetAttr( m_nWhich ); } else if ( pNode->IsTableNode() ) { static_cast(pNode)->GetTable().GetFrmFmt()-> ResetFmtAttr( m_nWhich ); } } SwHistorySetTxt::SwHistorySetTxt( SwTxtAttr* pTxtHt, ULONG nNodePos ) : SwHistoryHint( HSTRY_SETTXTHNT ) , m_nNodeIndex( nNodePos ) , m_nStart( *pTxtHt->GetStart() ) , m_nEnd( *pTxtHt->GetAnyEnd() ) { // !! Achtung: folgende Attribute erzeugen keine FormatAttribute: // - NoLineBreak, NoHypen, Inserted, Deleted // Dafuer muessen Sonderbehandlungen gemacht werden !!! // ein bisschen kompliziert, aber ist Ok so: erst vom default // eine Kopie und dann die Werte aus dem Text Attribut zuweisen USHORT nWhich = pTxtHt->Which(); if ( RES_TXTATR_CHARFMT == nWhich ) { m_pAttr.reset( new SwFmtCharFmt( pTxtHt->GetCharFmt().GetCharFmt() ) ); } else { m_pAttr.reset( pTxtHt->GetAttr().Clone() ); } } SwHistorySetTxt::~SwHistorySetTxt() { } void SwHistorySetTxt::SetInDoc( SwDoc* pDoc, bool ) { if ( !m_pAttr.get() ) return; if ( RES_TXTATR_CHARFMT == m_pAttr->Which() ) { // ask the Doc if the CharFmt still exists if ( USHRT_MAX == pDoc->GetCharFmts()->GetPos( (static_cast(*m_pAttr)).GetCharFmt() ) ) return; // do not set, format does not exist } SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); ASSERT( pTxtNd, "SwHistorySetTxt::SetInDoc: not a TextNode" ); if ( pTxtNd ) { pTxtNd->InsertItem( *m_pAttr, m_nStart, m_nEnd, nsSetAttrMode::SETATTR_NOTXTATRCHR | nsSetAttrMode::SETATTR_NOHINTADJUST ); } } SwHistorySetTxtFld::SwHistorySetTxtFld( SwTxtFld* pTxtFld, ULONG nNodePos ) : SwHistoryHint( HSTRY_SETTXTFLDHNT ) , m_pFldType( 0 ) , m_pFld( new SwFmtFld( *pTxtFld->GetFld().GetFld() ) ) { // only copy if not Sys-FieldType SwDoc* pDoc = pTxtFld->GetTxtNode().GetDoc(); m_nFldWhich = m_pFld->GetFld()->GetTyp()->Which(); if (m_nFldWhich == RES_DBFLD || m_nFldWhich == RES_USERFLD || m_nFldWhich == RES_SETEXPFLD || m_nFldWhich == RES_DDEFLD || !pDoc->GetSysFldType( m_nFldWhich )) { m_pFldType.reset( m_pFld->GetFld()->GetTyp()->Copy() ); m_pFld->GetFld()->ChgTyp( m_pFldType.get() ); // change field type } m_nNodeIndex = nNodePos; m_nPos = *pTxtFld->GetStart(); } String SwHistorySetTxtFld::GetDescription() const { return m_pFld->GetFld()->GetDescription();; } SwHistorySetTxtFld::~SwHistorySetTxtFld() { } void SwHistorySetTxtFld::SetInDoc( SwDoc* pDoc, bool ) { if ( !m_pFld.get() ) return; SwFieldType* pNewFldType = m_pFldType.get(); if ( !pNewFldType ) { pNewFldType = pDoc->GetSysFldType( m_nFldWhich ); } else { // register type with the document pNewFldType = pDoc->InsertFldType( *m_pFldType ); } m_pFld->GetFld()->ChgTyp( pNewFldType ); // change field type SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); ASSERT( pTxtNd, "SwHistorySetTxtFld: no TextNode" ); if ( pTxtNd ) { pTxtNd->InsertItem( *m_pFld, m_nPos, m_nPos, nsSetAttrMode::SETATTR_NOTXTATRCHR ); } } SwHistorySetRefMark::SwHistorySetRefMark( SwTxtRefMark* pTxtHt, ULONG nNodePos ) : SwHistoryHint( HSTRY_SETREFMARKHNT ) , m_RefName( pTxtHt->GetRefMark().GetRefName() ) , m_nNodeIndex( nNodePos ) , m_nStart( *pTxtHt->GetStart() ) , m_nEnd( *pTxtHt->GetAnyEnd() ) { } void SwHistorySetRefMark::SetInDoc( SwDoc* pDoc, bool ) { SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); ASSERT( pTxtNd, "SwHistorySetRefMark: no TextNode" ); if ( !pTxtNd ) return; SwFmtRefMark aRefMark( m_RefName ); // if a reference mark without an end already exists here: must not insert! if ( m_nStart != m_nEnd || !pTxtNd->GetTxtAttrForCharAt( m_nStart, RES_TXTATR_REFMARK ) ) { pTxtNd->InsertItem( aRefMark, m_nStart, m_nEnd, nsSetAttrMode::SETATTR_NOTXTATRCHR ); } } SwHistorySetTOXMark::SwHistorySetTOXMark( SwTxtTOXMark* pTxtHt, ULONG nNodePos ) : SwHistoryHint( HSTRY_SETTOXMARKHNT ) , m_TOXMark( pTxtHt->GetTOXMark() ) , m_TOXName( m_TOXMark.GetTOXType()->GetTypeName() ) , m_eTOXTypes( m_TOXMark.GetTOXType()->GetType() ) , m_nNodeIndex( nNodePos ) , m_nStart( *pTxtHt->GetStart() ) , m_nEnd( *pTxtHt->GetAnyEnd() ) { const_cast(m_TOXMark.GetRegisteredIn())->Remove( &m_TOXMark ); } void SwHistorySetTOXMark::SetInDoc( SwDoc* pDoc, bool ) { SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); ASSERT( pTxtNd, "SwHistorySetTOXMark: no TextNode" ); if ( !pTxtNd ) return; // search for respective TOX type USHORT nCnt = pDoc->GetTOXTypeCount( m_eTOXTypes ); SwTOXType* pToxType = 0; for ( USHORT n = 0; n < nCnt; ++n ) { pToxType = const_cast(pDoc->GetTOXType( m_eTOXTypes, n )); if ( pToxType->GetTypeName() == m_TOXName ) break; pToxType = 0; } if ( !pToxType ) // TOX type not found, create new { pToxType = const_cast( pDoc->InsertTOXType( SwTOXType( m_eTOXTypes, m_TOXName ))); } SwTOXMark aNew( m_TOXMark ); pToxType->Add( &aNew ); pTxtNd->InsertItem( aNew, m_nStart, m_nEnd, nsSetAttrMode::SETATTR_NOTXTATRCHR ); } int SwHistorySetTOXMark::IsEqual( const SwTOXMark& rCmp ) const { return m_TOXName == rCmp.GetTOXType()->GetTypeName() && m_eTOXTypes == rCmp.GetTOXType()->GetType() && m_TOXMark.GetAlternativeText() == rCmp.GetAlternativeText() && ( (TOX_INDEX == m_eTOXTypes) ? ( m_TOXMark.GetPrimaryKey() == rCmp.GetPrimaryKey() && m_TOXMark.GetSecondaryKey() == rCmp.GetSecondaryKey() ) : m_TOXMark.GetLevel() == rCmp.GetLevel() ); } SwHistoryResetTxt::SwHistoryResetTxt( USHORT nWhich, xub_StrLen nAttrStart, xub_StrLen nAttrEnd, ULONG nNodePos ) : SwHistoryHint( HSTRY_RESETTXTHNT ) , m_nNodeIndex( nNodePos ), m_nStart( nAttrStart ), m_nEnd( nAttrEnd ) , m_nAttr( nWhich ) { } void SwHistoryResetTxt::SetInDoc( SwDoc* pDoc, bool ) { SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); ASSERT( pTxtNd, "SwHistoryResetTxt: no TextNode" ); if ( pTxtNd ) { pTxtNd->DeleteAttributes( m_nAttr, m_nStart, m_nEnd ); } } SwHistorySetFootnote::SwHistorySetFootnote( SwTxtFtn* pTxtFtn, ULONG nNodePos ) : SwHistoryHint( HSTRY_SETFTNHNT ) , m_pUndo( new SwUndoSaveSection ) , m_FootnoteNumber( pTxtFtn->GetFtn().GetNumStr() ) , m_nNodeIndex( nNodePos ) , m_nStart( *pTxtFtn->GetStart() ) , m_bEndNote( pTxtFtn->GetFtn().IsEndNote() ) { ASSERT( pTxtFtn->GetStartNode(), "SwHistorySetFootnote: Footnote without Section" ); // merke die alte NodePos, denn wer weiss was alles in der SaveSection // gespeichert (geloescht) wird SwDoc* pDoc = const_cast(pTxtFtn->GetTxtNode().GetDoc()); SwNode* pSaveNd = pDoc->GetNodes()[ m_nNodeIndex ]; //Pointer auf StartNode der FtnSection merken und erstmal den Pointer im //Attribut zuruecksetzen -> Damit werden automatisch die Frms vernichtet. SwNodeIndex aSttIdx( *pTxtFtn->GetStartNode() ); pTxtFtn->SetStartNode( 0, FALSE ); m_pUndo->SaveSection( pDoc, aSttIdx ); m_nNodeIndex = pSaveNd->GetIndex(); } SwHistorySetFootnote::SwHistorySetFootnote( const SwTxtFtn &rTxtFtn ) : SwHistoryHint( HSTRY_SETFTNHNT ) , m_pUndo( 0 ) , m_FootnoteNumber( rTxtFtn.GetFtn().GetNumStr() ) , m_nNodeIndex( _SwTxtFtn_GetIndex( (&rTxtFtn) ) ) , m_nStart( *rTxtFtn.GetStart() ) , m_bEndNote( rTxtFtn.GetFtn().IsEndNote() ) { ASSERT( rTxtFtn.GetStartNode(), "SwHistorySetFootnote: Footnote without Section" ); } String SwHistorySetFootnote::GetDescription() const { return SW_RES(STR_FOOTNOTE); } SwHistorySetFootnote::~SwHistorySetFootnote() { } void SwHistorySetFootnote::SetInDoc( SwDoc* pDoc, bool ) { SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode(); ASSERT( pTxtNd, "SwHistorySetFootnote: no TextNode" ); if ( !pTxtNd ) return; if ( m_pUndo.get() ) { // set the footnote in the TextNode SwFmtFtn aTemp( m_bEndNote ); SwFmtFtn& rNew = const_cast( static_cast(pDoc->GetAttrPool().Put(aTemp)) ); if ( m_FootnoteNumber.Len() ) { rNew.SetNumStr( m_FootnoteNumber ); } SwTxtFtn* pTxtFtn = new SwTxtFtn( rNew, m_nStart ); // create the section of the Footnote SwNodeIndex aIdx( *pTxtNd ); m_pUndo->RestoreSection( pDoc, &aIdx, SwFootnoteStartNode ); pTxtFtn->SetStartNode( &aIdx ); if ( m_pUndo->GetHistory() ) { // create frames only now m_pUndo->GetHistory()->Rollback( pDoc ); } pTxtNd->InsertHint( pTxtFtn ); } else { SwTxtFtn * const pFtn = const_cast( static_cast( pTxtNd->GetTxtAttrForCharAt( m_nStart ))); SwFmtFtn &rFtn = const_cast(pFtn->GetFtn()); rFtn.SetNumStr( m_FootnoteNumber ); if ( rFtn.IsEndNote() != m_bEndNote ) { rFtn.SetEndNote( m_bEndNote ); pFtn->CheckCondColl(); } } } SwHistoryChangeFmtColl::SwHistoryChangeFmtColl( SwFmtColl* pFmtColl, ULONG nNd, BYTE nNodeWhich ) : SwHistoryHint( HSTRY_CHGFMTCOLL ) , m_pColl( pFmtColl ) , m_nNodeIndex( nNd ) , m_nNodeType( nNodeWhich ) { } void SwHistoryChangeFmtColl::SetInDoc( SwDoc* pDoc, bool ) { SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode(); ASSERT( pCntntNd, "SwHistoryChangeFmtColl: no ContentNode" ); // before setting the format, check if it is still available in the // document. if it has been deleted, there is no undo! if ( pCntntNd && m_nNodeType == pCntntNd->GetNodeType() ) { if ( ND_TEXTNODE == m_nNodeType ) { if ( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( static_cast(m_pColl) )) { pCntntNd->ChgFmtColl( m_pColl ); } } else if ( USHRT_MAX != pDoc->GetGrfFmtColls()->GetPos( static_cast(m_pColl) )) { pCntntNd->ChgFmtColl( m_pColl ); } } } SwHistoryTxtFlyCnt::SwHistoryTxtFlyCnt( SwFrmFmt* const pFlyFmt ) : SwHistoryHint( HSTRY_FLYCNT ) , m_pUndo( new SwUndoDelLayFmt( pFlyFmt ) ) { ASSERT( pFlyFmt, "SwHistoryTxtFlyCnt: no Format" ); m_pUndo->ChgShowSel( FALSE ); } SwHistoryTxtFlyCnt::~SwHistoryTxtFlyCnt() { } void SwHistoryTxtFlyCnt::SetInDoc( SwDoc* pDoc, bool ) { SwPaM aPam( pDoc->GetNodes().GetEndOfPostIts() ); SwUndoIter aUndoIter( &aPam ); m_pUndo->Undo( aUndoIter ); } SwHistoryBookmark::SwHistoryBookmark( const ::sw::mark::IMark& rBkmk, bool bSavePos, bool bSaveOtherPos) : SwHistoryHint(HSTRY_BOOKMARK) , m_aName(rBkmk.GetName()) , m_aShortName() , m_aKeycode() , m_nNode(bSavePos ? rBkmk.GetMarkPos().nNode.GetIndex() : 0) , m_nOtherNode(bSaveOtherPos ? rBkmk.GetOtherMarkPos().nNode.GetIndex() : 0) , m_nCntnt(bSavePos ? rBkmk.GetMarkPos().nContent.GetIndex() : 0) , m_nOtherCntnt(bSaveOtherPos ? rBkmk.GetOtherMarkPos().nContent.GetIndex() :0) , m_bSavePos(bSavePos) , m_bSaveOtherPos(bSaveOtherPos) , m_bHadOtherPos(rBkmk.IsExpanded()) , m_eBkmkType(IDocumentMarkAccess::GetType(rBkmk)) { const ::sw::mark::IBookmark* const pBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(&rBkmk); if(pBookmark) { m_aKeycode = pBookmark->GetKeyCode(); m_aShortName = pBookmark->GetShortName(); ::sfx2::Metadatable const*const pMetadatable( dynamic_cast< ::sfx2::Metadatable const* >(pBookmark)); if (pMetadatable) { m_pMetadataUndo = pMetadatable->CreateUndo(); } } } void SwHistoryBookmark::SetInDoc( SwDoc* pDoc, bool ) { bool bDoesUndo = pDoc->DoesUndo(); pDoc->DoUndo(false); SwNodes& rNds = pDoc->GetNodes(); IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); ::std::auto_ptr pPam; ::sw::mark::IMark* pMark = NULL; if(m_bSavePos) { SwCntntNode* const pCntntNd = rNds[m_nNode]->GetCntntNode(); OSL_ENSURE(pCntntNd, "" " - wrong node for a mark"); // #111660# don't crash when nNode1 doesn't point to content node. if(pCntntNd) pPam = ::std::auto_ptr(new SwPaM(*pCntntNd, m_nCntnt)); } else { pMark = pMarkAccess->findMark(m_aName)->get(); pPam = ::std::auto_ptr(new SwPaM(pMark->GetMarkPos())); } if(m_bSaveOtherPos) { SwCntntNode* const pCntntNd = rNds[m_nOtherNode]->GetCntntNode(); OSL_ENSURE(pCntntNd, "" " - wrong node for a mark"); if(pPam.get() != NULL && pCntntNd) { pPam->SetMark(); pPam->GetMark()->nNode = m_nOtherNode; pPam->GetMark()->nContent.Assign(pCntntNd, m_nOtherCntnt); } } else if(m_bHadOtherPos) { if(!pMark) pMark = pMarkAccess->findMark(m_aName)->get(); OSL_ENSURE(pMark->IsExpanded(), "" " - missing pos on old mark"); pPam->SetMark(); *pPam->GetMark() = pMark->GetOtherMarkPos(); } if(pPam.get()) { if(pMark) pMarkAccess->deleteMark(pMark); ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >( pMarkAccess->makeMark(*pPam, m_aName, m_eBkmkType)); if(pBookmark) { pBookmark->SetKeyCode(m_aKeycode); pBookmark->SetShortName(m_aShortName); if (m_pMetadataUndo) { ::sfx2::Metadatable * const pMeta( dynamic_cast< ::sfx2::Metadatable* >(pBookmark)); OSL_ENSURE(pMeta, "metadata undo, but not metadatable?"); if (pMeta) { pMeta->RestoreMetadata(m_pMetadataUndo); } } } } pDoc->DoUndo(bDoesUndo); } bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark& rBkmk) { return m_nNode == rBkmk.GetMarkPos().nNode.GetIndex() && m_nCntnt == rBkmk.GetMarkPos().nContent.GetIndex() && m_aName == rBkmk.GetName(); } const ::rtl::OUString& SwHistoryBookmark::GetName() const { return m_aName; } /*************************************************************************/ SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet& rSet, ULONG nNodePos, const SvUShortsSort& rSetArr ) : SwHistoryHint( HSTRY_SETATTRSET ) , m_OldSet( rSet ) , m_ResetArray( 0, 4 ) , m_nNodeIndex( nNodePos ) { SfxItemIter aIter( m_OldSet ), aOrigIter( rSet ); const SfxPoolItem* pItem = aIter.FirstItem(), * pOrigItem = aOrigIter.FirstItem(); do { if( !rSetArr.Seek_Entry( pOrigItem->Which() )) { m_ResetArray.Insert( pOrigItem->Which(), m_ResetArray.Count() ); m_OldSet.ClearItem( pOrigItem->Which() ); } else { switch ( pItem->Which() ) { case RES_PAGEDESC: static_cast( const_cast(pItem))->ChgDefinedIn( 0 ); break; case RES_PARATR_DROP: static_cast( const_cast(pItem))->ChgDefinedIn( 0 ); break; case RES_BOXATR_FORMULA: { //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den // Value mit sichern. Der muss gegebenfalls neu // errechnet werden! //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern m_OldSet.ClearItem( RES_BOXATR_VALUE ); SwTblBoxFormula& rNew = *static_cast( const_cast(pItem)); if ( rNew.IsIntrnlName() ) { const SwTblBoxFormula& rOld = static_cast( rSet.Get( RES_BOXATR_FORMULA )); const SwNode* pNd = rOld.GetNodeOfFormula(); if ( pNd ) { const SwTableNode* pTableNode = pNd->FindTableNode(); if (pTableNode) { SwTableFmlUpdate aMsgHnt( &pTableNode->GetTable() ); aMsgHnt.eFlags = TBL_BOXNAME; rNew.ChgDefinedIn( rOld.GetDefinedIn() ); rNew.ChangeState( &aMsgHnt ); } } } rNew.ChgDefinedIn( 0 ); } break; } } if( aIter.IsAtEnd() ) break; pItem = aIter.NextItem(); pOrigItem = aOrigIter.NextItem(); } while( TRUE ); } void SwHistorySetAttrSet::SetInDoc( SwDoc* pDoc, bool ) { BOOL bDoesUndo = pDoc->DoesUndo(); pDoc->DoUndo( FALSE ); SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ]; if ( pNode->IsCntntNode() ) { static_cast(pNode)->SetAttr( m_OldSet ); if ( m_ResetArray.Count() ) { static_cast(pNode)->ResetAttr( m_ResetArray ); } } else if ( pNode->IsTableNode() ) { SwFmt& rFmt = *static_cast(pNode)->GetTable().GetFrmFmt(); rFmt.SetFmtAttr( m_OldSet ); if ( m_ResetArray.Count() ) { rFmt.ResetFmtAttr( *m_ResetArray.GetData() ); } } pDoc->DoUndo( bDoesUndo ); } /*************************************************************************/ SwHistoryResetAttrSet::SwHistoryResetAttrSet( const SfxItemSet& rSet, ULONG nNodePos, xub_StrLen nAttrStt, xub_StrLen nAttrEnd ) : SwHistoryHint( HSTRY_RESETATTRSET ) , m_nNodeIndex( nNodePos ), m_nStart( nAttrStt ), m_nEnd( nAttrEnd ) , m_Array( (BYTE)rSet.Count() ) { SfxItemIter aIter( rSet ); bool bAutoStyle = false; while( TRUE ) { const USHORT nWhich = aIter.GetCurItem()->Which(); #ifndef PRODUCT switch (nWhich) { case RES_TXTATR_REFMARK: case RES_TXTATR_TOXMARK: if (m_nStart != m_nEnd) break; // else: fall through! case RES_TXTATR_FIELD: case RES_TXTATR_FLYCNT: case RES_TXTATR_FTN: case RES_TXTATR_META: case RES_TXTATR_METAFIELD: ASSERT(rSet.Count() == 1, "text attribute with CH_TXTATR, but not the only one:" "\nnot such a good idea"); break; } #endif // Character attribute cannot be inserted into the hints array // anymore. Therefore we have to treat them as one RES_TXTATR_AUTOFMT: if (isCHRATR(nWhich)) { bAutoStyle = true; } else { m_Array.Insert( aIter.GetCurItem()->Which(), m_Array.Count() ); } if( aIter.IsAtEnd() ) break; aIter.NextItem(); } if ( bAutoStyle ) { m_Array.Insert( RES_TXTATR_AUTOFMT, m_Array.Count() ); } } void SwHistoryResetAttrSet::SetInDoc( SwDoc* pDoc, bool ) { BOOL bDoesUndo = pDoc->DoesUndo(); pDoc->DoUndo( FALSE ); SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode(); ASSERT( pCntntNd, "SwHistoryResetAttrSet: no CntntNode" ); if (pCntntNd) { const USHORT* pArr = m_Array.GetData(); if ( USHRT_MAX == m_nEnd && USHRT_MAX == m_nStart ) { // no area: use ContentNode for ( USHORT n = m_Array.Count(); n; --n, ++pArr ) { pCntntNd->ResetAttr( *pArr ); } } else { // area: use TextNode for ( USHORT n = m_Array.Count(); n; --n, ++pArr ) { static_cast(pCntntNd)-> DeleteAttributes( *pArr, m_nStart, m_nEnd ); } } } pDoc->DoUndo( bDoesUndo ); } /*************************************************************************/ SwHistoryChangeFlyAnchor::SwHistoryChangeFlyAnchor( SwFrmFmt& rFmt ) : SwHistoryHint( HSTRY_CHGFLYANCHOR ) , m_rFmt( rFmt ) , m_nOldNodeIndex( rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex() ) , m_nOldContentIndex( (FLY_AT_CHAR == rFmt.GetAnchor().GetAnchorId()) ? rFmt.GetAnchor().GetCntntAnchor()->nContent.GetIndex() : STRING_MAXLEN ) { } void SwHistoryChangeFlyAnchor::SetInDoc( SwDoc* pDoc, bool ) { BOOL bDoesUndo = pDoc->DoesUndo(); pDoc->DoUndo( FALSE ); USHORT nPos = pDoc->GetSpzFrmFmts()->GetPos( &m_rFmt ); if ( USHRT_MAX != nPos ) // Format does still exist { SwFmtAnchor aTmp( m_rFmt.GetAnchor() ); SwNode* pNd = pDoc->GetNodes()[ m_nOldNodeIndex ]; SwCntntNode* pCNd = pNd->GetCntntNode(); SwPosition aPos( *pNd ); if ( STRING_MAXLEN != m_nOldContentIndex ) { ASSERT(pCNd, "SwHistoryChangeFlyAnchor: no ContentNode"); if (pCNd) { aPos.nContent.Assign( pCNd, m_nOldContentIndex ); } } aTmp.SetAnchor( &aPos ); // so the Layout does not get confused if ( !pCNd || !pCNd->GetFrm( 0, 0, FALSE ) ) { m_rFmt.DelFrms(); } m_rFmt.SetFmtAttr( aTmp ); } pDoc->DoUndo( bDoesUndo ); } /*************************************************************************/ SwHistoryChangeFlyChain::SwHistoryChangeFlyChain( SwFlyFrmFmt& rFmt, const SwFmtChain& rAttr ) : SwHistoryHint( HSTRY_CHGFLYCHAIN ) , m_pPrevFmt( rAttr.GetPrev() ) , m_pNextFmt( rAttr.GetNext() ) , m_pFlyFmt( &rFmt ) { } void SwHistoryChangeFlyChain::SetInDoc( SwDoc* pDoc, bool ) { if ( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pFlyFmt ) ) { SwFmtChain aChain; if ( m_pPrevFmt && USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pPrevFmt ) ) { aChain.SetPrev( m_pPrevFmt ); SwFmtChain aTmp( m_pPrevFmt->GetChain() ); aTmp.SetNext( m_pFlyFmt ); m_pPrevFmt->SetFmtAttr( aTmp ); } if ( m_pNextFmt && USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pNextFmt ) ) { aChain.SetNext( m_pNextFmt ); SwFmtChain aTmp( m_pNextFmt->GetChain() ); aTmp.SetPrev( m_pFlyFmt ); m_pNextFmt->SetFmtAttr( aTmp ); } if ( aChain.GetNext() || aChain.GetPrev() ) { m_pFlyFmt->SetFmtAttr( aChain ); } } } // -> #i27615# SwHistoryChangeCharFmt::SwHistoryChangeCharFmt(const SfxItemSet & rSet, const String & sFmt) : SwHistoryHint(HSTRY_CHGCHARFMT) , m_OldSet(rSet), m_Fmt(sFmt) { } void SwHistoryChangeCharFmt::SetInDoc(SwDoc * pDoc, bool ) { SwCharFmt * pCharFmt = pDoc->FindCharFmtByName(m_Fmt); if (pCharFmt) { pCharFmt->SetFmtAttr(m_OldSet); } } // <- #i27615# /* */ SwHistory::SwHistory( USHORT nInitSz, USHORT nGrowSz ) : m_SwpHstry( (BYTE)nInitSz, (BYTE)nGrowSz ) , m_nEndDiff( 0 ) {} SwHistory::~SwHistory() { Delete( 0 ); } /************************************************************************* |* |* void SwHistory::Add() |* |* Beschreibung Dokument 1.0 |* Ersterstellung JP 18.02.91 |* Letzte Aenderung JP 18.02.91 |* *************************************************************************/ // --> OD 2008-02-27 #refactorlists# - removed void SwHistory::Add( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue, ULONG nNodeIdx ) // <-- { ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); USHORT nWhich = pNewValue->Which(); if( (nWhich >= POOLATTR_END) || (nWhich == RES_TXTATR_FIELD) ) return; // no default Attribute? SwHistoryHint * pHt; if ( pOldValue && pOldValue != GetDfltAttr( pOldValue->Which() ) ) { pHt = new SwHistorySetFmt( pOldValue, nNodeIdx ); } else { pHt = new SwHistoryResetFmt( pNewValue, nNodeIdx ); } m_SwpHstry.Insert( pHt, Count() ); } void SwHistory::Add( SwTxtAttr* pHint, ULONG nNodeIdx, bool bNewAttr ) { ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); SwHistoryHint * pHt; USHORT nAttrWhich = pHint->Which(); if( !bNewAttr ) { switch ( nAttrWhich ) { case RES_TXTATR_FTN: pHt = new SwHistorySetFootnote( static_cast(pHint), nNodeIdx ); break; case RES_TXTATR_FLYCNT: pHt = new SwHistoryTxtFlyCnt( static_cast(pHint) ->GetFlyCnt().GetFrmFmt() ); break; case RES_TXTATR_FIELD: pHt = new SwHistorySetTxtFld( static_cast(pHint), nNodeIdx ); break; case RES_TXTATR_TOXMARK: pHt = new SwHistorySetTOXMark( static_cast(pHint), nNodeIdx ); break; case RES_TXTATR_REFMARK: pHt = new SwHistorySetRefMark( static_cast(pHint), nNodeIdx ); break; default: pHt = new SwHistorySetTxt( static_cast(pHint), nNodeIdx ); } } else { pHt = new SwHistoryResetTxt( pHint->Which(), *pHint->GetStart(), *pHint->GetAnyEnd(), nNodeIdx ); } m_SwpHstry.Insert( pHt, Count() ); } void SwHistory::Add( SwFmtColl* pColl, ULONG nNodeIdx, BYTE nWhichNd ) { ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); SwHistoryHint * pHt = new SwHistoryChangeFmtColl( pColl, nNodeIdx, nWhichNd ); m_SwpHstry.Insert( pHt, Count() ); } void SwHistory::Add(const ::sw::mark::IMark& rBkmk, bool bSavePos, bool bSaveOtherPos) { ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); SwHistoryHint * pHt = new SwHistoryBookmark(rBkmk, bSavePos, bSaveOtherPos); m_SwpHstry.Insert( pHt, Count() ); } void SwHistory::Add( SwFrmFmt& rFmt ) { SwHistoryHint * pHt = new SwHistoryChangeFlyAnchor( rFmt ); m_SwpHstry.Insert( pHt, Count() ); } void SwHistory::Add( SwFlyFrmFmt& rFmt, USHORT& rSetPos ) { ASSERT( !m_nEndDiff, "History was not deleted after REDO" ); SwHistoryHint * pHint; const USHORT nWh = rFmt.Which(); if( RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh ) { pHint = new SwHistoryTxtFlyCnt( &rFmt ); m_SwpHstry.Insert( pHint, Count() ); const SwFmtChain* pChainItem; if( SFX_ITEM_SET == rFmt.GetItemState( RES_CHAIN, FALSE, (const SfxPoolItem**)&pChainItem )) { if( pChainItem->GetNext() || pChainItem->GetPrev() ) { SwHistoryHint * pHt = new SwHistoryChangeFlyChain( rFmt, *pChainItem ); m_SwpHstry.Insert( pHt, rSetPos++ ); if ( pChainItem->GetNext() ) { SwFmtChain aTmp( pChainItem->GetNext()->GetChain() ); aTmp.SetPrev( 0 ); pChainItem->GetNext()->SetFmtAttr( aTmp ); } if ( pChainItem->GetPrev() ) { SwFmtChain aTmp( pChainItem->GetPrev()->GetChain() ); aTmp.SetNext( 0 ); pChainItem->GetPrev()->SetFmtAttr( aTmp ); } } rFmt.ResetFmtAttr( RES_CHAIN ); } } } void SwHistory::Add( const SwTxtFtn& rFtn ) { SwHistoryHint *pHt = new SwHistorySetFootnote( rFtn ); m_SwpHstry.Insert( pHt, Count() ); } // #i27615# void SwHistory::Add(const SfxItemSet & rSet, const SwCharFmt & rFmt) { SwHistoryHint * pHt = new SwHistoryChangeCharFmt(rSet, rFmt.GetName()); m_SwpHstry.Insert(pHt, Count()); } /************************************************************************* |* |* BOOL SwHistory::Rollback() |* |* Beschreibung Dokument 1.0 |* Ersterstellung JP 18.02.91 |* Letzte Aenderung JP 18.02.91 |* *************************************************************************/ bool SwHistory::Rollback( SwDoc* pDoc, USHORT nStart ) { if ( !Count() ) return false; SwHistoryHint * pHHt; USHORT i; for ( i = Count(); i > nStart ; ) { pHHt = m_SwpHstry[ --i ]; pHHt->SetInDoc( pDoc, false ); delete pHHt; } m_SwpHstry.Remove( nStart, Count() - nStart ); m_nEndDiff = 0; return true; } bool SwHistory::TmpRollback( SwDoc* pDoc, USHORT nStart, bool bToFirst ) { USHORT nEnd = Count() - m_nEndDiff; if ( !Count() || !nEnd || nStart >= nEnd ) return false; SwHistoryHint * pHHt; if ( bToFirst ) { for ( ; nEnd > nStart; ++m_nEndDiff ) { pHHt = m_SwpHstry[ --nEnd ]; pHHt->SetInDoc( pDoc, true ); } } else { for ( ; nStart < nEnd; ++m_nEndDiff, ++nStart ) { pHHt = m_SwpHstry[ nStart ]; pHHt->SetInDoc( pDoc, true ); } } return true; } void SwHistory::Delete( USHORT nStart ) { for ( USHORT n = Count(); n > nStart; ) { m_SwpHstry.DeleteAndDestroy( --n, 1 ); } m_nEndDiff = 0; } USHORT SwHistory::SetTmpEnd( USHORT nNewTmpEnd ) { ASSERT( nNewTmpEnd <= Count(), "SwHistory::SetTmpEnd: out of bounds" ); USHORT nOld = Count() - m_nEndDiff; m_nEndDiff = Count() - nNewTmpEnd; // for every SwHistoryFlyCnt, call the Redo of its UndoObject. // this saves the formats of the flys! for ( USHORT n = nOld; n < nNewTmpEnd; n++ ) { if ( HSTRY_FLYCNT == (*this)[ n ]->Which() ) { static_cast((*this)[ n ]) ->GetUDelLFmt()->Redo(); } } return nOld; } void SwHistory::CopyFmtAttr( const SfxItemSet& rSet, ULONG nNodeIdx ) { if( rSet.Count() ) { SfxItemIter aIter( rSet ); do { if( (SfxPoolItem*)-1 != aIter.GetCurItem() ) { const SfxPoolItem* pNew = aIter.GetCurItem(); Add( pNew, pNew, nNodeIdx ); } if( aIter.IsAtEnd() ) break; aIter.NextItem(); } while( TRUE ); } } void SwHistory::CopyAttr( SwpHints* pHts, ULONG nNodeIdx, xub_StrLen nStart, xub_StrLen nEnd, bool bFields ) { if( !pHts ) return; // copy all attributes of the TextNode in the area from nStart to nEnd SwTxtAttr* pHt; xub_StrLen nAttrStt; const xub_StrLen * pEndIdx; for( USHORT n = 0; n < pHts->Count(); n++ ) { // BP: nAttrStt muss auch bei !pEndIdx gesetzt werden pHt = pHts->GetTextHint(n); nAttrStt = *pHt->GetStart(); // JP: ???? wieso nAttrStt >= nEnd // if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt >= nEnd ) if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt > nEnd ) break; // Flys und Ftn nie kopieren !! BOOL bNextAttr = FALSE; switch( pHt->Which() ) { case RES_TXTATR_FIELD: // keine Felder, .. kopieren ?? if( !bFields ) bNextAttr = TRUE; break; case RES_TXTATR_FLYCNT: case RES_TXTATR_FTN: bNextAttr = TRUE; break; } if( bNextAttr ) continue; // save all attributes that are somehow in this area if ( nStart <= nAttrStt ) { if ( nEnd > nAttrStt // JP: ???? wieso nAttrStt >= nEnd // || (nEnd == nAttrStt && (!pEndIdx || nEnd == pEndIdx->GetIndex())) ) { Add( pHt, nNodeIdx, false ); } } else if ( pEndIdx && nStart < *pEndIdx ) { Add( pHt, nNodeIdx, false ); } } } /*************************************************************************/ // Klasse zum Registrieren der History am Node, Format, HintsArray, ... SwRegHistory::SwRegHistory( SwHistory* pHst ) : SwClient( 0 ) , m_pHistory( pHst ) , m_nNodeIndex( ULONG_MAX ) { _MakeSetWhichIds(); } SwRegHistory::SwRegHistory( SwModify* pRegIn, const SwNode& rNd, SwHistory* pHst ) : SwClient( pRegIn ) , m_pHistory( pHst ) , m_nNodeIndex( rNd.GetIndex() ) { _MakeSetWhichIds(); } SwRegHistory::SwRegHistory( const SwNode& rNd, SwHistory* pHst ) : SwClient( 0 ) , m_pHistory( pHst ) , m_nNodeIndex( rNd.GetIndex() ) { _MakeSetWhichIds(); } void SwRegHistory::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew ) { if ( m_pHistory && ( pOld || pNew ) ) { if ( pNew->Which() < POOLATTR_END ) { m_pHistory->Add( pOld, pNew, m_nNodeIndex ); } else if ( RES_ATTRSET_CHG == pNew->Which() ) { SwHistoryHint* pNewHstr; const SfxItemSet& rSet = *static_cast(pOld)->GetChgSet(); if ( 1 < rSet.Count() ) { pNewHstr = new SwHistorySetAttrSet( rSet, m_nNodeIndex, m_WhichIdSet ); } else { const SfxPoolItem* pItem = SfxItemIter( rSet ).FirstItem(); if ( m_WhichIdSet.Seek_Entry( pItem->Which() ) ) { pNewHstr = new SwHistorySetFmt( pItem, m_nNodeIndex ); } else { pNewHstr = new SwHistoryResetFmt( pItem, m_nNodeIndex ); } } m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() ); } } } void SwRegHistory::AddHint( SwTxtAttr* pHt, const bool bNew ) { m_pHistory->Add( pHt, m_nNodeIndex, bNew ); } bool SwRegHistory::InsertItems( const SfxItemSet& rSet, xub_StrLen const nStart, xub_StrLen const nEnd, SetAttrMode const nFlags ) { if( !rSet.Count() ) return false; SwTxtNode * const pTxtNode = dynamic_cast(const_cast(GetRegisteredIn())); ASSERT(pTxtNode, "SwRegHistory not registered at text node?"); if (!pTxtNode) return false; if ( pTxtNode->GetpSwpHints() && m_pHistory ) { pTxtNode->GetpSwpHints()->Register( this ); } const bool bInserted = pTxtNode->SetAttr( rSet, nStart, nEnd, nFlags ); // Achtung: Durch das Einfuegen eines Attributs kann das Array // geloescht werden!!! Wenn das einzufuegende zunaechst ein vorhandenes // loescht, selbst aber nicht eingefuegt werden braucht, weil die // Absatzattribute identisch sind( -> bForgetAttr in SwpHints::Insert ) if ( pTxtNode->GetpSwpHints() && m_pHistory ) { pTxtNode->GetpSwpHints()->DeRegister(); } if ( m_pHistory && bInserted ) { SwHistoryHint* pNewHstr = new SwHistoryResetAttrSet( rSet, pTxtNode->GetIndex(), nStart, nEnd ); // der NodeIndex kann verschoben sein !! m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() ); } return bInserted; } void SwRegHistory::RegisterInModify( SwModify* pRegIn, const SwNode& rNd ) { if ( m_pHistory && pRegIn ) { pRegIn->Add( this ); m_nNodeIndex = rNd.GetIndex(); _MakeSetWhichIds(); } else if ( m_WhichIdSet.Count() ) { m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() ); } } void SwRegHistory::_MakeSetWhichIds() { if (!m_pHistory) return; if ( m_WhichIdSet.Count() ) { m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() ); } if( GetRegisteredIn() ) { const SfxItemSet* pSet = 0; if( GetRegisteredIn()->ISA( SwCntntNode ) ) { pSet = static_cast( const_cast(GetRegisteredIn()))->GetpSwAttrSet(); } else if ( GetRegisteredIn()->ISA( SwFmt ) ) { pSet = &static_cast( const_cast(GetRegisteredIn()))->GetAttrSet(); } if( pSet && pSet->Count() ) { SfxItemIter aIter( *pSet ); USHORT nW = aIter.FirstItem()->Which(); while( TRUE ) { m_WhichIdSet.Insert( nW ); if( aIter.IsAtEnd() ) break; nW = aIter.NextItem()->Which(); } } } }