diff options
Diffstat (limited to 'sw/source/core/undo/SwUndoPageDesc.cxx')
-rw-r--r-- | sw/source/core/undo/SwUndoPageDesc.cxx | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/sw/source/core/undo/SwUndoPageDesc.cxx b/sw/source/core/undo/SwUndoPageDesc.cxx new file mode 100644 index 000000000000..2b6494003109 --- /dev/null +++ b/sw/source/core/undo/SwUndoPageDesc.cxx @@ -0,0 +1,435 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include <tools/resid.hxx> +#include <doc.hxx> +#include <IDocumentUndoRedo.hxx> +#include <swundo.hxx> +#include <pagedesc.hxx> +#include <SwUndoPageDesc.hxx> +#include <SwRewriter.hxx> +#include <undobj.hxx> +#include <comcore.hrc> +#include <fmtcntnt.hxx> +#include <fmthdft.hxx> + +#ifdef DEBUG +#include <ndindex.hxx> +#endif + + +#ifdef DEBUG +// Pure debug help function to have a quick look at the header/footer attributes. +void DebugHeaderFooterContent( const SwPageDesc& rPageDesc ) +{ + sal_uLong nHeaderMaster = ULONG_MAX; + sal_uLong nHeaderLeft = ULONG_MAX; + sal_uLong nFooterMaster = ULONG_MAX; + sal_uLong nFooterLeft = ULONG_MAX; + + SwFmtHeader& rHead = (SwFmtHeader&)rPageDesc.GetMaster().GetHeader(); + SwFmtFooter& rFoot = (SwFmtFooter&)rPageDesc.GetMaster().GetFooter(); + SwFmtHeader& rLeftHead = (SwFmtHeader&)rPageDesc.GetLeft().GetHeader(); + SwFmtFooter& rLeftFoot = (SwFmtFooter&)rPageDesc.GetLeft().GetFooter(); + if( rHead.IsActive() ) + { + SwFrmFmt* pHeaderFmt = rHead.GetHeaderFmt(); + if( pHeaderFmt ) + { + nHeaderCount = pHeaderFmt->GetClientCount(); + { + int nHeaderCount = 0; + } + const SwFmtCntnt* pCntnt = &pHeaderFmt->GetCntnt(); + if( pCntnt->GetCntntIdx() ) + nHeaderMaster = pCntnt->GetCntntIdx()->GetIndex(); + else + nHeaderMaster = 0; + } + SwFrmFmt* pLeftHeaderFmt = rLeftHead.GetHeaderFmt(); + if( pLeftHeaderFmt ) + { + nLeftHeaderCount = pLeftHeaderFmt->GetClientCount(); + { + int nLeftHeaderCount = 0; + } + const SwFmtCntnt* pLeftCntnt = &pLeftHeaderFmt->GetCntnt(); + if( pLeftCntnt->GetCntntIdx() ) + nHeaderLeft = pLeftCntnt->GetCntntIdx()->GetIndex(); + else + nHeaderLeft = 0; + } + } + if( rFoot.IsActive() ) + { + SwFrmFmt* pFooterFmt = rFoot.GetFooterFmt(); + if( pFooterFmt ) + { + nFooterCount = pFooterFmt->GetClientCount(); + { + int nFooterCount = 0; + } + const SwFmtCntnt* pCntnt = &pFooterFmt->GetCntnt(); + if( pCntnt->GetCntntIdx() ) + nFooterMaster = pCntnt->GetCntntIdx()->GetIndex(); + else + nFooterMaster = 0; + } + SwFrmFmt* pLeftFooterFmt = rLeftFoot.GetFooterFmt(); + if( pLeftFooterFmt ) + { + nLeftFooterCount = pLeftFooterFmt->GetClientCount(); + { + int nLeftFooterCount = 0; + } + const SwFmtCntnt* pLeftCntnt = &pLeftFooterFmt->GetCntnt(); + if( pLeftCntnt->GetCntntIdx() ) + nFooterLeft = pLeftCntnt->GetCntntIdx()->GetIndex(); + else + nFooterLeft = 0; + } + } + int i = 0; + ++i; // To set a breakpoint +} +#endif + +SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc & _aOld, + const SwPageDesc & _aNew, + SwDoc * _pDoc) + : SwUndo( _aOld.GetName() != _aNew.GetName() ? + UNDO_RENAME_PAGEDESC : + UNDO_CHANGE_PAGEDESC ), + aOld(_aOld, _pDoc), aNew(_aNew, _pDoc), pDoc(_pDoc), bExchange( false ) +{ + OSL_ENSURE(0 != pDoc, "no document?"); + +#ifdef DEBUG + DebugHeaderFooterContent( (SwPageDesc&)aOld ); + DebugHeaderFooterContent( (SwPageDesc&)aNew ); +#endif + + /* + The page description changes. + If there are no header/footer content changes like header on/off or change from shared content + to unshared etc., there is no reason to duplicate the content nodes (Crash i55547) + But this happens, this Undo Ctor will destroy the unnecessary duplicate and manipulate the + content pointer of the both page descriptions. + */ + SwPageDesc &rOldDesc = (SwPageDesc&)aOld; + SwPageDesc &rNewDesc = (SwPageDesc&)aNew; + const SwFmtHeader& rOldHead = rOldDesc.GetMaster().GetHeader(); + const SwFmtHeader& rNewHead = rNewDesc.GetMaster().GetHeader(); + const SwFmtFooter& rOldFoot = rOldDesc.GetMaster().GetFooter(); + const SwFmtFooter& rNewFoot = rNewDesc.GetMaster().GetFooter(); + /* bExchange must not be set, if the old page descriptor will stay active. + Two known situations: + #i67735#: renaming a page descriptor + #i67334#: changing the follow style + If header/footer will be activated or deactivated, this undo will not work. + */ + bExchange = ( aOld.GetName() == aNew.GetName() ) && + ( _aOld.GetFollow() == _aNew.GetFollow() ) && + ( rOldHead.IsActive() == rNewHead.IsActive() ) && + ( rOldFoot.IsActive() == rNewFoot.IsActive() ); + if( rOldHead.IsActive() && ( rOldDesc.IsHeaderShared() != rNewDesc.IsHeaderShared() ) ) + bExchange = false; + if( rOldFoot.IsActive() && ( rOldDesc.IsFooterShared() != rNewDesc.IsFooterShared() ) ) + bExchange = false; + if( bExchange ) + { + if( rNewHead.IsActive() ) + { + SwFrmFmt* pFormat = new SwFrmFmt( *rNewHead.GetHeaderFmt() ); + // The Ctor of this object will remove the duplicate! + SwFmtHeader aFmtHeader( pFormat ); + if( !rNewDesc.IsHeaderShared() ) + { + pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetHeader().GetHeaderFmt() ); + // The Ctor of this object will remove the duplicate! + SwFmtHeader aFormatHeader( pFormat ); + } + } + // Same procedure for footers... + if( rNewFoot.IsActive() ) + { + SwFrmFmt* pFormat = new SwFrmFmt( *rNewFoot.GetFooterFmt() ); + // The Ctor of this object will remove the duplicate! + SwFmtFooter aFmtFooter( pFormat ); + if( !rNewDesc.IsFooterShared() ) + { + pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetFooter().GetFooterFmt() ); + // The Ctor of this object will remove the duplicate! + SwFmtFooter aFormatFooter( pFormat ); + } + } + + // After this exchange method the old page description will point to zero, + // the new one will point to the node position of the original content nodes. + ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew ); +#ifdef DEBUG + DebugHeaderFooterContent( (SwPageDesc&)aOld ); + DebugHeaderFooterContent( (SwPageDesc&)aNew ); +#endif + } +} + +SwUndoPageDesc::~SwUndoPageDesc() +{ +} + + +void SwUndoPageDesc::ExchangeContentNodes( SwPageDesc& rSource, SwPageDesc &rDest ) +{ + OSL_ENSURE( bExchange, "You shouldn't do that." ); + const SwFmtHeader& rDestHead = rDest.GetMaster().GetHeader(); + const SwFmtHeader& rSourceHead = rSource.GetMaster().GetHeader(); + if( rDestHead.IsActive() ) + { + // Let the destination page descrition point to the source node position, + // from now on this descriptor is responsible for the content nodes! + const SfxPoolItem* pItem; + rDest.GetMaster().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem ); + SfxPoolItem *pNewItem = pItem->Clone(); + SwFrmFmt* pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt(); +#ifdef DEBUG + const SwFmtCntnt& rSourceCntnt = rSourceHead.GetHeaderFmt()->GetCntnt(); + (void)rSourceCntnt; + const SwFmtCntnt& rDestCntnt = rDestHead.GetHeaderFmt()->GetCntnt(); + (void)rDestCntnt; +#endif + pNewFmt->SetFmtAttr( rSourceHead.GetHeaderFmt()->GetCntnt() ); + delete pNewItem; + + // Let the source page description point to zero node position, + // it loses the responsible and can be destroyed without removing the content nodes. + rSource.GetMaster().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem ); + pNewItem = pItem->Clone(); + pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt(); + pNewFmt->SetFmtAttr( SwFmtCntnt() ); + delete pNewItem; + + if( !rDest.IsHeaderShared() ) + { + // Same procedure for unshared header.. + const SwFmtHeader& rSourceLeftHead = rSource.GetLeft().GetHeader(); + rDest.GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem ); + pNewItem = pItem->Clone(); + pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt(); +#ifdef DEBUG + const SwFmtCntnt& rSourceCntnt1 = rSourceLeftHead.GetHeaderFmt()->GetCntnt(); + (void)rSourceCntnt1; + const SwFmtCntnt& rDestCntnt1 = rDest.GetLeft().GetHeader().GetHeaderFmt()->GetCntnt(); + (void)rDestCntnt1; +#endif + pNewFmt->SetFmtAttr( rSourceLeftHead.GetHeaderFmt()->GetCntnt() ); + delete pNewItem; + rSource.GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem ); + pNewItem = pItem->Clone(); + pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt(); + pNewFmt->SetFmtAttr( SwFmtCntnt() ); + delete pNewItem; + } + } + // Same procedure for footers... + const SwFmtFooter& rDestFoot = rDest.GetMaster().GetFooter(); + const SwFmtFooter& rSourceFoot = rSource.GetMaster().GetFooter(); + if( rDestFoot.IsActive() ) + { + const SfxPoolItem* pItem; + rDest.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem ); + SfxPoolItem *pNewItem = pItem->Clone(); + SwFrmFmt *pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt(); + pNewFmt->SetFmtAttr( rSourceFoot.GetFooterFmt()->GetCntnt() ); + delete pNewItem; + +#ifdef DEBUG + const SwFmtCntnt& rFooterSourceCntnt = rSourceFoot.GetFooterFmt()->GetCntnt(); + (void)rFooterSourceCntnt; + const SwFmtCntnt& rFooterDestCntnt = rDestFoot.GetFooterFmt()->GetCntnt(); + (void)rFooterDestCntnt; +#endif + rSource.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem ); + pNewItem = pItem->Clone(); + pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt(); + pNewFmt->SetFmtAttr( SwFmtCntnt() ); + delete pNewItem; + + if( !rDest.IsFooterShared() ) + { + const SwFmtFooter& rSourceLeftFoot = rSource.GetLeft().GetFooter(); +#ifdef DEBUG + const SwFmtCntnt& rFooterSourceCntnt2 = rSourceLeftFoot.GetFooterFmt()->GetCntnt(); + const SwFmtCntnt& rFooterDestCntnt2 = + rDest.GetLeft().GetFooter().GetFooterFmt()->GetCntnt(); + (void)rFooterSourceCntnt2; + (void)rFooterDestCntnt2; +#endif + rDest.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem ); + pNewItem = pItem->Clone(); + pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt(); + pNewFmt->SetFmtAttr( rSourceLeftFoot.GetFooterFmt()->GetCntnt() ); + delete pNewItem; + rSource.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem ); + pNewItem = pItem->Clone(); + pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt(); + pNewFmt->SetFmtAttr( SwFmtCntnt() ); + delete pNewItem; + } + } +} + +void SwUndoPageDesc::UndoImpl(::sw::UndoRedoContext &) +{ + // Move (header/footer)content node responsibility from new page descriptor to old one again. + if( bExchange ) + ExchangeContentNodes( (SwPageDesc&)aNew, (SwPageDesc&)aOld ); + pDoc->ChgPageDesc(aOld.GetName(), aOld); +} + +void SwUndoPageDesc::RedoImpl(::sw::UndoRedoContext &) +{ + // Move (header/footer)content node responsibility from old page descriptor to new one again. + if( bExchange ) + ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew ); + pDoc->ChgPageDesc(aNew.GetName(), aNew); +} + +SwRewriter SwUndoPageDesc::GetRewriter() const +{ + SwRewriter aResult; + + aResult.AddRule(UNDO_ARG1, aOld.GetName()); + aResult.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS)); + aResult.AddRule(UNDO_ARG3, aNew.GetName()); + + return aResult; +} + +// #116530# +SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc * pNew, + SwDoc * _pDoc) + : SwUndo(UNDO_CREATE_PAGEDESC), pDesc(pNew), aNew(*pNew, _pDoc), + pDoc(_pDoc) +{ + OSL_ENSURE(0 != pDoc, "no document?"); +} + +SwUndoPageDescCreate::~SwUndoPageDescCreate() +{ +} + +void SwUndoPageDescCreate::UndoImpl(::sw::UndoRedoContext &) +{ + // -> #116530# + if (pDesc) + { + aNew = *pDesc; + pDesc = NULL; + } + // <- #116530# + + pDoc->DelPageDesc(aNew.GetName(), sal_True); +} + +void SwUndoPageDescCreate::DoImpl() +{ + SwPageDesc aPageDesc = aNew; + pDoc->MakePageDesc(aNew.GetName(), &aPageDesc, sal_False, sal_True); // #116530# +} + +void SwUndoPageDescCreate::RedoImpl(::sw::UndoRedoContext &) +{ + DoImpl(); +} + +void SwUndoPageDescCreate::RepeatImpl(::sw::RepeatContext &) +{ + ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); + DoImpl(); +} + +SwRewriter SwUndoPageDescCreate::GetRewriter() const +{ + SwRewriter aResult; + + if (pDesc) + aResult.AddRule(UNDO_ARG1, pDesc->GetName()); + else + aResult.AddRule(UNDO_ARG1, aNew.GetName()); + + + return aResult; +} + +SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc & _aOld, + SwDoc * _pDoc) + : SwUndo(UNDO_DELETE_PAGEDESC), aOld(_aOld, _pDoc), pDoc(_pDoc) +{ + OSL_ENSURE(0 != pDoc, "no document?"); +} + +SwUndoPageDescDelete::~SwUndoPageDescDelete() +{ +} + +void SwUndoPageDescDelete::UndoImpl(::sw::UndoRedoContext &) +{ + SwPageDesc aPageDesc = aOld; + pDoc->MakePageDesc(aOld.GetName(), &aPageDesc, sal_False, sal_True); // #116530# +} + +void SwUndoPageDescDelete::DoImpl() +{ + pDoc->DelPageDesc(aOld.GetName(), sal_True); // #116530# +} + +void SwUndoPageDescDelete::RedoImpl(::sw::UndoRedoContext &) +{ + DoImpl(); +} + +void SwUndoPageDescDelete::RepeatImpl(::sw::RepeatContext &) +{ + ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); + DoImpl(); +} + +SwRewriter SwUndoPageDescDelete::GetRewriter() const +{ + SwRewriter aResult; + + aResult.AddRule(UNDO_ARG1, aOld.GetName()); + + return aResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |