diff options
Diffstat (limited to 'sc/source/ui/undo')
-rw-r--r-- | sc/source/ui/undo/areasave.cxx | 231 | ||||
-rw-r--r-- | sc/source/ui/undo/refundo.cxx | 216 | ||||
-rw-r--r-- | sc/source/ui/undo/target.cxx | 48 | ||||
-rw-r--r-- | sc/source/ui/undo/undobase.cxx | 532 | ||||
-rw-r--r-- | sc/source/ui/undo/undoblk.cxx | 2267 | ||||
-rw-r--r-- | sc/source/ui/undo/undoblk2.cxx | 208 | ||||
-rw-r--r-- | sc/source/ui/undo/undoblk3.cxx | 2136 | ||||
-rw-r--r-- | sc/source/ui/undo/undocell.cxx | 1147 | ||||
-rw-r--r-- | sc/source/ui/undo/undodat.cxx | 2235 | ||||
-rw-r--r-- | sc/source/ui/undo/undodraw.cxx | 198 | ||||
-rw-r--r-- | sc/source/ui/undo/undoolk.cxx | 104 | ||||
-rw-r--r-- | sc/source/ui/undo/undorangename.cxx | 117 | ||||
-rw-r--r-- | sc/source/ui/undo/undostyl.cxx | 312 | ||||
-rw-r--r-- | sc/source/ui/undo/undotab.cxx | 1680 | ||||
-rw-r--r-- | sc/source/ui/undo/undoutil.cxx | 137 |
15 files changed, 11568 insertions, 0 deletions
diff --git a/sc/source/ui/undo/areasave.cxx b/sc/source/ui/undo/areasave.cxx new file mode 100644 index 000000000000..fab15bd8a996 --- /dev/null +++ b/sc/source/ui/undo/areasave.cxx @@ -0,0 +1,231 @@ +/* -*- 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_sc.hxx" + +// ----------------------------------------------------------------------- + + + +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/linkmgr.hxx> +#include <tools/debug.hxx> + +#include "areasave.hxx" +#include "arealink.hxx" +#include "document.hxx" + +// ----------------------------------------------------------------------- + +ScAreaLinkSaver::ScAreaLinkSaver( const ScAreaLink& rSource ) : + aFileName ( rSource.GetFile() ), + aFilterName ( rSource.GetFilter() ), + aOptions ( rSource.GetOptions() ), + aSourceArea ( rSource.GetSource() ), + aDestArea ( rSource.GetDestArea() ), + nRefresh ( rSource.GetRefreshDelay() ) // seconds +{ +} + +ScAreaLinkSaver::ScAreaLinkSaver( const ScAreaLinkSaver& rCopy ) : + ScDataObject(), + aFileName ( rCopy.aFileName ), + aFilterName ( rCopy.aFilterName ), + aOptions ( rCopy.aOptions ), + aSourceArea ( rCopy.aSourceArea ), + aDestArea ( rCopy.aDestArea ), + nRefresh ( rCopy.nRefresh ) +{ +} + +ScAreaLinkSaver::~ScAreaLinkSaver() +{ +} + +ScDataObject* ScAreaLinkSaver::Clone() const +{ + return new ScAreaLinkSaver( *this ); +} + +sal_Bool ScAreaLinkSaver::IsEqualSource( const ScAreaLink& rCompare ) const +{ + return ( aFileName == rCompare.GetFile() && + aFilterName == rCompare.GetFilter() && + aOptions == rCompare.GetOptions() && + aSourceArea == rCompare.GetSource() && + nRefresh == rCompare.GetRefreshDelay() ); +} + +sal_Bool ScAreaLinkSaver::IsEqual( const ScAreaLink& rCompare ) const +{ + return ( IsEqualSource( rCompare ) && + aDestArea == rCompare.GetDestArea() ); +} + +void ScAreaLinkSaver::WriteToLink( ScAreaLink& rLink ) const +{ + rLink.SetDestArea( aDestArea ); +} + +void ScAreaLinkSaver::InsertNewLink( ScDocument* pDoc ) const +{ + // (see ScUndoRemoveAreaLink::Undo) + + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); + + if ( pLinkManager && pObjSh ) + { + ScAreaLink* pLink = new ScAreaLink( pObjSh, aFileName, aFilterName, aOptions, + aSourceArea, aDestArea.aStart, nRefresh ); + pLink->SetInCreate( sal_True ); + pLink->SetDestArea( aDestArea ); + pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName, &aFilterName, &aSourceArea ); + pLink->Update(); + pLink->SetInCreate( false ); + } +} + +// ----------------------------------------------------------------------- + +ScAreaLinkSaveCollection::ScAreaLinkSaveCollection() +{ +} + +ScAreaLinkSaveCollection::ScAreaLinkSaveCollection( const ScAreaLinkSaveCollection& rCopy ) : + ScCollection( rCopy ) +{ +} + +ScAreaLinkSaveCollection::~ScAreaLinkSaveCollection() +{ +} + +ScDataObject* ScAreaLinkSaveCollection::Clone() const +{ + return new ScAreaLinkSaveCollection( *this ); +} + +sal_Bool ScAreaLinkSaveCollection::IsEqual( const ScDocument* pDoc ) const +{ + // IsEqual can be checked in sequence. + // Neither ref-update nor removing links will change the order. + + sfx2::LinkManager* pLinkManager = const_cast<ScDocument*>(pDoc)->GetLinkManager(); + if (pLinkManager) + { + sal_uInt16 nPos = 0; + const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks(); + sal_uInt16 nLinkCount = rLinks.Count(); + for (sal_uInt16 i=0; i<nLinkCount; i++) + { + ::sfx2::SvBaseLink* pBase = *rLinks[i]; + if (pBase->ISA(ScAreaLink)) + { + if ( nPos >= GetCount() || !(*this)[nPos]->IsEqual( *(ScAreaLink*)pBase ) ) + return false; + + ++nPos; + } + } + if ( nPos < GetCount() ) + return false; // fewer links in the document than in the save collection + } + + return sal_True; +} + +ScAreaLink* lcl_FindLink( const ::sfx2::SvBaseLinks& rLinks, const ScAreaLinkSaver& rSaver ) +{ + sal_uInt16 nLinkCount = rLinks.Count(); + for (sal_uInt16 i=0; i<nLinkCount; i++) + { + ::sfx2::SvBaseLink* pBase = *rLinks[i]; + if ( pBase->ISA(ScAreaLink) && + rSaver.IsEqualSource( *static_cast<ScAreaLink*>(pBase) ) ) + { + return static_cast<ScAreaLink*>(pBase); // found + } + } + return NULL; // not found +} + +void ScAreaLinkSaveCollection::Restore( ScDocument* pDoc ) const +{ + // The save collection may contain additional entries that are not in the document. + // They must be inserted again. + // Entries from the save collection must be searched via source data, as the order + // of links changes if deleted entries are re-added to the link manager (always at the end). + + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + if (pLinkManager) + { + const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks(); + sal_uInt16 nSaveCount = GetCount(); + for (sal_uInt16 nPos=0; nPos<nSaveCount; nPos++) + { + ScAreaLinkSaver* pSaver = (*this)[nPos]; + ScAreaLink* pLink = lcl_FindLink( rLinks, *pSaver ); + if ( pLink ) + pSaver->WriteToLink( *pLink ); // restore output position + else + pSaver->InsertNewLink( pDoc ); // re-insert deleted link + } + } +} + +ScAreaLinkSaveCollection* ScAreaLinkSaveCollection::CreateFromDoc( const ScDocument* pDoc ) +{ + ScAreaLinkSaveCollection* pColl = NULL; + + sfx2::LinkManager* pLinkManager = const_cast<ScDocument*>(pDoc)->GetLinkManager(); + if (pLinkManager) + { + const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks(); + sal_uInt16 nLinkCount = rLinks.Count(); + for (sal_uInt16 i=0; i<nLinkCount; i++) + { + ::sfx2::SvBaseLink* pBase = *rLinks[i]; + if (pBase->ISA(ScAreaLink)) + { + if (!pColl) + pColl = new ScAreaLinkSaveCollection; + + ScAreaLinkSaver* pSaver = new ScAreaLinkSaver( *(ScAreaLink*)pBase ); + if (!pColl->Insert(pSaver)) + delete pSaver; + } + } + } + + return pColl; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/refundo.cxx b/sc/source/ui/undo/refundo.cxx new file mode 100644 index 000000000000..0376f7c7a9c4 --- /dev/null +++ b/sc/source/ui/undo/refundo.cxx @@ -0,0 +1,216 @@ +/* -*- 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_sc.hxx" + +// ----------------------------------------------------------------------- + + + +// INCLUDE --------------------------------------------------------------- + +#include "refundo.hxx" +#include "undobase.hxx" +#include "document.hxx" +#include "dbcolect.hxx" +#include "rangenam.hxx" +#include "pivot.hxx" +#include "chartarr.hxx" +#include "stlpool.hxx" +#include "conditio.hxx" +#include "detdata.hxx" +#include "prnsave.hxx" +#include "chartlis.hxx" +#include "dpobject.hxx" +#include "areasave.hxx" +#include "unoreflist.hxx" + +// ----------------------------------------------------------------------- + +ScRefUndoData::ScRefUndoData( const ScDocument* pDoc ) : + pUnoRefs( NULL ) +{ + ScDBCollection* pOldDBColl = pDoc->GetDBCollection(); + pDBCollection = pOldDBColl ? new ScDBCollection(*pOldDBColl) : NULL; + + ScRangeName* pOldRanges = ((ScDocument*)pDoc)->GetRangeName(); //! const + pRangeName = pOldRanges ? new ScRangeName(*pOldRanges) : NULL; + + pPrintRanges = pDoc->CreatePrintRangeSaver(); // neu erzeugt + + //! bei Pivot nur Bereiche merken ??? + + ScDPCollection* pOldDP = ((ScDocument*)pDoc)->GetDPCollection(); //! const + pDPCollection = pOldDP ? new ScDPCollection(*pOldDP) : NULL; + + ScConditionalFormatList* pOldCond = pDoc->GetCondFormList(); + pCondFormList = pOldCond ? new ScConditionalFormatList(*pOldCond) : NULL; + + ScDetOpList* pOldDetOp = pDoc->GetDetOpList(); + pDetOpList = pOldDetOp ? new ScDetOpList(*pOldDetOp) : 0; + + ScChartListenerCollection* pOldChartListenerCollection = + pDoc->GetChartListenerCollection(); + pChartListenerCollection = pOldChartListenerCollection ? + new ScChartListenerCollection( *pOldChartListenerCollection ) : NULL; + + pAreaLinks = ScAreaLinkSaveCollection::CreateFromDoc(pDoc); // returns NULL if empty + + const_cast<ScDocument*>(pDoc)->BeginUnoRefUndo(); +} + +ScRefUndoData::~ScRefUndoData() +{ + delete pDBCollection; + delete pRangeName; + delete pPrintRanges; + delete pDPCollection; + delete pCondFormList; + delete pDetOpList; + delete pChartListenerCollection; + delete pAreaLinks; + delete pUnoRefs; +} + +void ScRefUndoData::DeleteUnchanged( const ScDocument* pDoc ) +{ + if (pDBCollection) + { + ScDBCollection* pNewDBColl = pDoc->GetDBCollection(); + if ( pNewDBColl && *pDBCollection == *pNewDBColl ) + DELETEZ(pDBCollection); + } + if (pRangeName) + { + ScRangeName* pNewRanges = ((ScDocument*)pDoc)->GetRangeName(); //! const + if ( pNewRanges && *pRangeName == *pNewRanges ) + DELETEZ(pRangeName); + } + + if (pPrintRanges) + { + ScPrintRangeSaver* pNewRanges = pDoc->CreatePrintRangeSaver(); + if ( pNewRanges && *pPrintRanges == *pNewRanges ) + DELETEZ(pPrintRanges); + delete pNewRanges; + } + + if (pDPCollection) + { + ScDPCollection* pNewDP = ((ScDocument*)pDoc)->GetDPCollection(); //! const + if ( pNewDP && pDPCollection->RefsEqual(*pNewDP) ) + DELETEZ(pDPCollection); + } + + if (pCondFormList) + { + ScConditionalFormatList* pNewCond = pDoc->GetCondFormList(); + if ( pNewCond && *pCondFormList == *pNewCond ) + DELETEZ(pCondFormList); + } + + if (pDetOpList) + { + ScDetOpList* pNewDetOp = pDoc->GetDetOpList(); + if ( pNewDetOp && *pDetOpList == *pNewDetOp ) + DELETEZ(pDetOpList); + } + + if ( pChartListenerCollection ) + { + ScChartListenerCollection* pNewChartListenerCollection = + pDoc->GetChartListenerCollection(); + if ( pNewChartListenerCollection && + *pChartListenerCollection == *pNewChartListenerCollection ) + DELETEZ( pChartListenerCollection ); + } + + if (pAreaLinks) + { + if ( pAreaLinks->IsEqual( pDoc ) ) + DELETEZ(pAreaLinks); + } + + if ( pDoc->HasUnoRefUndo() ) + { + pUnoRefs = const_cast<ScDocument*>(pDoc)->EndUnoRefUndo(); + if ( pUnoRefs && pUnoRefs->IsEmpty() ) + { + DELETEZ( pUnoRefs ); + } + } +} + +void ScRefUndoData::DoUndo( ScDocument* pDoc, sal_Bool bUndoRefFirst ) +{ + if (pDBCollection) + pDoc->SetDBCollection( new ScDBCollection(*pDBCollection) ); + if (pRangeName) + pDoc->SetRangeName( new ScRangeName(*pRangeName) ); + + if (pPrintRanges) + pDoc->RestorePrintRanges(*pPrintRanges); + + if (pDPCollection) + { + ScDPCollection* pDocDP = pDoc->GetDPCollection(); + if (pDocDP) + pDPCollection->WriteRefsTo( *pDocDP ); + } + + if (pCondFormList) + pDoc->SetCondFormList( new ScConditionalFormatList(*pCondFormList) ); + if (pDetOpList) + pDoc->SetDetOpList( new ScDetOpList(*pDetOpList) ); + + // bUndoRefFirst ist bSetChartRangeLists + if ( pChartListenerCollection ) + pDoc->SetChartListenerCollection( new ScChartListenerCollection( + *pChartListenerCollection ), bUndoRefFirst ); + + if (pDBCollection || pRangeName) + { + sal_Bool bOldAutoCalc = pDoc->GetAutoCalc(); + pDoc->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden + pDoc->CompileAll(); + pDoc->SetDirty(); + pDoc->SetAutoCalc( bOldAutoCalc ); + } + + if (pAreaLinks) + pAreaLinks->Restore( pDoc ); + + if ( pUnoRefs ) + pUnoRefs->Undo( pDoc ); +} + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/target.cxx b/sc/source/ui/undo/target.cxx new file mode 100644 index 000000000000..d652e3f8931a --- /dev/null +++ b/sc/source/ui/undo/target.cxx @@ -0,0 +1,48 @@ +/* -*- 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_sc.hxx" + +// System - Includes ----------------------------------------------------- + + + +// INCLUDE --------------------------------------------------------------- + +#include "target.hxx" + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1(ScTabViewTarget, SfxRepeatTarget); + +ScTabViewTarget::~ScTabViewTarget() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx new file mode 100644 index 000000000000..20d38fc9a89a --- /dev/null +++ b/sc/source/ui/undo/undobase.cxx @@ -0,0 +1,532 @@ +/* -*- 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_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <vcl/virdev.hxx> + +#include "undobase.hxx" +#include "refundo.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "undoolk.hxx" +#include "undodraw.hxx" +#include "dbcolect.hxx" +#include "attrib.hxx" +#include "queryparam.hxx" +#include "subtotalparam.hxx" +#include "globstr.hrc" + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1(ScSimpleUndo, SfxUndoAction); +TYPEINIT1(ScBlockUndo, ScSimpleUndo); +TYPEINIT1(ScMoveUndo, ScSimpleUndo); +TYPEINIT1(ScDBFuncUndo, ScSimpleUndo); +TYPEINIT1(ScUndoWrapper, SfxUndoAction); + +// ----------------------------------------------------------------------- + +ScSimpleUndo::ScSimpleUndo( ScDocShell* pDocSh ) : + pDocShell( pDocSh ), + pDetectiveUndo( NULL ) +{ +} + +ScSimpleUndo::~ScSimpleUndo() +{ + delete pDetectiveUndo; +} + +bool ScSimpleUndo::SetViewMarkData( const ScMarkData& rMarkData ) +{ + if ( IsPaintLocked() ) + return false; + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if ( !pViewShell ) + return false; + + pViewShell->SetMarkData( rMarkData ); + return true; +} + +sal_Bool ScSimpleUndo::Merge( SfxUndoAction *pNextAction ) +{ + // Zu jeder Undo-Action kann eine SdrUndoGroup fuer das Aktualisieren + // der Detektiv-Pfeile gehoeren. + // DetectiveRefresh kommt immer hinterher, die SdrUndoGroup ist in + // eine ScUndoDraw Action verpackt. + // Nur beim automatischen Aktualisieren wird AddUndoAction mit + // bTryMerg=sal_True gerufen. + + if ( !pDetectiveUndo && pNextAction->ISA(ScUndoDraw) ) + { + // SdrUndoAction aus der ScUndoDraw Action uebernehmen, + // ScUndoDraw wird dann vom UndoManager geloescht + + ScUndoDraw* pCalcUndo = (ScUndoDraw*)pNextAction; + pDetectiveUndo = pCalcUndo->GetDrawUndo(); + pCalcUndo->ForgetDrawUndo(); + return sal_True; + } + + return false; +} + +void ScSimpleUndo::BeginUndo() +{ + pDocShell->SetInUndo( sal_True ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->HideAllCursors(); // z.B. wegen zusammengefassten Zellen + + // detective updates happened last, must be undone first + if (pDetectiveUndo) + pDetectiveUndo->Undo(); +} + +void ScSimpleUndo::EndUndo() +{ + pDocShell->SetDocumentModified(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->UpdateAutoFillMark(); + pViewShell->UpdateInputHandler(); + pViewShell->ShowAllCursors(); + } + + pDocShell->SetInUndo( false ); +} + +void ScSimpleUndo::BeginRedo() +{ + pDocShell->SetInUndo( sal_True ); //! eigenes Flag fuer Redo? + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->HideAllCursors(); // z.B. wegen zusammengefassten Zellen +} + +void ScSimpleUndo::EndRedo() +{ + if (pDetectiveUndo) + pDetectiveUndo->Redo(); + + pDocShell->SetDocumentModified(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->UpdateAutoFillMark(); + pViewShell->UpdateInputHandler(); + pViewShell->ShowAllCursors(); + } + + pDocShell->SetInUndo( false ); +} + +void ScSimpleUndo::ShowTable( SCTAB nTab ) +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->SetTabNo( nTab ); +} + +void ScSimpleUndo::ShowTable( const ScRange& rRange ) +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + SCTAB nStart = rRange.aStart.Tab(); + SCTAB nEnd = rRange.aEnd.Tab(); + SCTAB nTab = pViewShell->GetViewData()->GetTabNo(); + if ( nTab < nStart || nTab > nEnd ) // wenn nicht im Bereich: + pViewShell->SetTabNo( nStart ); // auf erste des Bereiches + } +} + + +// ----------------------------------------------------------------------- + +ScBlockUndo::ScBlockUndo( ScDocShell* pDocSh, const ScRange& rRange, + ScBlockUndoMode eBlockMode ) : + ScSimpleUndo( pDocSh ), + aBlockRange( rRange ), + eMode( eBlockMode ) +{ + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); +} + +ScBlockUndo::~ScBlockUndo() +{ + DeleteSdrUndoAction( pDrawUndo ); +} + +void ScBlockUndo::BeginUndo() +{ + ScSimpleUndo::BeginUndo(); + EnableDrawAdjust( pDocShell->GetDocument(), false ); +} + +void ScBlockUndo::EndUndo() +{ + if (eMode == SC_UNDO_AUTOHEIGHT) + AdjustHeight(); + + EnableDrawAdjust( pDocShell->GetDocument(), sal_True ); + DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); + + ShowBlock(); + ScSimpleUndo::EndUndo(); +} + +void ScBlockUndo::EndRedo() +{ + if (eMode == SC_UNDO_AUTOHEIGHT) + AdjustHeight(); + + ShowBlock(); + ScSimpleUndo::EndRedo(); +} + +sal_Bool ScBlockUndo::AdjustHeight() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + VirtualDevice aVirtDev; + Fraction aZoomX( 1, 1 ); + Fraction aZoomY = aZoomX; + double nPPTX, nPPTY; + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + ScViewData* pData = pViewShell->GetViewData(); + nPPTX = pData->GetPPTX(); + nPPTY = pData->GetPPTY(); + aZoomX = pData->GetZoomX(); + aZoomY = pData->GetZoomY(); + } + else + { + // Zoom auf 100 lassen + nPPTX = ScGlobal::nScreenPPTX; + nPPTY = ScGlobal::nScreenPPTY; + } + + sal_Bool bRet = pDoc->SetOptimalHeight( aBlockRange.aStart.Row(), aBlockRange.aEnd.Row(), +/*!*/ aBlockRange.aStart.Tab(), 0, &aVirtDev, + nPPTX, nPPTY, aZoomX, aZoomY, false ); + + if (bRet) + pDocShell->PostPaint( 0, aBlockRange.aStart.Row(), aBlockRange.aStart.Tab(), + MAXCOL, MAXROW, aBlockRange.aEnd.Tab(), + PAINT_GRID | PAINT_LEFT ); + + return bRet; +} + +void ScBlockUndo::ShowBlock() +{ + if ( IsPaintLocked() ) + return; + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + ShowTable( aBlockRange ); // bei mehreren Tabs im Range ist jede davon gut + pViewShell->MoveCursorAbs( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(), + SC_FOLLOW_JUMP, false, false ); + SCTAB nTab = pViewShell->GetViewData()->GetTabNo(); + ScRange aRange = aBlockRange; + aRange.aStart.SetTab( nTab ); + aRange.aEnd.SetTab( nTab ); + pViewShell->MarkRange( aRange ); + + // nicht per SetMarkArea an MarkData, wegen evtl. fehlendem Paint + } +} + + +// ----------------------------------------------------------------------- + +ScMoveUndo::ScMoveUndo( ScDocShell* pDocSh, ScDocument* pRefDoc, ScRefUndoData* pRefData, + ScMoveUndoMode eRefMode ) : + ScSimpleUndo( pDocSh ), + pRefUndoDoc( pRefDoc ), + pRefUndoData( pRefData ), + eMode( eRefMode ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + if (pRefUndoData) + pRefUndoData->DeleteUnchanged(pDoc); + pDrawUndo = GetSdrUndoAction( pDoc ); +} + +ScMoveUndo::~ScMoveUndo() +{ + delete pRefUndoData; + delete pRefUndoDoc; + DeleteSdrUndoAction( pDrawUndo ); +} + +void ScMoveUndo::UndoRef() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScRange aRange(0,0,0, MAXCOL,MAXROW,pRefUndoDoc->GetTableCount()-1); + pRefUndoDoc->CopyToDocument( aRange, IDF_FORMULA, false, pDoc, NULL, false ); + if (pRefUndoData) + pRefUndoData->DoUndo( pDoc, (eMode == SC_UNDO_REFFIRST) ); + // HACK: ScDragDropUndo ist der einzige mit REFFIRST. + // Falls nicht, resultiert daraus evtl. ein zu haeufiges Anpassen + // der ChartRefs, nicht schoen, aber auch nicht schlecht.. +} + +void ScMoveUndo::BeginUndo() +{ + ScSimpleUndo::BeginUndo(); + + EnableDrawAdjust( pDocShell->GetDocument(), false ); + + if (pRefUndoDoc && eMode == SC_UNDO_REFFIRST) + UndoRef(); +} + +void ScMoveUndo::EndUndo() +{ + DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); // must also be called when pointer is null + + if (pRefUndoDoc && eMode == SC_UNDO_REFLAST) + UndoRef(); + + EnableDrawAdjust( pDocShell->GetDocument(), sal_True ); + + ScSimpleUndo::EndUndo(); +} + +// ----------------------------------------------------------------------- + +ScDBFuncUndo::ScDBFuncUndo( ScDocShell* pDocSh, const ScRange& rOriginal, SdrUndoAction* pDrawUndo ) : + ScSimpleUndo( pDocSh ), + aOriginalRange( rOriginal ), + mpDrawUndo( pDrawUndo ) +{ + pAutoDBRange = pDocSh->GetOldAutoDBRange(); +} + +ScDBFuncUndo::~ScDBFuncUndo() +{ + DeleteSdrUndoAction( mpDrawUndo ); + delete pAutoDBRange; +} + +void ScDBFuncUndo::SetDrawUndoAction( SdrUndoAction* pDrawUndo ) +{ + DeleteSdrUndoAction( mpDrawUndo ); + mpDrawUndo = pDrawUndo; +} + +void ScDBFuncUndo::BeginUndo() +{ + ScSimpleUndo::BeginUndo(); + DoSdrUndoAction( mpDrawUndo, pDocShell->GetDocument() ); +} + +void ScDBFuncUndo::EndUndo() +{ + ScSimpleUndo::EndUndo(); + + if ( pAutoDBRange ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTab = pDoc->GetVisibleTab(); + ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab); + if (pNoNameData ) + { + SCCOL nRangeX1; + SCROW nRangeY1; + SCCOL nRangeX2; + SCROW nRangeY2; + SCTAB nRangeTab; + pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + + *pNoNameData = *pAutoDBRange; + + if ( pAutoDBRange->HasAutoFilter() ) + { + // restore AutoFilter buttons + pAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + pDoc->ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO ); + pDocShell->PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID ); + } + } + } +} + +void ScDBFuncUndo::BeginRedo() +{ + RedoSdrUndoAction( mpDrawUndo ); + if ( pAutoDBRange ) + { + // move the database range to this function's position again (see ScDocShell::GetDBData) + + ScDocument* pDoc = pDocShell->GetDocument(); + ScDBData* pNoNameData = pDoc->GetAnonymousDBData(aOriginalRange.aStart.Tab()); + if ( pNoNameData ) + { + + SCCOL nRangeX1; + SCROW nRangeY1; + SCCOL nRangeX2; + SCROW nRangeY2; + SCTAB nRangeTab; + pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + + pNoNameData->SetSortParam( ScSortParam() ); + pNoNameData->SetQueryParam( ScQueryParam() ); + pNoNameData->SetSubTotalParam( ScSubTotalParam() ); + + pNoNameData->SetArea( aOriginalRange.aStart.Tab(), + aOriginalRange.aStart.Col(), aOriginalRange.aStart.Row(), + aOriginalRange.aEnd.Col(), aOriginalRange.aEnd.Row() ); + + pNoNameData->SetByRow( sal_True ); + pNoNameData->SetAutoFilter( false ); + // header is always set with the operation in redo + } + } + + ScSimpleUndo::BeginRedo(); +} + +void ScDBFuncUndo::EndRedo() +{ + ScSimpleUndo::EndRedo(); +} + +// ----------------------------------------------------------------------- + +ScUndoWrapper::ScUndoWrapper( SfxUndoAction* pUndo ) : + pWrappedUndo( pUndo ) +{ +} + +ScUndoWrapper::~ScUndoWrapper() +{ + delete pWrappedUndo; +} + +void ScUndoWrapper::ForgetWrappedUndo() +{ + pWrappedUndo = NULL; // don't delete in dtor - pointer must be stored outside +} + +String ScUndoWrapper::GetComment() const +{ + if (pWrappedUndo) + return pWrappedUndo->GetComment(); + else + return String(); +} + +String ScUndoWrapper::GetRepeatComment(SfxRepeatTarget& rTarget) const +{ + if (pWrappedUndo) + return pWrappedUndo->GetRepeatComment(rTarget); + else + return String(); +} + +sal_uInt16 ScUndoWrapper::GetId() const +{ + if (pWrappedUndo) + return pWrappedUndo->GetId(); + else + return 0; +} + +sal_Bool ScUndoWrapper::IsLinked() +{ + if (pWrappedUndo) + return pWrappedUndo->IsLinked(); + else + return false; +} + +void ScUndoWrapper::SetLinked( sal_Bool bIsLinked ) +{ + if (pWrappedUndo) + pWrappedUndo->SetLinked(bIsLinked); +} + +sal_Bool ScUndoWrapper::Merge( SfxUndoAction* pNextAction ) +{ + if (pWrappedUndo) + return pWrappedUndo->Merge(pNextAction); + else + return false; +} + +void ScUndoWrapper::Undo() +{ + if (pWrappedUndo) + pWrappedUndo->Undo(); +} + +void ScUndoWrapper::Redo() +{ + if (pWrappedUndo) + pWrappedUndo->Redo(); +} + +void ScUndoWrapper::Repeat(SfxRepeatTarget& rTarget) +{ + if (pWrappedUndo) + pWrappedUndo->Repeat(rTarget); +} + +sal_Bool ScUndoWrapper::CanRepeat(SfxRepeatTarget& rTarget) const +{ + if (pWrappedUndo) + return pWrappedUndo->CanRepeat(rTarget); + else + return false; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx new file mode 100644 index 000000000000..0e59c0a35f92 --- /dev/null +++ b/sc/source/ui/undo/undoblk.cxx @@ -0,0 +1,2267 @@ +/* -*- 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_sc.hxx" + + + +//------------------------------------------------------------------ + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <vcl/virdev.hxx> +#include <vcl/waitobj.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/justifyitem.hxx> +#include <sfx2/app.hxx> + +#include "undoblk.hxx" +#include "undoutil.hxx" +#include "document.hxx" +#include "patattr.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "rangenam.hxx" +#include "rangeutl.hxx" +#include "dbcolect.hxx" +#include "stlpool.hxx" +#include "stlsheet.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "target.hxx" +#include "docpool.hxx" +#include "docfunc.hxx" +#include "attrib.hxx" +#include "chgtrack.hxx" +#include "transobj.hxx" +#include "refundo.hxx" +#include "undoolk.hxx" +#include "clipparam.hxx" +#include "sc.hrc" + +#include <set> + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1(ScUndoInsertCells, SfxUndoAction); +TYPEINIT1(ScUndoDeleteCells, SfxUndoAction); +TYPEINIT1(ScUndoDeleteMulti, SfxUndoAction); +TYPEINIT1(ScUndoCut, ScBlockUndo); +TYPEINIT1(ScUndoPaste, SfxUndoAction); +TYPEINIT1(ScUndoDragDrop, SfxUndoAction); +TYPEINIT1(ScUndoListNames, SfxUndoAction); +TYPEINIT1(ScUndoUseScenario, SfxUndoAction); +TYPEINIT1(ScUndoSelectionStyle, SfxUndoAction); +TYPEINIT1(ScUndoEnterMatrix, ScBlockUndo); +TYPEINIT1(ScUndoIndent, ScBlockUndo); +TYPEINIT1(ScUndoTransliterate, ScBlockUndo); +TYPEINIT1(ScUndoClearItems, ScBlockUndo); +TYPEINIT1(ScUndoRemoveBreaks, SfxUndoAction); +TYPEINIT1(ScUndoRemoveMerge, ScBlockUndo); +TYPEINIT1(ScUndoBorder, ScBlockUndo); + + + +// To Do: +/*A*/ // SetOptimalHeight auf Dokument, wenn keine View +/*B*/ // gelinkte Tabellen +/*C*/ // ScArea +//? // spaeter mal pruefen + + +// ----------------------------------------------------------------------- +// +// Zellen einfuegen +// Zeilen einfuegen +// einzeln oder Block +// + +ScUndoInsertCells::ScUndoInsertCells( ScDocShell* pNewDocShell, + const ScRange& rRange, SCTAB nNewCount, SCTAB* pNewTabs, SCTAB* pNewScenarios, + InsCellCmd eNewCmd, ScDocument* pUndoDocument, ScRefUndoData* pRefData, + sal_Bool bNewPartOfPaste ) : + ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ), + aEffRange( rRange ), + nCount( nNewCount ), + pTabs( pNewTabs ), + pScenarios( pNewScenarios ), + eCmd( eNewCmd ), + bPartOfPaste( bNewPartOfPaste ), + pPasteUndo( NULL ) +{ + if (eCmd == INS_INSROWS) // ganze Zeilen? + { + aEffRange.aStart.SetCol(0); + aEffRange.aEnd.SetCol(MAXCOL); + } + + if (eCmd == INS_INSCOLS) // ganze Spalten? + { + aEffRange.aStart.SetRow(0); + aEffRange.aEnd.SetRow(MAXROW); + } + + SetChangeTrack(); +} + +ScUndoInsertCells::~ScUndoInsertCells() +{ + delete pPasteUndo; + delete []pTabs; + delete []pScenarios; +} + +String ScUndoInsertCells::GetComment() const +{ + return ScGlobal::GetRscString( pPasteUndo ? STR_UNDO_PASTE : STR_UNDO_INSERTCELLS ); +} + +sal_Bool ScUndoInsertCells::Merge( SfxUndoAction* pNextAction ) +{ + // If a paste undo action has already been added, append (detective) action there. + if ( pPasteUndo ) + return pPasteUndo->Merge( pNextAction ); + + if ( bPartOfPaste && pNextAction->ISA( ScUndoWrapper ) ) + { + ScUndoWrapper* pWrapper = (ScUndoWrapper*)pNextAction; + SfxUndoAction* pWrappedAction = pWrapper->GetWrappedUndo(); + if ( pWrappedAction && pWrappedAction->ISA( ScUndoPaste ) ) + { + // Store paste action if this is part of paste with inserting cells. + // A list action isn't used because Repeat wouldn't work (insert wrong cells). + + pPasteUndo = pWrappedAction; + pWrapper->ForgetWrappedUndo(); // pWrapper is deleted by UndoManager + return sal_True; + } + } + + // Call base class for detective handling + return ScMoveUndo::Merge( pNextAction ); +} + +void ScUndoInsertCells::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + { + pChangeTrack->AppendInsert( aEffRange ); + nEndChangeAction = pChangeTrack->GetActionMax(); + } + else + nEndChangeAction = 0; +} + +void ScUndoInsertCells::DoChange( const sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB i; + + if ( bUndo ) + { + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nEndChangeAction, nEndChangeAction ); + } + else + SetChangeTrack(); + + // refresh of merged cells has to be after inserting/deleting + + switch (eCmd) + { + case INS_INSROWS: + case INS_CELLSDOWN: + for( i=0; i<nCount; i++ ) + { + if (bUndo) + pDoc->DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i], + aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1)); + else + pDoc->InsertRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i], + aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1)); + } + break; + case INS_INSCOLS: + case INS_CELLSRIGHT: + for( i=0; i<nCount; i++ ) + { + if (bUndo) + pDoc->DeleteCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i], + aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1)); + else + pDoc->InsertCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i], + aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1)); + } + break; + default: + { + // added to avoid warnings + } + } + + ScRange aWorkRange( aEffRange ); + if ( eCmd == INS_CELLSRIGHT ) // only "shift right" requires refresh of the moved area + aWorkRange.aEnd.SetCol(MAXCOL); + for( i=0; i<nCount; i++ ) + { + if ( pDoc->HasAttrib( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i], + aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i], HASATTR_MERGED ) ) + { + SCCOL nEndCol = aWorkRange.aEnd.Col(); + SCROW nEndRow = aWorkRange.aEnd.Row(); + pDoc->ExtendMerge( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), nEndCol, nEndRow, pTabs[i], sal_True ); + } + } + +//? Undo fuer herausgeschobene Attribute ? + + sal_uInt16 nPaint = PAINT_GRID; + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + switch (eCmd) + { + case INS_INSROWS: + nPaint |= PAINT_LEFT; + aWorkRange.aEnd.SetRow(MAXROW); + break; + case INS_CELLSDOWN: + for( i=0; i<nCount; i++ ) + { + aWorkRange.aEnd.SetRow(MAXROW); + if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i] )) + { + aWorkRange.aStart.SetCol(0); + aWorkRange.aEnd.SetCol(MAXCOL); + nPaint |= PAINT_LEFT; + } + } + break; + case INS_INSCOLS: + nPaint |= PAINT_TOP; // obere Leiste + case INS_CELLSRIGHT: + for( i=0; i<nCount; i++ ) + { + aWorkRange.aEnd.SetCol(MAXCOL); // bis ganz nach rechts + if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i]) ) + { // AdjustDraw zeichnet PAINT_TOP nicht, + aWorkRange.aStart.SetCol(0); // daher so geloest + aWorkRange.aEnd.SetRow(MAXROW); + nPaint |= PAINT_LEFT; + } + } + break; + default: + { + // added to avoid warnings + } + } + + for( i=0; i<nCount; i++ ) + { + pDocShell->PostPaint( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i], + aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i]+pScenarios[i], nPaint ); + } + pDocShell->PostDataChanged(); + if (pViewShell) + pViewShell->CellContentChanged(); +} + +void ScUndoInsertCells::Undo() +{ + if ( pPasteUndo ) + pPasteUndo->Undo(); // undo paste first + + WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference + BeginUndo(); + DoChange( sal_True ); + EndUndo(); +} + +void ScUndoInsertCells::Redo() +{ + WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference + BeginRedo(); + DoChange( false ); + EndRedo(); + + if ( pPasteUndo ) + pPasteUndo->Redo(); // redo paste last +} + +void ScUndoInsertCells::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + if ( pPasteUndo ) + { + // Repeat for paste with inserting cells is handled completely + // by the Paste undo action + + pPasteUndo->Repeat( rTarget ); + } + else + ((ScTabViewTarget&)rTarget).GetViewShell()->InsertCells( eCmd, sal_True ); + } +} + +sal_Bool ScUndoInsertCells::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Zellen loeschen +// Zeilen loeschen +// einzeln oder Block +// + +ScUndoDeleteCells::ScUndoDeleteCells( ScDocShell* pNewDocShell, + const ScRange& rRange, SCTAB nNewCount, SCTAB* pNewTabs, SCTAB* pNewScenarios, + DelCellCmd eNewCmd, ScDocument* pUndoDocument, ScRefUndoData* pRefData ) : + ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ), + aEffRange( rRange ), + nCount( nNewCount ), + pTabs( pNewTabs ), + pScenarios( pNewScenarios ), + eCmd( eNewCmd ) +{ + if (eCmd == DEL_DELROWS) // gaze Zeilen? + { + aEffRange.aStart.SetCol(0); + aEffRange.aEnd.SetCol(MAXCOL); + } + + if (eCmd == DEL_DELCOLS) // ganze Spalten? + { + aEffRange.aStart.SetRow(0); + aEffRange.aEnd.SetRow(MAXROW); + } + + SetChangeTrack(); +} + +ScUndoDeleteCells::~ScUndoDeleteCells() +{ + delete []pTabs; + delete []pScenarios; +} + +String ScUndoDeleteCells::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_DELETECELLS ); // "Loeschen" +} + +void ScUndoDeleteCells::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->AppendDeleteRange( aEffRange, pRefUndoDoc, + nStartChangeAction, nEndChangeAction ); + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoDeleteCells::DoChange( const sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB i; + + if ( bUndo ) + { + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + } + else + SetChangeTrack(); + + // Ausfuehren + switch (eCmd) + { + case DEL_DELROWS: + case DEL_CELLSUP: + for( i=0; i<nCount; i++ ) + { + if (bUndo) + pDoc->InsertRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i], + aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1)); + else + pDoc->DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i], + aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1)); + } + break; + case DEL_DELCOLS: + case DEL_CELLSLEFT: + for( i=0; i<nCount; i++ ) + { + if (bUndo) + pDoc->InsertCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i], + aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1)); + else + pDoc->DeleteCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i], + aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1)); + } + break; + default: + { + // added to avoid warnings + } + } + + // bei Undo Referenzen wiederherstellen + for( i=0; i<nCount && bUndo; i++ ) + { + pRefUndoDoc->CopyToDocument( aEffRange.aStart.Col(), aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Col(), aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i], + IDF_ALL | IDF_NOCAPTIONS, false, pDoc ); + } + + ScRange aWorkRange( aEffRange ); + if ( eCmd == DEL_CELLSLEFT ) // only "shift left" requires refresh of the moved area + aWorkRange.aEnd.SetCol(MAXCOL); + + for( i=0; i<nCount; i++ ) + { + if ( pDoc->HasAttrib( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i], + aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i], HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + { + // #i51445# old merge flag attributes must be deleted also for single cells, + // not only for whole columns/rows + + if ( !bUndo ) + { + if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT ) + aWorkRange.aEnd.SetCol(MAXCOL); + if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP ) + aWorkRange.aEnd.SetRow(MAXROW); + ScMarkData aMarkData; + aMarkData.SelectOneTable( aWorkRange.aStart.Tab() ); + ScPatternAttr aPattern( pDoc->GetPool() ); + aPattern.GetItemSet().Put( ScMergeFlagAttr() ); + pDoc->ApplyPatternArea( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), + aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), + aMarkData, aPattern ); + } + + SCCOL nEndCol = aWorkRange.aEnd.Col(); + SCROW nEndRow = aWorkRange.aEnd.Row(); + pDoc->ExtendMerge( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), nEndCol, nEndRow, pTabs[i], sal_True ); + } + } + + // Zeichnen + sal_uInt16 nPaint = PAINT_GRID; + switch (eCmd) + { + case DEL_DELROWS: + nPaint |= PAINT_LEFT; + aWorkRange.aEnd.SetRow(MAXROW); + break; + case DEL_CELLSUP: + for( i=0; i<nCount; i++ ) + { + aWorkRange.aEnd.SetRow(MAXROW); + if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i] )) + { + aWorkRange.aStart.SetCol(0); + aWorkRange.aEnd.SetCol(MAXCOL); + nPaint |= PAINT_LEFT; + } + } + break; + case DEL_DELCOLS: + nPaint |= PAINT_TOP; // obere Leiste + case DEL_CELLSLEFT: + for( i=0; i<nCount; i++ ) + { + aWorkRange.aEnd.SetCol(MAXCOL); // bis ganz nach rechts + if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i] ) ) + { + aWorkRange.aStart.SetCol(0); + aWorkRange.aEnd.SetRow(MAXROW); + nPaint |= PAINT_LEFT; + } + } + break; + default: + { + // added to avoid warnings + } + } + + for( i=0; i<nCount; i++ ) + { + pDocShell->PostPaint( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i], + aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i]+pScenarios[i], nPaint, SC_PF_LINES ); + } + // Markierung erst nach EndUndo + + pDocShell->PostDataChanged(); + // CellContentChanged kommt mit der Markierung +} + +void ScUndoDeleteCells::Undo() +{ + WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference + BeginUndo(); + DoChange( sal_True ); + EndUndo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); + + // Markierung erst nach EndUndo + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + for( SCTAB i=0; i<nCount; i++ ) + { + pViewShell->MarkRange( ScRange(aEffRange.aStart.Col(), aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Col(), aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i]) ); + } + } +} + +void ScUndoDeleteCells::Redo() +{ + WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference + BeginRedo(); + DoChange( false); + EndRedo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->DoneBlockMode(); // aktuelle weg +} + +void ScUndoDeleteCells::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->DeleteCells( eCmd, sal_True ); +} + +sal_Bool ScUndoDeleteCells::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Zellen loeschen auf Mehrfachselektion +// + +ScUndoDeleteMulti::ScUndoDeleteMulti( ScDocShell* pNewDocShell, + sal_Bool bNewRows, sal_Bool bNeedsRefresh, SCTAB nNewTab, + const SCCOLROW* pRng, SCCOLROW nRngCnt, + ScDocument* pUndoDocument, ScRefUndoData* pRefData ) : + ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ), + bRows( bNewRows ), + bRefresh( bNeedsRefresh ), + nTab( nNewTab ), + nRangeCnt( nRngCnt ) +{ + pRanges = new SCCOLROW[ 2 * nRangeCnt ]; + memcpy(pRanges,pRng,nRangeCnt*2*sizeof(SCCOLROW)); + SetChangeTrack(); +} + +ScUndoDeleteMulti::~ScUndoDeleteMulti() +{ + delete [] pRanges; +} + +String ScUndoDeleteMulti::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_DELETECELLS ); // wie DeleteCells +} + +void ScUndoDeleteMulti::DoChange() const +{ + SCCOL nStartCol; + SCROW nStartRow; + sal_uInt16 nPaint; + if (bRows) + { + nStartCol = 0; + nStartRow = static_cast<SCROW>(pRanges[0]); + nPaint = PAINT_GRID | PAINT_LEFT; + } + else + { + nStartCol = static_cast<SCCOL>(pRanges[0]); + nStartRow = 0; + nPaint = PAINT_GRID | PAINT_TOP; + } + + if ( bRefresh ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + SCCOL nEndCol = MAXCOL; + SCROW nEndRow = MAXROW; + pDoc->RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER ); + pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, sal_True ); + } + + pDocShell->PostPaint( nStartCol, nStartRow, nTab, MAXCOL, MAXROW, nTab, nPaint ); + pDocShell->PostDataChanged(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->CellContentChanged(); + + ShowTable( nTab ); +} + +void ScUndoDeleteMulti::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + { + nStartChangeAction = pChangeTrack->GetActionMax() + 1; + ScRange aRange( 0, 0, nTab, 0, 0, nTab ); + if ( bRows ) + aRange.aEnd.SetCol( MAXCOL ); + else + aRange.aEnd.SetRow( MAXROW ); + // rueckwaerts loeschen + SCCOLROW* pOneRange = &pRanges[2*nRangeCnt]; + for ( SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++ ) + { + SCCOLROW nEnd = *(--pOneRange); + SCCOLROW nStart = *(--pOneRange); + if ( bRows ) + { + aRange.aStart.SetRow( nStart ); + aRange.aEnd.SetRow( nEnd ); + } + else + { + aRange.aStart.SetCol( static_cast<SCCOL>(nStart) ); + aRange.aEnd.SetCol( static_cast<SCCOL>(nEnd) ); + } + sal_uLong nDummyStart; + pChangeTrack->AppendDeleteRange( aRange, pRefUndoDoc, + nDummyStart, nEndChangeAction ); + } + } + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoDeleteMulti::Undo() +{ + WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + SCCOLROW* pOneRange; + SCCOLROW nRangeNo; + + // rueckwaerts geloescht -> vorwaerts einfuegen + pOneRange = pRanges; + for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) + { + SCCOLROW nStart = *(pOneRange++); + SCCOLROW nEnd = *(pOneRange++); + if (bRows) + pDoc->InsertRow( 0,nTab, MAXCOL,nTab, nStart,static_cast<SCSIZE>(nEnd-nStart+1) ); + else + pDoc->InsertCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) ); + } + + pOneRange = pRanges; + for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) + { + SCCOLROW nStart = *(pOneRange++); + SCCOLROW nEnd = *(pOneRange++); + if (bRows) + pRefUndoDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,false,pDoc ); + else + pRefUndoDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab, + static_cast<SCCOL>(nEnd),MAXROW,nTab, IDF_ALL,false,pDoc ); + } + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + + DoChange(); + + //! Markierung wieder einzeichnen + //! geht im Moment nicht, da keine Daten fuer Markierung vorhanden! + + EndUndo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); +} + +void ScUndoDeleteMulti::Redo() +{ + WaitObject aWait( pDocShell->GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + // rueckwaerts loeschen + SCCOLROW* pOneRange = &pRanges[2*nRangeCnt]; + for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) + { + SCCOLROW nEnd = *(--pOneRange); + SCCOLROW nStart = *(--pOneRange); + if (bRows) + pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, nStart,static_cast<SCSIZE>(nEnd-nStart+1) ); + else + pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) ); + } + + SetChangeTrack(); + + DoChange(); + +//! Markierung loeschen, derzeit unnoetig (s.o.) +//! ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); +//! if (pViewShell) +//! DoneBlockMode(); + + EndRedo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); +} + +void ScUndoDeleteMulti::Repeat(SfxRepeatTarget& rTarget) +{ + // DeleteCells, falls einfache Selektion + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->DeleteCells( DEL_DELROWS, sal_True ); +} + +sal_Bool ScUndoDeleteMulti::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Ausschneiden (Cut) +// + +ScUndoCut::ScUndoCut( ScDocShell* pNewDocShell, + ScRange aRange, ScAddress aOldEnd, const ScMarkData& rMark, + ScDocument* pNewUndoDoc ) : + ScBlockUndo( pNewDocShell, ScRange(aRange.aStart, aOldEnd), SC_UNDO_AUTOHEIGHT ), + aMarkData( rMark ), + pUndoDoc( pNewUndoDoc ), + aExtendedRange( aRange ) +{ + SetChangeTrack(); +} + +ScUndoCut::~ScUndoCut() +{ + delete pUndoDoc; +} + +String ScUndoCut::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_CUT ); // "Ausschneiden" +} + +void ScUndoCut::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc, + nStartChangeAction, nEndChangeAction, SC_CACM_CUT ); + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoCut::DoChange( const sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + sal_uInt16 nExtFlags = 0; + + // do not undo/redo objects and note captions, they are handled via drawing undo + sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS; + + if (bUndo) // nur bei Undo + { + // all sheets - CopyToDocument skips those that don't exist in pUndoDoc + SCTAB nTabCount = pDoc->GetTableCount(); + ScRange aCopyRange = aExtendedRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pUndoDoc->CopyToDocument( aCopyRange, nUndoFlags, false, pDoc ); + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + } + else // nur bei Redo + { + pDocShell->UpdatePaintExt( nExtFlags, aExtendedRange ); + pDoc->DeleteArea( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(), + aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), aMarkData, nUndoFlags ); + SetChangeTrack(); + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if ( !( (pViewShell) && pViewShell->AdjustBlockHeight() ) ) +/*A*/ pDocShell->PostPaint( aExtendedRange, PAINT_GRID, nExtFlags ); + + if ( !bUndo ) // draw redo after updating row heights + RedoSdrUndoAction( pDrawUndo ); //! include in ScBlockUndo? + + pDocShell->PostDataChanged(); + if (pViewShell) + pViewShell->CellContentChanged(); +} + +void ScUndoCut::Undo() +{ + BeginUndo(); + DoChange( sal_True ); + EndUndo(); +} + +void ScUndoCut::Redo() +{ + BeginRedo(); + ScDocument* pDoc = pDocShell->GetDocument(); + EnableDrawAdjust( pDoc, false ); //! include in ScBlockUndo? + DoChange( false ); + EnableDrawAdjust( pDoc, sal_True ); //! include in ScBlockUndo? + EndRedo(); +} + +void ScUndoCut::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->CutToClip( NULL, sal_True ); +} + +sal_Bool ScUndoCut::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Einfuegen (Paste) +// + +ScUndoPaste::ScUndoPaste( ScDocShell* pNewDocShell, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, + const ScMarkData& rMark, + ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, + sal_uInt16 nNewFlags, + ScRefUndoData* pRefData, + void* /* pFill1 */, void* /* pFill2 */, void* /* pFill3 */, + sal_Bool bRedoIsFilled, const ScUndoPasteOptions* pOptions ) : + ScBlockUndo( pNewDocShell, ScRange( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), SC_UNDO_SIMPLE ), + aMarkData( rMark ), + pUndoDoc( pNewUndoDoc ), + pRedoDoc( pNewRedoDoc ), + nFlags( nNewFlags ), + pRefUndoData( pRefData ), + pRefRedoData( NULL ), + bRedoFilled( bRedoIsFilled ) +{ + // pFill1,pFill2,pFill3 are there so the ctor calls for simple paste (without cutting) + // don't have to be changed and branched for 641. + // They can be removed later. + + if ( !aMarkData.IsMarked() ) // no cell marked: + aMarkData.SetMarkArea( aBlockRange ); // mark paste block + + if ( pRefUndoData ) + pRefUndoData->DeleteUnchanged( pDocShell->GetDocument() ); + + if ( pOptions ) + aPasteOptions = *pOptions; // used only for Repeat + + SetChangeTrack(); +} + +ScUndoPaste::~ScUndoPaste() +{ + delete pUndoDoc; + delete pRedoDoc; + delete pRefUndoData; + delete pRefRedoData; +} + +String ScUndoPaste::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_PASTE ); // "Einfuegen" +} + +void ScUndoPaste::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack && (nFlags & IDF_CONTENTS) ) + pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc, + nStartChangeAction, nEndChangeAction, SC_CACM_PASTE ); + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoPaste::DoChange( const sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + // RefUndoData for redo is created before first undo + // (with DeleteUnchanged after the DoUndo call) + sal_Bool bCreateRedoData = ( bUndo && pRefUndoData && !pRefRedoData ); + if ( bCreateRedoData ) + pRefRedoData = new ScRefUndoData( pDoc ); + + ScRefUndoData* pWorkRefData = bUndo ? pRefUndoData : pRefRedoData; + + // fuer Undo immer alle oder keine Inhalte sichern + sal_uInt16 nUndoFlags = IDF_NONE; + if (nFlags & IDF_CONTENTS) + nUndoFlags |= IDF_CONTENTS; + if (nFlags & IDF_ATTRIB) + nUndoFlags |= IDF_ATTRIB; + + // do not undo/redo objects and note captions, they are handled via drawing undo + (nUndoFlags &= ~IDF_OBJECTS) |= IDF_NOCAPTIONS; + + sal_Bool bPaintAll = false; + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + // marking is in ScBlockUndo... + ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockRange ); + + SCTAB nTabCount = pDoc->GetTableCount(); + if ( bUndo && !bRedoFilled ) + { + if (!pRedoDoc) + { + sal_Bool bColInfo = ( aBlockRange.aStart.Row()==0 && aBlockRange.aEnd.Row()==MAXROW ); + sal_Bool bRowInfo = ( aBlockRange.aStart.Col()==0 && aBlockRange.aEnd.Col()==MAXCOL ); + + pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); + pRedoDoc->InitUndoSelected( pDoc, aMarkData, bColInfo, bRowInfo ); + } + // read "redo" data from the document in the first undo + // all sheets - CopyToDocument skips those that don't exist in pRedoDoc + ScRange aCopyRange = aBlockRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pDoc->CopyToDocument( aCopyRange, nUndoFlags, false, pRedoDoc ); + bRedoFilled = sal_True; + } + + sal_uInt16 nExtFlags = 0; + pDocShell->UpdatePaintExt( nExtFlags, aBlockRange ); + + aMarkData.MarkToMulti(); + pDoc->DeleteSelection( nUndoFlags, aMarkData ); + aMarkData.MarkToSimple(); + + SCTAB nFirstSelected = aMarkData.GetFirstSelected(); + ScRange aTabSelectRange = aBlockRange; + SCTAB nTab; + + if ( !bUndo && pRedoDoc ) // Redo: UndoToDocument before handling RefData + { + aTabSelectRange.aStart.SetTab( nFirstSelected ); + aTabSelectRange.aEnd.SetTab( nFirstSelected ); + pRedoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, false, pDoc ); + for (nTab=0; nTab<nTabCount; nTab++) + if (nTab != nFirstSelected && aMarkData.GetTableSelect(nTab)) + { + aTabSelectRange.aStart.SetTab( nTab ); + aTabSelectRange.aEnd.SetTab( nTab ); + pRedoDoc->CopyToDocument( aTabSelectRange, nUndoFlags, false, pDoc ); + } + } + + if (pWorkRefData) + { + pWorkRefData->DoUndo( pDoc, sal_True ); // sal_True = bSetChartRangeLists for SetChartListenerCollection + if ( pDoc->RefreshAutoFilter( 0,0, MAXCOL,MAXROW, aBlockRange.aStart.Tab() ) ) + bPaintAll = sal_True; + } + + if ( bCreateRedoData && pRefRedoData ) + pRefRedoData->DeleteUnchanged( pDoc ); + + if (bUndo) // Undo: UndoToDocument after handling RefData + { + aTabSelectRange.aStart.SetTab( nFirstSelected ); + aTabSelectRange.aEnd.SetTab( nFirstSelected ); + pUndoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, false, pDoc ); + for (nTab=0; nTab<nTabCount; nTab++) + if (nTab != nFirstSelected && aMarkData.GetTableSelect(nTab)) + { + aTabSelectRange.aStart.SetTab( nTab ); + aTabSelectRange.aEnd.SetTab( nTab ); + pUndoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, false, pDoc ); + } + } + + if ( bUndo ) + { + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + } + else + SetChangeTrack(); + + ScRange aDrawRange( aBlockRange ); + pDoc->ExtendMerge( aDrawRange, sal_True ); // only needed for single sheet (text/rtf etc.) + sal_uInt16 nPaint = PAINT_GRID; + if (bPaintAll) + { + aDrawRange.aStart.SetCol(0); + aDrawRange.aStart.SetRow(0); + aDrawRange.aEnd.SetCol(MAXCOL); + aDrawRange.aEnd.SetRow(MAXROW); + nPaint |= PAINT_TOP | PAINT_LEFT; +/*A*/ if (pViewShell) + pViewShell->AdjustBlockHeight(false); + } + else + { + if ( aBlockRange.aStart.Row() == 0 && aBlockRange.aEnd.Row() == MAXROW ) // ganze Spalte + { + nPaint |= PAINT_TOP; + aDrawRange.aEnd.SetCol(MAXCOL); + } + if ( aBlockRange.aStart.Col() == 0 && aBlockRange.aEnd.Col() == MAXCOL ) // ganze Zeile + { + nPaint |= PAINT_LEFT; + aDrawRange.aEnd.SetRow(MAXROW); + } +/*A*/ if ((pViewShell) && pViewShell->AdjustBlockHeight(false)) + { + aDrawRange.aStart.SetCol(0); + aDrawRange.aStart.SetRow(0); + aDrawRange.aEnd.SetCol(MAXCOL); + aDrawRange.aEnd.SetRow(MAXROW); + nPaint |= PAINT_LEFT; + } + pDocShell->UpdatePaintExt( nExtFlags, aDrawRange ); + } + + if ( !bUndo ) // draw redo after updating row heights + RedoSdrUndoAction( pDrawUndo ); //! include in ScBlockUndo? + + pDocShell->PostPaint( aDrawRange, nPaint, nExtFlags ); + + pDocShell->PostDataChanged(); + if (pViewShell) + pViewShell->CellContentChanged(); +} + +void ScUndoPaste::Undo() +{ + BeginUndo(); + DoChange( sal_True ); + ShowTable( aBlockRange ); + EndUndo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); +} + +void ScUndoPaste::Redo() +{ + BeginRedo(); + ScDocument* pDoc = pDocShell->GetDocument(); + EnableDrawAdjust( pDoc, false ); //! include in ScBlockUndo? + DoChange( false ); + EnableDrawAdjust( pDoc, sal_True ); //! include in ScBlockUndo? + EndRedo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); +} + +void ScUndoPaste::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell* pViewSh = ((ScTabViewTarget&)rTarget).GetViewShell(); + ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pViewSh->GetActiveWin() ); + if (pOwnClip) + { + // keep a reference in case the clipboard is changed during PasteFromClip + com::sun::star::uno::Reference<com::sun::star::datatransfer::XTransferable> aOwnClipRef( pOwnClip ); + pViewSh->PasteFromClip( nFlags, pOwnClip->GetDocument(), + aPasteOptions.nFunction, aPasteOptions.bSkipEmpty, aPasteOptions.bTranspose, + aPasteOptions.bAsLink, aPasteOptions.eMoveMode, IDF_NONE, + sal_True ); // allow warning dialog + } + } +} + +sal_Bool ScUndoPaste::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Verschieben/Kopieren (Drag & Drop) +// + +ScUndoDragDrop::ScUndoDragDrop( ScDocShell* pNewDocShell, + const ScRange& rRange, ScAddress aNewDestPos, sal_Bool bNewCut, + ScDocument* pUndoDocument, ScRefUndoData* pRefData, sal_Bool bScenario ) : + ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFFIRST ), + aSrcRange( rRange ), + bCut( bNewCut ), + bKeepScenarioFlags( bScenario ) +{ + ScAddress aDestEnd(aNewDestPos); + aDestEnd.IncRow(aSrcRange.aEnd.Row() - aSrcRange.aStart.Row()); + aDestEnd.IncCol(aSrcRange.aEnd.Col() - aSrcRange.aStart.Col()); + aDestEnd.IncTab(aSrcRange.aEnd.Tab() - aSrcRange.aStart.Tab()); + + sal_Bool bIncludeFiltered = bCut; + if ( !bIncludeFiltered ) + { + // find number of non-filtered rows + SCROW nPastedCount = pDocShell->GetDocument()->CountNonFilteredRows( + aSrcRange.aStart.Row(), aSrcRange.aEnd.Row(), aSrcRange.aStart.Tab()); + + if ( nPastedCount == 0 ) + nPastedCount = 1; + aDestEnd.SetRow( aNewDestPos.Row() + nPastedCount - 1 ); + } + + aDestRange.aStart = aNewDestPos; + aDestRange.aEnd = aDestEnd; + + SetChangeTrack(); +} + +ScUndoDragDrop::~ScUndoDragDrop() +{ +} + +String ScUndoDragDrop::GetComment() const +{ // "Verschieben" : "Kopieren" + return bCut ? + ScGlobal::GetRscString( STR_UNDO_MOVE ) : + ScGlobal::GetRscString( STR_UNDO_COPY ); +} + +void ScUndoDragDrop::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + { + if ( bCut ) + { + nStartChangeAction = pChangeTrack->GetActionMax() + 1; + pChangeTrack->AppendMove( aSrcRange, aDestRange, pRefUndoDoc ); + nEndChangeAction = pChangeTrack->GetActionMax(); + } + else + pChangeTrack->AppendContentRange( aDestRange, pRefUndoDoc, + nStartChangeAction, nEndChangeAction ); + } + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoDragDrop::PaintArea( ScRange aRange, sal_uInt16 nExtFlags ) const +{ + sal_uInt16 nPaint = PAINT_GRID; + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + ScDocument* pDoc = pDocShell->GetDocument(); + + if (pViewShell) + { + VirtualDevice aVirtDev; + ScViewData* pViewData = pViewShell->GetViewData(); + + if ( pDoc->SetOptimalHeight( aRange.aStart.Row(), aRange.aEnd.Row(), + aRange.aStart.Tab(), 0, &aVirtDev, + pViewData->GetPPTX(), pViewData->GetPPTY(), + pViewData->GetZoomX(), pViewData->GetZoomY(), + false ) ) + { + aRange.aStart.SetCol(0); + aRange.aEnd.SetCol(MAXCOL); + aRange.aEnd.SetRow(MAXROW); + nPaint |= PAINT_LEFT; + } + } + + if ( bKeepScenarioFlags ) + { + // Szenarien mitkopiert -> auch Szenario-Rahmen painten + aRange.aStart.SetCol(0); + aRange.aStart.SetRow(0); + aRange.aEnd.SetCol(MAXCOL); + aRange.aEnd.SetRow(MAXROW); + } + + // column/row info (width/height) included if whole columns/rows were copied + if ( aSrcRange.aStart.Col() == 0 && aSrcRange.aEnd.Col() == MAXCOL ) + { + nPaint |= PAINT_LEFT; + aRange.aEnd.SetRow(MAXROW); + } + if ( aSrcRange.aStart.Row() == 0 && aSrcRange.aEnd.Row() == MAXROW ) + { + nPaint |= PAINT_TOP; + aRange.aEnd.SetCol(MAXCOL); + } + + pDocShell->PostPaint( aRange, nPaint, nExtFlags ); +} + + +void ScUndoDragDrop::DoUndo( ScRange aRange ) const +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + +//? DB-Areas vor Daten, damit bei ExtendMerge die Autofilter-Knoepfe stimmen + + ScRange aPaintRange = aRange; + pDoc->ExtendMerge( aPaintRange ); // before deleting + + sal_uInt16 nExtFlags = 0; + pDocShell->UpdatePaintExt( nExtFlags, aPaintRange ); + + // do not undo objects and note captions, they are handled via drawing undo + sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS; + + pDoc->DeleteAreaTab( aRange, nUndoFlags ); + pRefUndoDoc->CopyToDocument( aRange, nUndoFlags, false, pDoc ); + if ( pDoc->HasAttrib( aRange, HASATTR_MERGED ) ) + pDoc->ExtendMerge( aRange, sal_True ); + + aPaintRange.aEnd.SetCol( Max( aPaintRange.aEnd.Col(), aRange.aEnd.Col() ) ); + aPaintRange.aEnd.SetRow( Max( aPaintRange.aEnd.Row(), aRange.aEnd.Row() ) ); + + pDocShell->UpdatePaintExt( nExtFlags, aPaintRange ); + PaintArea( aPaintRange, nExtFlags ); +} + +void ScUndoDragDrop::Undo() +{ + BeginUndo(); + DoUndo(aDestRange); + if (bCut) + DoUndo(aSrcRange); + EndUndo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); +} + +void ScUndoDragDrop::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); + + EnableDrawAdjust( pDoc, false ); //! include in ScBlockUndo? + + // do not undo/redo objects and note captions, they are handled via drawing undo + sal_uInt16 nRedoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS; + + /* TODO: Redoing note captions is quite tricky due to the fact that a + helper clip document is used. While (re-)pasting the contents to the + destination area, the original pointers to the captions created while + dropping have to be restored. A simple CopyFromClip() would create new + caption objects that are not tracked by drawing undo, and the captions + restored by drawing redo would live without cell note objects pointing + to them. So, first, CopyToClip() and CopyFromClip() are called without + cloning the caption objects. This leads to cell notes pointing to the + wrong captions from source area that will be removed by drawing redo + later. Second, the pointers to the new captions have to be restored. + Sadly, currently these pointers are not stored anywhere but in the list + of drawing undo actions. */ + + SCTAB nTab; + ScMarkData aSourceMark; + for (nTab=aSrcRange.aStart.Tab(); nTab<=aSrcRange.aEnd.Tab(); nTab++) + aSourceMark.SelectTable( nTab, sal_True ); + + // do not clone objects and note captions into clipdoc (see above) + ScClipParam aClipParam(aSrcRange, bCut); + pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bKeepScenarioFlags, false, false); + + if (bCut) + { + ScRange aSrcPaintRange = aSrcRange; + pDoc->ExtendMerge( aSrcPaintRange ); // before deleting + sal_uInt16 nExtFlags = 0; + pDocShell->UpdatePaintExt( nExtFlags, aSrcPaintRange ); + pDoc->DeleteAreaTab( aSrcRange, nRedoFlags ); + PaintArea( aSrcPaintRange, nExtFlags ); + } + + ScMarkData aDestMark; + for (nTab=aDestRange.aStart.Tab(); nTab<=aDestRange.aEnd.Tab(); nTab++) + aDestMark.SelectTable( nTab, sal_True ); + + sal_Bool bIncludeFiltered = bCut; + // TODO: restore old note captions instead of cloning new captions... + pDoc->CopyFromClip( aDestRange, aDestMark, IDF_ALL & ~IDF_OBJECTS, NULL, pClipDoc, sal_True, false, bIncludeFiltered ); + + if (bCut) + for (nTab=aSrcRange.aStart.Tab(); nTab<=aSrcRange.aEnd.Tab(); nTab++) + pDoc->RefreshAutoFilter( aSrcRange.aStart.Col(), aSrcRange.aStart.Row(), + aSrcRange.aEnd.Col(), aSrcRange.aEnd.Row(), nTab ); + + // skipped rows and merged cells don't mix + if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() ) + pDocShell->GetDocFunc().UnmergeCells( aDestRange, false, sal_True ); + + for (nTab=aDestRange.aStart.Tab(); nTab<=aDestRange.aEnd.Tab(); nTab++) + { + SCCOL nEndCol = aDestRange.aEnd.Col(); + SCROW nEndRow = aDestRange.aEnd.Row(); + pDoc->ExtendMerge( aDestRange.aStart.Col(), aDestRange.aStart.Row(), + nEndCol, nEndRow, nTab, sal_True ); + PaintArea( ScRange( aDestRange.aStart.Col(), aDestRange.aStart.Row(), nTab, + nEndCol, nEndRow, nTab ), 0 ); + } + + SetChangeTrack(); + + delete pClipDoc; + ShowTable( aDestRange.aStart.Tab() ); + + RedoSdrUndoAction( pDrawUndo ); //! include in ScBlockUndo? + EnableDrawAdjust( pDoc, sal_True ); //! include in ScBlockUndo? + + EndRedo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); +} + +void ScUndoDragDrop::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoDragDrop::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // geht nicht +} + + +// ----------------------------------------------------------------------- +// +// Liste der Bereichsnamen einfuegen +// (Einfuegen|Name|Einfuegen =>[Liste]) +// + +ScUndoListNames::ScUndoListNames( ScDocShell* pNewDocShell, const ScRange& rRange, + ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc ) : + ScBlockUndo( pNewDocShell, rRange, SC_UNDO_AUTOHEIGHT ), + pUndoDoc( pNewUndoDoc ), + pRedoDoc( pNewRedoDoc ) +{ +} + +ScUndoListNames::~ScUndoListNames() +{ + delete pUndoDoc; + delete pRedoDoc; +} + +String ScUndoListNames::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_LISTNAMES ); +} + +void ScUndoListNames::DoChange( ScDocument* pSrcDoc ) const +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + pDoc->DeleteAreaTab( aBlockRange, IDF_ALL ); + pSrcDoc->CopyToDocument( aBlockRange, IDF_ALL, false, pDoc ); + pDocShell->PostPaint( aBlockRange, PAINT_GRID ); + pDocShell->PostDataChanged(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->CellContentChanged(); +} + +void ScUndoListNames::Undo() +{ + BeginUndo(); + DoChange(pUndoDoc); + EndUndo(); +} + +void ScUndoListNames::Redo() +{ + BeginRedo(); + DoChange(pRedoDoc); + EndRedo(); +} + +void ScUndoListNames::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->InsertNameList(); +} + +sal_Bool ScUndoListNames::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Szenario anwenden +// (Extras|Szenarien) +// + +ScUndoUseScenario::ScUndoUseScenario( ScDocShell* pNewDocShell, + const ScMarkData& rMark, +/*C*/ const ScArea& rDestArea, + ScDocument* pNewUndoDoc, + const String& rNewName ) : + ScSimpleUndo( pNewDocShell ), + pUndoDoc( pNewUndoDoc ), + aMarkData( rMark ), + aName( rNewName ) +{ + aRange.aStart.SetCol(rDestArea.nColStart); + aRange.aStart.SetRow(rDestArea.nRowStart); + aRange.aStart.SetTab(rDestArea.nTab); + aRange.aEnd.SetCol(rDestArea.nColEnd); + aRange.aEnd.SetRow(rDestArea.nRowEnd); + aRange.aEnd.SetTab(rDestArea.nTab); +} + +ScUndoUseScenario::~ScUndoUseScenario() +{ + delete pUndoDoc; +} + +String ScUndoUseScenario::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_USESCENARIO ); +} + +void ScUndoUseScenario::Undo() +{ + BeginUndo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->DoneBlockMode(); + pViewShell->InitOwnBlockMode(); + } + + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->DeleteSelection( IDF_ALL, aMarkData ); + pUndoDoc->CopyToDocument( aRange, IDF_ALL, sal_True, pDoc, &aMarkData ); + + // Szenario-Tabellen + sal_Bool bFrame = false; + SCTAB nTab = aRange.aStart.Tab(); + SCTAB nEndTab = nTab; + while ( pUndoDoc->HasTable(nEndTab+1) && pUndoDoc->IsScenario(nEndTab+1) ) + ++nEndTab; + for (SCTAB i = nTab+1; i<=nEndTab; i++) + { + // Flags immer + String aComment; + Color aColor; + sal_uInt16 nScenFlags; + pUndoDoc->GetScenarioData( i, aComment, aColor, nScenFlags ); + pDoc->SetScenarioData( i, aComment, aColor, nScenFlags ); + sal_Bool bActive = pUndoDoc->IsActiveScenario( i ); + pDoc->SetActiveScenario( i, bActive ); + // Bei Zurueckkopier-Szenarios auch Inhalte + if ( nScenFlags & SC_SCENARIO_TWOWAY ) + { + pDoc->DeleteAreaTab( 0,0, MAXCOL,MAXROW, i, IDF_ALL ); + pUndoDoc->CopyToDocument( 0,0,i, MAXCOL,MAXROW,i, IDF_ALL,false, pDoc ); + } + if ( nScenFlags & SC_SCENARIO_SHOWFRAME ) + bFrame = sal_True; + } + + // Wenn sichtbare Rahmen, dann alles painten + if (bFrame) + pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_EXTRAS ); + else + pDocShell->PostPaint( aRange, PAINT_GRID | PAINT_EXTRAS ); + pDocShell->PostDataChanged(); + if (pViewShell) + pViewShell->CellContentChanged(); + + ShowTable( aRange.aStart.Tab() ); + + EndUndo(); +} + +void ScUndoUseScenario::Redo() +{ + SCTAB nTab = aRange.aStart.Tab(); + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->SetTabNo( nTab ); + pViewShell->DoneBlockMode(); + pViewShell->InitOwnBlockMode(); + } + + pDocShell->UseScenario( nTab, aName, false ); + + EndRedo(); +} + +void ScUndoUseScenario::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + String aTemp = aName; + ((ScTabViewTarget&)rTarget).GetViewShell()->UseScenario(aTemp); + } +} + +sal_Bool ScUndoUseScenario::CanRepeat(SfxRepeatTarget& rTarget) const +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScViewData* pViewData = ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData(); + return !pViewData->GetDocument()->IsScenario( pViewData->GetTabNo() ); + } + return false; +} + + +// ----------------------------------------------------------------------- +// +// Vorlage anwenden +// (Format|Vorlagenkatalog) +// + +ScUndoSelectionStyle::ScUndoSelectionStyle( ScDocShell* pNewDocShell, + const ScMarkData& rMark, + const ScRange& rRange, + const String& rName, + ScDocument* pNewUndoDoc ) : + ScSimpleUndo( pNewDocShell ), + aMarkData( rMark ), + pUndoDoc( pNewUndoDoc ), + aStyleName( rName ), + aRange( rRange ) +{ + aMarkData.MarkToMulti(); +} + +ScUndoSelectionStyle::~ScUndoSelectionStyle() +{ + delete pUndoDoc; +} + +String ScUndoSelectionStyle::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_APPLYCELLSTYLE ); +} + +void ScUndoSelectionStyle::DoChange( const sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + SetViewMarkData( aMarkData ); + + ScRange aWorkRange( aRange ); + if ( pDoc->HasAttrib( aWorkRange, HASATTR_MERGED ) ) // zusammengefasste Zellen? + pDoc->ExtendMerge( aWorkRange, sal_True ); + + sal_uInt16 nExtFlags = 0; + pDocShell->UpdatePaintExt( nExtFlags, aWorkRange ); + + if (bUndo) // bei Undo alte Daten wieder reinschubsen + { + SCTAB nTabCount = pDoc->GetTableCount(); + ScRange aCopyRange = aWorkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pUndoDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData ); + } + else // bei Redo Style wieder zuweisen + { + ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool(); + ScStyleSheet* pStyleSheet = + (ScStyleSheet*) pStlPool->Find( aStyleName, SFX_STYLE_FAMILY_PARA ); + if (!pStyleSheet) + { + OSL_FAIL("StyleSheet not found"); + return; + } + pDoc->ApplySelectionStyle( *pStyleSheet, aMarkData ); + } + + pDocShell->UpdatePaintExt( nExtFlags, aWorkRange ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if ( !( (pViewShell) && pViewShell->AdjustBlockHeight() ) ) +/*A*/ pDocShell->PostPaint( aWorkRange, PAINT_GRID | PAINT_EXTRAS, nExtFlags ); + + ShowTable( aWorkRange.aStart.Tab() ); +} + +void ScUndoSelectionStyle::Undo() +{ + BeginUndo(); + DoChange( sal_True ); + EndUndo(); +} + +void ScUndoSelectionStyle::Redo() +{ + BeginRedo(); + DoChange( false ); + EndRedo(); +} + +void ScUndoSelectionStyle::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool(); + ScStyleSheet* pStyleSheet = (ScStyleSheet*) pStlPool-> + Find( aStyleName, SFX_STYLE_FAMILY_PARA ); + if (!pStyleSheet) + { + OSL_FAIL("StyleSheet not found"); + return; + } + + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + rViewShell.SetStyleSheetToMarked( pStyleSheet, sal_True ); + } +} + +sal_Bool ScUndoSelectionStyle::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +sal_uInt16 ScUndoSelectionStyle::GetId() const +{ + return STR_UNDO_APPLYCELLSTYLE; +} + + +// ----------------------------------------------------------------------- +// +// Matrix-Formel eingeben +// + +ScUndoEnterMatrix::ScUndoEnterMatrix( ScDocShell* pNewDocShell, const ScRange& rArea, + ScDocument* pNewUndoDoc, const String& rForm ) : + ScBlockUndo( pNewDocShell, rArea, SC_UNDO_SIMPLE ), + pUndoDoc( pNewUndoDoc ), + aFormula( rForm ) +{ + SetChangeTrack(); +} + +ScUndoEnterMatrix::~ScUndoEnterMatrix() +{ + delete pUndoDoc; +} + +String ScUndoEnterMatrix::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_ENTERMATRIX ); +} + +void ScUndoEnterMatrix::SetChangeTrack() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc, + nStartChangeAction, nEndChangeAction ); + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoEnterMatrix::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + pDoc->DeleteAreaTab( aBlockRange, IDF_ALL & ~IDF_NOTE ); + pUndoDoc->CopyToDocument( aBlockRange, IDF_ALL & ~IDF_NOTE, false, pDoc ); + pDocShell->PostPaint( aBlockRange, PAINT_GRID ); + pDocShell->PostDataChanged(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->CellContentChanged(); + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + + EndUndo(); +} + +void ScUndoEnterMatrix::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + ScMarkData aDestMark; + aDestMark.SelectOneTable( aBlockRange.aStart.Tab() ); + aDestMark.SetMarkArea( aBlockRange ); + + pDoc->InsertMatrixFormula( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(), + aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), + aDestMark, aFormula ); +// pDocShell->PostPaint( aBlockRange, PAINT_GRID ); // nicht noetig ??? + + SetChangeTrack(); + + EndRedo(); +} + +void ScUndoEnterMatrix::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + String aTemp = aFormula; + ((ScTabViewTarget&)rTarget).GetViewShell()->EnterMatrix(aTemp); + } +} + +sal_Bool ScUndoEnterMatrix::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// ----------------------------------------------------------------------- +// +// Einzug vermindern / erhoehen +// + +ScRange lcl_GetMultiMarkRange( const ScMarkData& rMark ) +{ + DBG_ASSERT( rMark.IsMultiMarked(), "wrong mark type" ); + + ScRange aRange; + rMark.GetMultiMarkArea( aRange ); + return aRange; +} + +ScUndoIndent::ScUndoIndent( ScDocShell* pNewDocShell, const ScMarkData& rMark, + ScDocument* pNewUndoDoc, sal_Bool bIncrement ) : + ScBlockUndo( pNewDocShell, lcl_GetMultiMarkRange(rMark), SC_UNDO_AUTOHEIGHT ), + aMarkData( rMark ), + pUndoDoc( pNewUndoDoc ), + bIsIncrement( bIncrement ) +{ +} + +ScUndoIndent::~ScUndoIndent() +{ + delete pUndoDoc; +} + +String ScUndoIndent::GetComment() const +{ + sal_uInt16 nId = bIsIncrement ? STR_UNDO_INC_INDENT : STR_UNDO_DEC_INDENT; + return ScGlobal::GetRscString( nId ); +} + +void ScUndoIndent::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + ScRange aCopyRange = aBlockRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pUndoDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData ); + pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + EndUndo(); +} + +void ScUndoIndent::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->ChangeSelectionIndent( bIsIncrement, aMarkData ); + pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + EndRedo(); +} + +void ScUndoIndent::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->ChangeIndent( bIsIncrement ); +} + +sal_Bool ScUndoIndent::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// ----------------------------------------------------------------------- +// +// Transliteration for cells +// + +ScUndoTransliterate::ScUndoTransliterate( ScDocShell* pNewDocShell, const ScMarkData& rMark, + ScDocument* pNewUndoDoc, sal_Int32 nType ) : + ScBlockUndo( pNewDocShell, lcl_GetMultiMarkRange(rMark), SC_UNDO_AUTOHEIGHT ), + aMarkData( rMark ), + pUndoDoc( pNewUndoDoc ), + nTransliterationType( nType ) +{ +} + +ScUndoTransliterate::~ScUndoTransliterate() +{ + delete pUndoDoc; +} + +String ScUndoTransliterate::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_TRANSLITERATE ); +} + +void ScUndoTransliterate::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + ScRange aCopyRange = aBlockRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pUndoDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, sal_True, pDoc, &aMarkData ); + pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + EndUndo(); +} + +void ScUndoTransliterate::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->TransliterateText( aMarkData, nTransliterationType ); + pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + EndRedo(); +} + +void ScUndoTransliterate::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->TransliterateText( nTransliterationType ); +} + +sal_Bool ScUndoTransliterate::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// ----------------------------------------------------------------------- +// +// einzelne Items per Which-IDs aus Bereich loeschen +// + +ScUndoClearItems::ScUndoClearItems( ScDocShell* pNewDocShell, const ScMarkData& rMark, + ScDocument* pNewUndoDoc, const sal_uInt16* pW ) : + ScBlockUndo( pNewDocShell, lcl_GetMultiMarkRange(rMark), SC_UNDO_AUTOHEIGHT ), + aMarkData( rMark ), + pUndoDoc( pNewUndoDoc ), + pWhich( NULL ) +{ + DBG_ASSERT( pW, "ScUndoClearItems: Which-Pointer ist 0" ); + + sal_uInt16 nCount = 0; + while ( pW[nCount] ) + ++nCount; + pWhich = new sal_uInt16[nCount+1]; + for (sal_uInt16 i=0; i<=nCount; i++) + pWhich[i] = pW[i]; +} + +ScUndoClearItems::~ScUndoClearItems() +{ + delete pUndoDoc; + delete pWhich; +} + +String ScUndoClearItems::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_DELETECONTENTS ); +} + +void ScUndoClearItems::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + pUndoDoc->CopyToDocument( aBlockRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData ); + pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + EndUndo(); +} + +void ScUndoClearItems::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->ClearSelectionItems( pWhich, aMarkData ); + pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + EndRedo(); +} + +void ScUndoClearItems::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScViewData* pViewData = ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData(); + ScDocFunc aFunc(*pViewData->GetDocShell()); + aFunc.ClearItems( pViewData->GetMarkData(), pWhich, false ); + } +} + +sal_Bool ScUndoClearItems::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// ----------------------------------------------------------------------- +// +// Alle Umbrueche einer Tabelle loeschen +// + +ScUndoRemoveBreaks::ScUndoRemoveBreaks( ScDocShell* pNewDocShell, + SCTAB nNewTab, ScDocument* pNewUndoDoc ) : + ScSimpleUndo( pNewDocShell ), + nTab( nNewTab ), + pUndoDoc( pNewUndoDoc ) +{ +} + +ScUndoRemoveBreaks::~ScUndoRemoveBreaks() +{ + delete pUndoDoc; +} + +String ScUndoRemoveBreaks::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_REMOVEBREAKS ); +} + +void ScUndoRemoveBreaks::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + pUndoDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, false, pDoc ); + if (pViewShell) + pViewShell->UpdatePageBreakData( sal_True ); + pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); + + EndUndo(); +} + +void ScUndoRemoveBreaks::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + pDoc->RemoveManualBreaks(nTab); + pDoc->UpdatePageBreaks(nTab); + if (pViewShell) + pViewShell->UpdatePageBreakData( sal_True ); + pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); + + EndRedo(); +} + +void ScUndoRemoveBreaks::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + rViewShell.RemoveManualBreaks(); + } +} + +sal_Bool ScUndoRemoveBreaks::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// ----------------------------------------------------------------------- +// +// Zusammenfassung aufheben (fuer einen ganzen Bereich) +// + +ScUndoRemoveMerge::ScUndoRemoveMerge( ScDocShell* pNewDocShell, + const ScCellMergeOption& rOption, ScDocument* pNewUndoDoc ) : + ScBlockUndo( pNewDocShell, rOption.getFirstSingleRange(), SC_UNDO_SIMPLE ), + maOption(rOption), + pUndoDoc( pNewUndoDoc ) +{ +} + +ScUndoRemoveMerge::~ScUndoRemoveMerge() +{ + delete pUndoDoc; +} + +String ScUndoRemoveMerge::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_REMERGE ); // "Zusammenfassung aufheben" +} + +void ScUndoRemoveMerge::Undo() +{ + using ::std::set; + + SetCurTab(); + BeginUndo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + ScDocument* pDoc = pDocShell->GetDocument(); + for (set<SCTAB>::const_iterator itr = maOption.maTabs.begin(), itrEnd = maOption.maTabs.end(); + itr != itrEnd; ++itr) + { + // There is no need to extend merge area because it's already been extended. + ScRange aRange = maOption.getSingleRange(*itr); + pDoc->DeleteAreaTab(aRange, IDF_ATTRIB); + pUndoDoc->CopyToDocument(aRange, IDF_ATTRIB, false, pDoc); + + bool bDidPaint = false; + if ( pViewShell ) + { + pViewShell->SetTabNo(*itr); + bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow); + } + if (!bDidPaint) + ScUndoUtil::PaintMore(pDocShell, aRange); + } + + EndUndo(); +} + +void ScUndoRemoveMerge::Redo() +{ + using ::std::set; + + SetCurTab(); + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + for (set<SCTAB>::const_iterator itr = maOption.maTabs.begin(), itrEnd = maOption.maTabs.end(); + itr != itrEnd; ++itr) + { + SCTAB nTab = *itr; + // There is no need to extend merge area because it's already been extended. + ScRange aRange = maOption.getSingleRange(nTab); + + // ausfuehren + + const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE ); + ScPatternAttr aPattern( pDoc->GetPool() ); + aPattern.GetItemSet().Put( rDefAttr ); + pDoc->ApplyPatternAreaTab( maOption.mnStartCol, maOption.mnStartRow, + maOption.mnEndCol, maOption.mnEndRow, nTab, + aPattern ); + + pDoc->RemoveFlagsTab( maOption.mnStartCol, maOption.mnStartRow, + maOption.mnEndCol, maOption.mnEndRow, nTab, + SC_MF_HOR | SC_MF_VER ); + + pDoc->ExtendMerge(aRange, true, false); + + // Paint + + sal_Bool bDidPaint = false; + if ( pViewShell ) + { + pViewShell->SetTabNo(nTab); + bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow); + } + if (!bDidPaint) + ScUndoUtil::PaintMore(pDocShell, aRange); + } + + EndRedo(); +} + +void ScUndoRemoveMerge::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->RemoveMerge(); +} + +sal_Bool ScUndoRemoveMerge::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +void ScUndoRemoveMerge::SetCurTab() +{ + SCTAB nCurTab = pDocShell->GetCurTab(); + aBlockRange.aStart.SetTab(nCurTab); + aBlockRange.aEnd.SetTab(nCurTab); +} + +// ----------------------------------------------------------------------- +// +// nur Umrandung setzen, per ScRangeList (StarOne) +// + +ScRange lcl_TotalRange( const ScRangeList& rRanges ) +{ + ScRange aTotal; + if ( !rRanges.empty() ) + { + aTotal = *rRanges[ 0 ]; + for ( size_t i = 1, nCount = rRanges.size(); i < nCount; ++i ) + { + ScRange aRange = *rRanges[ i ]; + if (aRange.aStart.Col() < aTotal.aStart.Col()) aTotal.aStart.SetCol(aRange.aStart.Col()); + if (aRange.aStart.Row() < aTotal.aStart.Row()) aTotal.aStart.SetRow(aRange.aStart.Row()); + if (aRange.aStart.Tab() < aTotal.aStart.Tab()) aTotal.aStart.SetTab(aRange.aStart.Tab()); + if (aRange.aEnd.Col() > aTotal.aEnd.Col() ) aTotal.aEnd.SetCol( aRange.aEnd.Col() ); + if (aRange.aEnd.Row() > aTotal.aEnd.Row() ) aTotal.aEnd.SetRow( aRange.aEnd.Row() ); + if (aRange.aEnd.Tab() > aTotal.aEnd.Tab() ) aTotal.aEnd.SetTab(aRange.aEnd.Tab() ); + } + } + return aTotal; +} + +ScUndoBorder::ScUndoBorder( ScDocShell* pNewDocShell, + const ScRangeList& rRangeList, ScDocument* pNewUndoDoc, + const SvxBoxItem& rNewOuter, const SvxBoxInfoItem& rNewInner ) : + ScBlockUndo( pNewDocShell, lcl_TotalRange(rRangeList), SC_UNDO_SIMPLE ), + pUndoDoc( pNewUndoDoc ) +{ + pRanges = new ScRangeList(rRangeList); + pOuter = new SvxBoxItem(rNewOuter); + pInner = new SvxBoxInfoItem(rNewInner); +} + +ScUndoBorder::~ScUndoBorder() +{ + delete pUndoDoc; + delete pRanges; + delete pOuter; + delete pInner; +} + +String ScUndoBorder::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_SELATTRLINES ); //! eigener String? +} + +void ScUndoBorder::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScMarkData aMarkData; + aMarkData.MarkFromRangeList( *pRanges, false ); + pUndoDoc->CopyToDocument( aBlockRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData ); + pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + EndUndo(); +} + +void ScUndoBorder::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); //! Funktion an docfunc aufrufen + size_t nCount = pRanges->size(); + for (size_t i = 0; i < nCount; ++i ) + { + ScRange aRange = *(*pRanges)[i]; + SCTAB nTab = aRange.aStart.Tab(); + + ScMarkData aMark; + aMark.SetMarkArea( aRange ); + aMark.SelectTable( nTab, sal_True ); + + pDoc->ApplySelectionFrame( aMark, pOuter, pInner ); + } + for (size_t i = 0; i < nCount; ++i) + pDocShell->PostPaint( *(*pRanges)[i], PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + EndRedo(); +} + +void ScUndoBorder::Repeat(SfxRepeatTarget& /* rTarget */) +{ + //! spaeter (wenn die Funktion aus cellsuno nach docfunc gewandert ist) +} + +sal_Bool ScUndoBorder::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // s.o. +} + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undoblk2.cxx b/sc/source/ui/undo/undoblk2.cxx new file mode 100644 index 000000000000..208a10d437cc --- /dev/null +++ b/sc/source/ui/undo/undoblk2.cxx @@ -0,0 +1,208 @@ +/* -*- 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_sc.hxx" + +// System - Includes ----------------------------------------------------- + + + +#ifndef PCH +#include "scitems.hxx" // SearchItem +#endif + +// INCLUDE --------------------------------------------------------------- + +#include "undoblk.hxx" +#include "document.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "olinetab.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "target.hxx" + +#include "undoolk.hxx" //! GetUndo ins Document verschieben! + + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1(ScUndoWidthOrHeight, SfxUndoAction); + +// ----------------------------------------------------------------------- + + + +// +// Spaltenbreiten oder Zeilenhoehen aendern +// + +ScUndoWidthOrHeight::ScUndoWidthOrHeight( ScDocShell* pNewDocShell, + const ScMarkData& rMark, + SCCOLROW nNewStart, SCTAB nNewStartTab, SCCOLROW nNewEnd, SCTAB nNewEndTab, + ScDocument* pNewUndoDoc, SCCOLROW nNewCnt, SCCOLROW* pNewRanges, + ScOutlineTable* pNewUndoTab, + ScSizeMode eNewMode, sal_uInt16 nNewSizeTwips, sal_Bool bNewWidth ) : + ScSimpleUndo( pNewDocShell ), + aMarkData( rMark ), + nStart( nNewStart ), + nEnd( nNewEnd ), + nStartTab( nNewStartTab ), + nEndTab( nNewEndTab ), + pUndoDoc( pNewUndoDoc ), + pUndoTab( pNewUndoTab ), + nRangeCnt( nNewCnt ), + pRanges( pNewRanges ), + nNewSize( nNewSizeTwips ), + bWidth( bNewWidth ), + eMode( eNewMode ), + pDrawUndo( NULL ) +{ + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); +} + +ScUndoWidthOrHeight::~ScUndoWidthOrHeight() +{ + delete[] pRanges; + delete pUndoDoc; + delete pUndoTab; + DeleteSdrUndoAction( pDrawUndo ); +} + +String ScUndoWidthOrHeight::GetComment() const +{ + // [ "optimale " ] "Spaltenbreite" | "Zeilenhoehe" + return ( bWidth ? + ( ( eMode == SC_SIZE_OPTIMAL )? + ScGlobal::GetRscString( STR_UNDO_OPTCOLWIDTH ) : + ScGlobal::GetRscString( STR_UNDO_COLWIDTH ) + ) : + ( ( eMode == SC_SIZE_OPTIMAL )? + ScGlobal::GetRscString( STR_UNDO_OPTROWHEIGHT ) : + ScGlobal::GetRscString( STR_UNDO_ROWHEIGHT ) + ) ); +} + +void ScUndoWidthOrHeight::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + SCCOLROW nPaintStart = nStart > 0 ? nStart-1 : static_cast<SCCOLROW>(0); + + if (eMode==SC_SIZE_OPTIMAL) + { + if ( SetViewMarkData( aMarkData ) ) + nPaintStart = 0; // paint all, because of changed selection + } + + //! outlines from all tables? + if (pUndoTab) // Outlines mit gespeichert? + pDoc->SetOutlineTable( nStartTab, pUndoTab ); + + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nTab; + for (nTab=0; nTab<nTabCount; nTab++) + if (aMarkData.GetTableSelect(nTab)) + { + if (bWidth) // Width + { + pUndoDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, + static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, + false, pDoc ); + pDoc->UpdatePageBreaks( nTab ); + pDocShell->PostPaint( static_cast<SCCOL>(nPaintStart), 0, nTab, + MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_TOP ); + } + else // Height + { + pUndoDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, false, pDoc ); + pDoc->UpdatePageBreaks( nTab ); + pDocShell->PostPaint( 0, nPaintStart, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_LEFT ); + } + } + + DoSdrUndoAction( pDrawUndo, pDoc ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->UpdateScrollBars(); + + SCTAB nCurrentTab = pViewShell->GetViewData()->GetTabNo(); + if ( nCurrentTab < nStartTab || nCurrentTab > nEndTab ) + pViewShell->SetTabNo( nStartTab ); + } + + EndUndo(); +} + +void ScUndoWidthOrHeight::Redo() +{ + BeginRedo(); + + sal_Bool bPaintAll = false; + if (eMode==SC_SIZE_OPTIMAL) + { + if ( SetViewMarkData( aMarkData ) ) + bPaintAll = sal_True; // paint all, because of changed selection + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + SCTAB nTab = pViewShell->GetViewData()->GetTabNo(); + if ( nTab < nStartTab || nTab > nEndTab ) + pViewShell->SetTabNo( nStartTab ); + + // SetWidthOrHeight aendert aktuelle Tabelle ! + pViewShell->SetWidthOrHeight( bWidth, nRangeCnt, pRanges, eMode, nNewSize, false, true, &aMarkData ); + } + + // paint grid if selection was changed directly at the MarkData + if (bPaintAll) + pDocShell->PostPaint( 0, 0, nStartTab, MAXCOL, MAXROW, nEndTab, PAINT_GRID ); + + EndRedo(); +} + +void ScUndoWidthOrHeight::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->SetMarkedWidthOrHeight( bWidth, eMode, nNewSize, sal_True ); +} + +sal_Bool ScUndoWidthOrHeight::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx new file mode 100644 index 000000000000..45ea822f2090 --- /dev/null +++ b/sc/source/ui/undo/undoblk3.cxx @@ -0,0 +1,2136 @@ +/* -*- 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_sc.hxx" + +// INCLUDE ------------------------------------------------------------------- + +#include "scitems.hxx" +#include <svx/algitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/justifyitem.hxx> +#include <svl/srchitem.hxx> +#include <sfx2/linkmgr.hxx> +#include <sfx2/bindings.hxx> +#include <vcl/virdev.hxx> +#include <sfx2/app.hxx> + +#include "undoblk.hxx" +#include "sc.hrc" +#include "globstr.hrc" +#include "global.hxx" +#include "rangenam.hxx" +#include "arealink.hxx" +#include "patattr.hxx" +#include "target.hxx" +#include "document.hxx" +#include "docpool.hxx" +#include "table.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "undoolk.hxx" +#include "undoutil.hxx" +#include "chgtrack.hxx" +#include "dociter.hxx" +#include "cell.hxx" +#include "paramisc.hxx" +#include "postit.hxx" +#include "docuno.hxx" + +// STATIC DATA --------------------------------------------------------------- + +TYPEINIT1(ScUndoDeleteContents, SfxUndoAction); +TYPEINIT1(ScUndoFillTable, SfxUndoAction); +TYPEINIT1(ScUndoSelectionAttr, SfxUndoAction); +TYPEINIT1(ScUndoAutoFill, SfxUndoAction); +TYPEINIT1(ScUndoMerge, SfxUndoAction); +TYPEINIT1(ScUndoAutoFormat, SfxUndoAction); +TYPEINIT1(ScUndoReplace, SfxUndoAction); +TYPEINIT1(ScUndoTabOp, SfxUndoAction); +TYPEINIT1(ScUndoConversion, SfxUndoAction); +TYPEINIT1(ScUndoRefConversion, SfxUndoAction); +TYPEINIT1(ScUndoRefreshLink, SfxUndoAction); +TYPEINIT1(ScUndoInsertAreaLink, SfxUndoAction); +TYPEINIT1(ScUndoRemoveAreaLink, SfxUndoAction); +TYPEINIT1(ScUndoUpdateAreaLink, SfxUndoAction); + + +// To Do: +/*A*/ // SetOptimalHeight auf Dokument, wenn keine View + + +//============================================================================ +// class ScUndoDeleteContents +// +// Inhalte loeschen + +//---------------------------------------------------------------------------- + +ScUndoDeleteContents::ScUndoDeleteContents( + ScDocShell* pNewDocShell, + const ScMarkData& rMark, const ScRange& rRange, + ScDocument* pNewUndoDoc, sal_Bool bNewMulti, + sal_uInt16 nNewFlags, sal_Bool bObjects ) + // + : ScSimpleUndo( pNewDocShell ), + // + aRange ( rRange ), + aMarkData ( rMark ), + pUndoDoc ( pNewUndoDoc ), + pDrawUndo ( NULL ), + nFlags ( nNewFlags ), + bMulti ( bNewMulti ) // ueberliquid +{ + if (bObjects) + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); + + if ( !(aMarkData.IsMarked() || aMarkData.IsMultiMarked()) ) // keine Zelle markiert: + aMarkData.SetMarkArea( aRange ); // Zelle unter Cursor markieren + + SetChangeTrack(); +} + + +//---------------------------------------------------------------------------- + +ScUndoDeleteContents::~ScUndoDeleteContents() +{ + delete pUndoDoc; + DeleteSdrUndoAction( pDrawUndo ); +} + + +//---------------------------------------------------------------------------- + +String ScUndoDeleteContents::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_DELETECONTENTS ); // "Loeschen" +} + + +void ScUndoDeleteContents::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack && (nFlags & IDF_CONTENTS) ) + pChangeTrack->AppendContentRange( aRange, pUndoDoc, + nStartChangeAction, nEndChangeAction ); + else + nStartChangeAction = nEndChangeAction = 0; +} + + +//---------------------------------------------------------------------------- + +void ScUndoDeleteContents::DoChange( const sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + SetViewMarkData( aMarkData ); + + sal_uInt16 nExtFlags = 0; + + if (bUndo) // nur Undo + { + sal_uInt16 nUndoFlags = IDF_NONE; // entweder alle oder keine Inhalte kopieren + if (nFlags & IDF_CONTENTS) // (es sind nur die richtigen ins UndoDoc kopiert worden) + nUndoFlags |= IDF_CONTENTS; + if (nFlags & IDF_ATTRIB) + nUndoFlags |= IDF_ATTRIB; + if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute + nUndoFlags |= IDF_STRING; // -> Zellen werden geaendert + // do not create clones of note captions, they will be restored via drawing undo + nUndoFlags |= IDF_NOCAPTIONS; + + ScRange aCopyRange = aRange; + SCTAB nTabCount = pDoc->GetTableCount(); + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + + pUndoDoc->CopyToDocument( aCopyRange, nUndoFlags, bMulti, pDoc, &aMarkData ); + + DoSdrUndoAction( pDrawUndo, pDoc ); + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + + pDocShell->UpdatePaintExt( nExtFlags, aRange ); // content after the change + } + else // nur Redo + { + pDocShell->UpdatePaintExt( nExtFlags, aRange ); // content before the change + + aMarkData.MarkToMulti(); + RedoSdrUndoAction( pDrawUndo ); + // do not delete objects and note captions, they have been removed via drawing undo + sal_uInt16 nRedoFlags = (nFlags & ~IDF_OBJECTS) | IDF_NOCAPTIONS; + pDoc->DeleteSelection( nRedoFlags, aMarkData ); + aMarkData.MarkToSimple(); + + SetChangeTrack(); + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if ( !( (pViewShell) && pViewShell->AdjustRowHeight( + aRange.aStart.Row(), aRange.aEnd.Row() ) ) ) +/*A*/ pDocShell->PostPaint( aRange, PAINT_GRID | PAINT_EXTRAS, nExtFlags ); + + pDocShell->PostDataChanged(); + if (pViewShell) + pViewShell->CellContentChanged(); + + ShowTable( aRange ); +} + + +//---------------------------------------------------------------------------- + +void ScUndoDeleteContents::Undo() +{ + BeginUndo(); + DoChange( sal_True ); + EndUndo(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocShell->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + aChangeRanges.Append( aRange ); + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } +} + + +//---------------------------------------------------------------------------- + +void ScUndoDeleteContents::Redo() +{ + BeginRedo(); + DoChange( false ); + EndRedo(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocShell->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + aChangeRanges.Append( aRange ); + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } +} + + +//---------------------------------------------------------------------------- + +void ScUndoDeleteContents::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->DeleteContents( nFlags, sal_True ); +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoDeleteContents::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +//============================================================================ +// class ScUndoFillTable +// +// Tabellen ausfuellen +// (Bearbeiten|Ausfuellen|...) + +//---------------------------------------------------------------------------- + +ScUndoFillTable::ScUndoFillTable( ScDocShell* pNewDocShell, + const ScMarkData& rMark, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, + ScDocument* pNewUndoDoc, sal_Bool bNewMulti, SCTAB nSrc, + sal_uInt16 nFlg, sal_uInt16 nFunc, sal_Bool bSkip, sal_Bool bLink ) + // + : ScSimpleUndo( pNewDocShell ), + // + aRange ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), + aMarkData ( rMark ), + pUndoDoc ( pNewUndoDoc ), + nFlags ( nFlg ), + nFunction ( nFunc ), + nSrcTab ( nSrc ), + bMulti ( bNewMulti ), + bSkipEmpty ( bSkip ), + bAsLink ( bLink ) +{ + SetChangeTrack(); +} + + +//---------------------------------------------------------------------------- + +ScUndoFillTable::~ScUndoFillTable() +{ + delete pUndoDoc; +} + + +//---------------------------------------------------------------------------- + +String ScUndoFillTable::GetComment() const +{ + return ScGlobal::GetRscString( STR_FILL_TAB ); +} + + +void ScUndoFillTable::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + { + SCTAB nTabCount = pDocShell->GetDocument()->GetTableCount(); + ScRange aWorkRange(aRange); + nStartChangeAction = 0; + sal_uLong nTmpAction; + for ( SCTAB i = 0; i < nTabCount; i++ ) + { + if (i != nSrcTab && aMarkData.GetTableSelect(i)) + { + aWorkRange.aStart.SetTab(i); + aWorkRange.aEnd.SetTab(i); + pChangeTrack->AppendContentRange( aWorkRange, pUndoDoc, + nTmpAction, nEndChangeAction ); + if ( !nStartChangeAction ) + nStartChangeAction = nTmpAction; + } + } + } + else + nStartChangeAction = nEndChangeAction = 0; +} + + +//---------------------------------------------------------------------------- + +void ScUndoFillTable::DoChange( const sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + SetViewMarkData( aMarkData ); + + if (bUndo) // nur Undo + { + SCTAB nTabCount = pDoc->GetTableCount(); + ScRange aWorkRange(aRange); + for ( SCTAB i = 0; i < nTabCount; i++ ) + if (i != nSrcTab && aMarkData.GetTableSelect(i)) + { + aWorkRange.aStart.SetTab(i); + aWorkRange.aEnd.SetTab(i); + if (bMulti) + pDoc->DeleteSelectionTab( i, IDF_ALL, aMarkData ); + else + pDoc->DeleteAreaTab( aWorkRange, IDF_ALL ); + pUndoDoc->CopyToDocument( aWorkRange, IDF_ALL, bMulti, pDoc, &aMarkData ); + } + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + } + else // nur Redo + { + aMarkData.MarkToMulti(); + pDoc->FillTabMarked( nSrcTab, aMarkData, nFlags, nFunction, bSkipEmpty, bAsLink ); + aMarkData.MarkToSimple(); + SetChangeTrack(); + } + + pDocShell->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_EXTRAS); + pDocShell->PostDataChanged(); + + // CellContentChanged kommt mit der Markierung + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + SCTAB nTab = pViewShell->GetViewData()->GetTabNo(); + if ( !aMarkData.GetTableSelect(nTab) ) + pViewShell->SetTabNo( nSrcTab ); + + pViewShell->DoneBlockMode(); // gibt sonst Probleme, weil Markierung auf falscher Tabelle + } +} + + +//---------------------------------------------------------------------------- + +void ScUndoFillTable::Undo() +{ + BeginUndo(); + DoChange( sal_True ); + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoFillTable::Redo() +{ + BeginRedo(); + DoChange( false ); + EndRedo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoFillTable::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->FillTab( nFlags, nFunction, bSkipEmpty, bAsLink ); +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoFillTable::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +//============================================================================ +// class ScUndoSelectionAttr +// +// Zellformat aendern + +//---------------------------------------------------------------------------- + +ScUndoSelectionAttr::ScUndoSelectionAttr( ScDocShell* pNewDocShell, + const ScMarkData& rMark, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, + ScDocument* pNewUndoDoc, sal_Bool bNewMulti, + const ScPatternAttr* pNewApply, + const SvxBoxItem* pNewOuter, const SvxBoxInfoItem* pNewInner ) + // + : ScSimpleUndo( pNewDocShell ), + // + aMarkData ( rMark ), + aRange ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), + pUndoDoc ( pNewUndoDoc ), + bMulti ( bNewMulti ) +{ + ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool(); + pApplyPattern = (ScPatternAttr*) &pPool->Put( *pNewApply ); + pLineOuter = pNewOuter ? (SvxBoxItem*) &pPool->Put( *pNewOuter ) : NULL; + pLineInner = pNewInner ? (SvxBoxInfoItem*) &pPool->Put( *pNewInner ) : NULL; +} + + +//---------------------------------------------------------------------------- + +ScUndoSelectionAttr::~ScUndoSelectionAttr() +{ + ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool(); + pPool->Remove(*pApplyPattern); + if (pLineOuter) + pPool->Remove(*pLineOuter); + if (pLineInner) + pPool->Remove(*pLineInner); + + delete pUndoDoc; +} + + +//---------------------------------------------------------------------------- + +String ScUndoSelectionAttr::GetComment() const +{ + //"Attribute" "/Linien" + return ScGlobal::GetRscString( pLineOuter ? STR_UNDO_SELATTRLINES : STR_UNDO_SELATTR ); +} + +//---------------------------------------------------------------------------- + +ScEditDataArray* ScUndoSelectionAttr::GetDataArray() +{ + return &aDataArray; +} + +//---------------------------------------------------------------------------- + +void ScUndoSelectionAttr::DoChange( const sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + SetViewMarkData( aMarkData ); + + ScRange aEffRange( aRange ); + if ( pDoc->HasAttrib( aEffRange, HASATTR_MERGED ) ) // zusammengefasste Zellen? + pDoc->ExtendMerge( aEffRange ); + + sal_uInt16 nExtFlags = 0; + pDocShell->UpdatePaintExt( nExtFlags, aEffRange ); + + ChangeEditData(bUndo); + + if (bUndo) // nur bei Undo + { + ScRange aCopyRange = aRange; + SCTAB nTabCount = pDoc->GetTableCount(); + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pUndoDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pDoc, &aMarkData ); + } + else // nur bei Redo + { + aMarkData.MarkToMulti(); + pDoc->ApplySelectionPattern( *pApplyPattern, aMarkData ); + aMarkData.MarkToSimple(); + + if (pLineOuter) + pDoc->ApplySelectionFrame( aMarkData, pLineOuter, pLineInner ); + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if ( !( (pViewShell) && pViewShell->AdjustBlockHeight() ) ) +/*A*/ pDocShell->PostPaint( aEffRange, PAINT_GRID | PAINT_EXTRAS, nExtFlags ); + + ShowTable( aRange ); +} + +void ScUndoSelectionAttr::ChangeEditData( const bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + for (const ScEditDataArray::Item* pItem = aDataArray.First(); pItem; pItem = aDataArray.Next()) + { + ScBaseCell* pCell; + pDoc->GetCell(pItem->GetCol(), pItem->GetRow(), pItem->GetTab(), pCell); + if (!pCell || pCell->GetCellType() != CELLTYPE_EDIT) + continue; + + ScEditCell* pEditCell = static_cast<ScEditCell*>(pCell); + if (bUndo) + pEditCell->SetData(pItem->GetOldData(), NULL); + else + pEditCell->SetData(pItem->GetNewData(), NULL); + } +} + + +//---------------------------------------------------------------------------- + +void ScUndoSelectionAttr::Undo() +{ + BeginUndo(); + DoChange( sal_True ); + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoSelectionAttr::Redo() +{ + BeginRedo(); + DoChange( false ); + EndRedo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoSelectionAttr::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + if (pLineOuter) + rViewShell.ApplyPatternLines( *pApplyPattern, pLineOuter, pLineInner, sal_True ); + else + rViewShell.ApplySelectionPattern( *pApplyPattern, sal_True ); + } +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoSelectionAttr::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +//============================================================================ +// class ScUndoAutoFill +// +// Auto-Fill (nur einfache Bloecke) + +//---------------------------------------------------------------------------- + +ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell, + const ScRange& rRange, const ScRange& rSourceArea, + ScDocument* pNewUndoDoc, const ScMarkData& rMark, + FillDir eNewFillDir, FillCmd eNewFillCmd, FillDateCmd eNewFillDateCmd, + double fNewStartValue, double fNewStepValue, double fNewMaxValue ) + // + : ScBlockUndo( pNewDocShell, rRange, SC_UNDO_AUTOHEIGHT ), + // + aSource ( rSourceArea ), + aMarkData ( rMark ), + pUndoDoc ( pNewUndoDoc ), + eFillDir ( eNewFillDir ), + eFillCmd ( eNewFillCmd ), + eFillDateCmd ( eNewFillDateCmd ), + fStartValue ( fNewStartValue ), + fStepValue ( fNewStepValue ), + fMaxValue ( fNewMaxValue ) +{ + SetChangeTrack(); +} + + +//---------------------------------------------------------------------------- + +ScUndoAutoFill::~ScUndoAutoFill() +{ + delete pUndoDoc; +} + + +//---------------------------------------------------------------------------- + +String ScUndoAutoFill::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_AUTOFILL ); //"Ausfuellen" +} + + +void ScUndoAutoFill::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc, + nStartChangeAction, nEndChangeAction ); + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoAutoFill::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + { + if (aMarkData.GetTableSelect(nTab)) + { + ScRange aWorkRange = aBlockRange; + aWorkRange.aStart.SetTab(nTab); + aWorkRange.aEnd.SetTab(nTab); + + sal_uInt16 nExtFlags = 0; + pDocShell->UpdatePaintExt( nExtFlags, aWorkRange ); + pDoc->DeleteAreaTab( aWorkRange, IDF_AUTOFILL ); + pUndoDoc->CopyToDocument( aWorkRange, IDF_AUTOFILL, false, pDoc ); + + pDoc->ExtendMerge( aWorkRange, sal_True ); + pDocShell->PostPaint( aWorkRange, PAINT_GRID, nExtFlags ); + } + } + pDocShell->PostDataChanged(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->CellContentChanged(); + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoAutoFill::Redo() +{ + BeginRedo(); + +//! Tabellen selektieren + + SCCOLROW nCount = 0; + switch (eFillDir) + { + case FILL_TO_BOTTOM: + nCount = aBlockRange.aEnd.Row() - aSource.aEnd.Row(); + break; + case FILL_TO_RIGHT: + nCount = aBlockRange.aEnd.Col() - aSource.aEnd.Col(); + break; + case FILL_TO_TOP: + nCount = aSource.aStart.Row() - aBlockRange.aStart.Row(); + break; + case FILL_TO_LEFT: + nCount = aSource.aStart.Col() - aBlockRange.aStart.Col(); + break; + } + + ScDocument* pDoc = pDocShell->GetDocument(); + if ( fStartValue != MAXDOUBLE ) + { + SCCOL nValX = (eFillDir == FILL_TO_LEFT) ? aSource.aEnd.Col() : aSource.aStart.Col(); + SCROW nValY = (eFillDir == FILL_TO_TOP ) ? aSource.aEnd.Row() : aSource.aStart.Row(); + SCTAB nTab = aSource.aStart.Tab(); + pDoc->SetValue( nValX, nValY, nTab, fStartValue ); + } + pDoc->Fill( aSource.aStart.Col(), aSource.aStart.Row(), + aSource.aEnd.Col(), aSource.aEnd.Row(), + aMarkData, nCount, + eFillDir, eFillCmd, eFillDateCmd, + fStepValue, fMaxValue ); + + SetChangeTrack(); + + pDocShell->PostPaint( aBlockRange, PAINT_GRID ); + pDocShell->PostDataChanged(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->CellContentChanged(); + + EndRedo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoAutoFill::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + if (eFillCmd==FILL_SIMPLE) + rViewShell.FillSimple( eFillDir, sal_True ); + else + rViewShell.FillSeries( eFillDir, eFillCmd, eFillDateCmd, + fStartValue, fStepValue, fMaxValue, sal_True ); + } +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoAutoFill::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +//============================================================================ +// class ScUndoMerge +// +// Zellen zusammenfassen / Zusammenfassung aufheben + +//---------------------------------------------------------------------------- + +ScUndoMerge::ScUndoMerge( ScDocShell* pNewDocShell, const ScCellMergeOption& rOption, + bool bMergeContents, ScDocument* pUndoDoc, SdrUndoAction* pDrawUndo ) + // + : ScSimpleUndo( pNewDocShell ), + // + maOption(rOption), + mbMergeContents( bMergeContents ), + mpUndoDoc( pUndoDoc ), + mpDrawUndo( pDrawUndo ) +{ +} + + +//---------------------------------------------------------------------------- + +ScUndoMerge::~ScUndoMerge() +{ + delete mpUndoDoc; + DeleteSdrUndoAction( mpDrawUndo ); +} + + +//---------------------------------------------------------------------------- + +String ScUndoMerge::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_MERGE ); +} + + +//---------------------------------------------------------------------------- + +void ScUndoMerge::DoChange( bool bUndo ) const +{ + using ::std::set; + + if (maOption.maTabs.empty()) + // Nothing to do. + return; + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + ScRange aCurRange = maOption.getSingleRange(pDocShell->GetCurTab()); + ScUndoUtil::MarkSimpleBlock(pDocShell, aCurRange); + + for (set<SCTAB>::const_iterator itr = maOption.maTabs.begin(), itrEnd = maOption.maTabs.end(); + itr != itrEnd; ++itr) + { + SCTAB nTab = *itr; + ScRange aRange = maOption.getSingleRange(nTab); + + if (bUndo) + // remove merge (contents are copied back below from undo document) + pDoc->RemoveMerge( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab() ); + else + { + // repeat merge, but do not remove note captions (will be done by drawing redo below) + pDoc->DoMerge( aRange.aStart.Tab(), + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), false ); + + if (maOption.mbCenter) + { + pDoc->ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), + SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) ); + pDoc->ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), + SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY ) ); + } + } + + // undo -> copy back deleted contents + if (bUndo && mpUndoDoc) + { + pDoc->DeleteAreaTab( aRange, IDF_CONTENTS|IDF_NOCAPTIONS ); + mpUndoDoc->CopyToDocument( aRange, IDF_ALL|IDF_NOCAPTIONS, false, pDoc ); + } + + // redo -> merge contents again + else if (!bUndo && mbMergeContents) + { + pDoc->DoMergeContents( aRange.aStart.Tab(), + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row() ); + } + + if (bUndo) + DoSdrUndoAction( mpDrawUndo, pDoc ); + else + RedoSdrUndoAction( mpDrawUndo ); + + bool bDidPaint = false; + if ( pViewShell ) + { + pViewShell->SetTabNo(nTab); + bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow); + } + + if (!bDidPaint) + ScUndoUtil::PaintMore(pDocShell, aRange); + } + + ShowTable(aCurRange); +} + + +//---------------------------------------------------------------------------- + +void ScUndoMerge::Undo() +{ + BeginUndo(); + DoChange( true ); + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoMerge::Redo() +{ + BeginRedo(); + DoChange( false ); + EndRedo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoMerge::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + sal_Bool bCont = false; + rViewShell.MergeCells( false, bCont, sal_True ); + } +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoMerge::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +//============================================================================ +// class ScUndoAutoFormat +// +// Auto-Format (nur einfache Bloecke) + +//---------------------------------------------------------------------------- + +ScUndoAutoFormat::ScUndoAutoFormat( ScDocShell* pNewDocShell, + const ScRange& rRange, ScDocument* pNewUndoDoc, + const ScMarkData& rMark, sal_Bool bNewSize, sal_uInt16 nNewFormatNo ) + // + : ScBlockUndo( pNewDocShell, rRange, bNewSize ? SC_UNDO_MANUALHEIGHT : SC_UNDO_AUTOHEIGHT ), + // + pUndoDoc ( pNewUndoDoc ), + aMarkData ( rMark ), + bSize ( bNewSize ), + nFormatNo ( nNewFormatNo ) +{ +} + + +//---------------------------------------------------------------------------- + +ScUndoAutoFormat::~ScUndoAutoFormat() +{ + delete pUndoDoc; +} + + +//---------------------------------------------------------------------------- + +String ScUndoAutoFormat::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_AUTOFORMAT ); //"Auto-Format" +} + + +//---------------------------------------------------------------------------- + +void ScUndoAutoFormat::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + // Attribute +// pDoc->DeleteAreaTab( aBlockRange, IDF_ATTRIB ); +// pUndoDoc->CopyToDocument( aBlockRange, IDF_ATTRIB, sal_False, pDoc ); + + SCTAB nTabCount = pDoc->GetTableCount(); + pDoc->DeleteArea( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(), + aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), + aMarkData, IDF_ATTRIB ); + ScRange aCopyRange = aBlockRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pUndoDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, false, pDoc, &aMarkData ); + + // Zellhoehen und -breiten (IDF_NONE) + if (bSize) + { + SCCOL nStartX = aBlockRange.aStart.Col(); + SCROW nStartY = aBlockRange.aStart.Row(); + SCTAB nStartZ = aBlockRange.aStart.Tab(); + SCCOL nEndX = aBlockRange.aEnd.Col(); + SCROW nEndY = aBlockRange.aEnd.Row(); + SCTAB nEndZ = aBlockRange.aEnd.Tab(); + + pUndoDoc->CopyToDocument( nStartX, 0, 0, nEndX, MAXROW, nTabCount-1, + IDF_NONE, false, pDoc, &aMarkData ); + pUndoDoc->CopyToDocument( 0, nStartY, 0, MAXCOL, nEndY, nTabCount-1, + IDF_NONE, false, pDoc, &aMarkData ); + pDocShell->PostPaint( 0, 0, nStartZ, MAXCOL, MAXROW, nEndZ, + PAINT_GRID | PAINT_LEFT | PAINT_TOP, SC_PF_LINES ); + } + else + pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES ); + + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoAutoFormat::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + SCCOL nStartX = aBlockRange.aStart.Col(); + SCROW nStartY = aBlockRange.aStart.Row(); + SCTAB nStartZ = aBlockRange.aStart.Tab(); + SCCOL nEndX = aBlockRange.aEnd.Col(); + SCROW nEndY = aBlockRange.aEnd.Row(); + SCTAB nEndZ = aBlockRange.aEnd.Tab(); + + pDoc->AutoFormat( nStartX, nStartY, nEndX, nEndY, nFormatNo, aMarkData ); + + if (bSize) + { + VirtualDevice aVirtDev; + Fraction aZoomX(1,1); + Fraction aZoomY = aZoomX; + double nPPTX,nPPTY; + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + ScViewData* pData = pViewShell->GetViewData(); + nPPTX = pData->GetPPTX(); + nPPTY = pData->GetPPTY(); + aZoomX = pData->GetZoomX(); + aZoomY = pData->GetZoomY(); + } + else + { + // Zoom auf 100 lassen + nPPTX = ScGlobal::nScreenPPTX; + nPPTY = ScGlobal::nScreenPPTY; + } + + sal_Bool bFormula = false; //! merken + + for (SCTAB nTab=nStartZ; nTab<=nEndZ; nTab++) + { + ScMarkData aDestMark; + aDestMark.SelectOneTable( nTab ); + aDestMark.SetMarkArea( ScRange( nStartX, nStartY, nTab, nEndX, nEndY, nTab ) ); + aDestMark.MarkToMulti(); + + // wie SC_SIZE_VISOPT + for (SCROW nRow=nStartY; nRow<=nEndY; nRow++) + { + sal_uInt8 nOld = pDoc->GetRowFlags(nRow,nTab); + bool bHidden = pDoc->RowHidden(nRow, nTab); + if ( !bHidden && ( nOld & CR_MANUALSIZE ) ) + pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE ); + } + pDoc->SetOptimalHeight( nStartY, nEndY, nTab, 0, &aVirtDev, + nPPTX, nPPTY, aZoomX, aZoomY, false ); + + for (SCCOL nCol=nStartX; nCol<=nEndX; nCol++) + if (!pDoc->ColHidden(nCol, nTab)) + { + sal_uInt16 nThisSize = STD_EXTRA_WIDTH + pDoc->GetOptimalColWidth( nCol, nTab, + &aVirtDev, nPPTX, nPPTY, aZoomX, aZoomY, bFormula, + &aDestMark ); + pDoc->SetColWidth( nCol, nTab, nThisSize ); + pDoc->ShowCol( nCol, nTab, sal_True ); + } + } + + pDocShell->PostPaint( 0, 0, nStartZ, + MAXCOL, MAXROW, nEndZ, + PAINT_GRID | PAINT_LEFT | PAINT_TOP, SC_PF_LINES); + } + else + pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES ); + + EndRedo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoAutoFormat::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->AutoFormat( nFormatNo, sal_True ); +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoAutoFormat::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +//============================================================================ +// class ScUndoReplace +// +// Ersetzen + +//---------------------------------------------------------------------------- + +ScUndoReplace::ScUndoReplace( ScDocShell* pNewDocShell, const ScMarkData& rMark, + SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, + const String& rNewUndoStr, ScDocument* pNewUndoDoc, + const SvxSearchItem* pItem ) + // + : ScSimpleUndo( pNewDocShell ), + // + aCursorPos ( nCurX, nCurY, nCurZ ), + aMarkData ( rMark ), + aUndoStr ( rNewUndoStr ), + pUndoDoc ( pNewUndoDoc ) +{ + pSearchItem = new SvxSearchItem( *pItem ); + SetChangeTrack(); +} + + +//---------------------------------------------------------------------------- + +ScUndoReplace::~ScUndoReplace() +{ + delete pUndoDoc; + delete pSearchItem; +} + + +//---------------------------------------------------------------------------- + +void ScUndoReplace::SetChangeTrack() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + { + if ( pUndoDoc ) + { //! im UndoDoc stehen nur die geaenderten Zellen, + // deswegen per Iterator moeglich + pChangeTrack->AppendContentsIfInRefDoc( pUndoDoc, + nStartChangeAction, nEndChangeAction ); + } + else + { + nStartChangeAction = pChangeTrack->GetActionMax() + 1; + ScChangeActionContent* pContent = new ScChangeActionContent( + ScRange( aCursorPos) ); + pContent->SetOldValue( aUndoStr, pDoc ); + pContent->SetNewValue( pDoc->GetCell( aCursorPos ), pDoc ); + pChangeTrack->Append( pContent ); + nEndChangeAction = pChangeTrack->GetActionMax(); + } + } + else + nStartChangeAction = nEndChangeAction = 0; +} + +//---------------------------------------------------------------------------- + +String ScUndoReplace::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_REPLACE ); // "Ersetzen" +} + + +//---------------------------------------------------------------------------- + +void ScUndoReplace::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + ShowTable( aCursorPos.Tab() ); + + if (pUndoDoc) // nur bei ReplaceAll !! + { + DBG_ASSERT(pSearchItem->GetCommand() == SVX_SEARCHCMD_REPLACE_ALL, + "ScUndoReplace:: Falscher Modus"); + + SetViewMarkData( aMarkData ); + +//! markierte Tabellen +//! Bereich merken ? + + // Undo-Dokument hat keine Zeilen-/Spalten-Infos, also mit bColRowFlags = FALSE + // kopieren, um Outline-Gruppen nicht kaputtzumachen. + + sal_uInt16 nUndoFlags = (pSearchItem->GetPattern()) ? IDF_ATTRIB : IDF_CONTENTS; + pUndoDoc->CopyToDocument( 0, 0, 0, + MAXCOL, MAXROW, MAXTAB, + nUndoFlags, false, pDoc, NULL, false ); // ohne Row-Flags + pDocShell->PostPaintGridAll(); + } + else if (pSearchItem->GetPattern() && + pSearchItem->GetCommand() == SVX_SEARCHCMD_REPLACE) + { + String aTempStr = pSearchItem->GetSearchString(); // vertauschen + pSearchItem->SetSearchString(pSearchItem->GetReplaceString()); + pSearchItem->SetReplaceString(aTempStr); + pDoc->ReplaceStyle( *pSearchItem, + aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), + aMarkData, sal_True); + pSearchItem->SetReplaceString(pSearchItem->GetSearchString()); + pSearchItem->SetSearchString(aTempStr); + if (pViewShell) + pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(), + SC_FOLLOW_JUMP, false, false ); + pDocShell->PostPaintGridAll(); + } + else if (pSearchItem->GetCellType() == SVX_SEARCHIN_NOTE) + { + ScPostIt* pNote = pDoc->GetNote( aCursorPos ); + DBG_ASSERT( pNote, "ScUndoReplace::Undo - cell does not contain a note" ); + if (pNote) + pNote->SetText( aCursorPos, aUndoStr ); + if (pViewShell) + pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(), + SC_FOLLOW_JUMP, false, false ); + } + else + { + // aUndoStr may contain line breaks + if ( aUndoStr.Search('\n') != STRING_NOTFOUND ) + pDoc->PutCell( aCursorPos, new ScEditCell( aUndoStr, pDoc ) ); + else + pDoc->SetString( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), aUndoStr ); + if (pViewShell) + pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(), + SC_FOLLOW_JUMP, false, false ); + pDocShell->PostPaintGridAll(); + } + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoReplace::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + if (pViewShell) + pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(), + SC_FOLLOW_JUMP, false, false ); + if (pUndoDoc) + { + if (pViewShell) + { + SetViewMarkData( aMarkData ); + + pViewShell->SearchAndReplace( pSearchItem, false, sal_True ); + } + } + else if (pSearchItem->GetPattern() && + pSearchItem->GetCommand() == SVX_SEARCHCMD_REPLACE) + { + pDoc->ReplaceStyle( *pSearchItem, + aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), + aMarkData, sal_True); + pDocShell->PostPaintGridAll(); + } + else + if (pViewShell) + pViewShell->SearchAndReplace( pSearchItem, false, sal_True ); + + SetChangeTrack(); + + EndRedo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoReplace::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->SearchAndReplace( pSearchItem, sal_True, false ); +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoReplace::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +//============================================================================ +// class ScUndoTabOp +// +// Mehrfachoperation (nur einfache Bloecke) + +//---------------------------------------------------------------------------- + +ScUndoTabOp::ScUndoTabOp( ScDocShell* pNewDocShell, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, ScDocument* pNewUndoDoc, + const ScRefAddress& rFormulaCell, + const ScRefAddress& rFormulaEnd, + const ScRefAddress& rRowCell, + const ScRefAddress& rColCell, + sal_uInt8 nMd ) + // + : ScSimpleUndo( pNewDocShell ), + // + aRange ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), + pUndoDoc ( pNewUndoDoc ), + theFormulaCell ( rFormulaCell ), + theFormulaEnd ( rFormulaEnd ), + theRowCell ( rRowCell ), + theColCell ( rColCell ), + nMode ( nMd ) +{ +} + + +//---------------------------------------------------------------------------- + +ScUndoTabOp::~ScUndoTabOp() +{ + delete pUndoDoc; +} + + +//---------------------------------------------------------------------------- + +String ScUndoTabOp::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_TABOP ); // "Mehrfachoperation" +} + + +//---------------------------------------------------------------------------- + +void ScUndoTabOp::Undo() +{ + BeginUndo(); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aRange ); + + sal_uInt16 nExtFlags = 0; + pDocShell->UpdatePaintExt( nExtFlags, aRange ); + + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->DeleteAreaTab( aRange,IDF_ALL & ~IDF_NOTE ); + pUndoDoc->CopyToDocument( aRange, IDF_ALL & ~IDF_NOTE, false, pDoc ); + pDocShell->PostPaint( aRange, PAINT_GRID, nExtFlags ); + pDocShell->PostDataChanged(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->CellContentChanged(); + + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoTabOp::Redo() +{ + BeginRedo(); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aRange ); + + ScTabOpParam aParam( theFormulaCell, theFormulaEnd, + theRowCell, theColCell, + nMode ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->TabOp( aParam, false); + + EndRedo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoTabOp::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoTabOp::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +//============================================================================ +// class ScUndoConversion +// +// Spelling + +//---------------------------------------------------------------------------- + +ScUndoConversion::ScUndoConversion( + ScDocShell* pNewDocShell, const ScMarkData& rMark, + SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, ScDocument* pNewUndoDoc, + SCCOL nNewX, SCROW nNewY, SCTAB nNewZ, ScDocument* pNewRedoDoc, + const ScConversionParam& rConvParam ) : + ScSimpleUndo( pNewDocShell ), + aMarkData( rMark ), + aCursorPos( nCurX, nCurY, nCurZ ), + pUndoDoc( pNewUndoDoc ), + aNewCursorPos( nNewX, nNewY, nNewZ ), + pRedoDoc( pNewRedoDoc ), + maConvParam( rConvParam ) +{ + SetChangeTrack(); +} + + +//---------------------------------------------------------------------------- + +ScUndoConversion::~ScUndoConversion() +{ + delete pUndoDoc; + delete pRedoDoc; +} + + +//---------------------------------------------------------------------------- + +void ScUndoConversion::SetChangeTrack() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + { + if ( pUndoDoc ) + pChangeTrack->AppendContentsIfInRefDoc( pUndoDoc, + nStartChangeAction, nEndChangeAction ); + else + { + OSL_FAIL( "ScUndoConversion::SetChangeTrack: kein UndoDoc" ); + nStartChangeAction = nEndChangeAction = 0; + } + } + else + nStartChangeAction = nEndChangeAction = 0; +} + +//---------------------------------------------------------------------------- + +String ScUndoConversion::GetComment() const +{ + String aText; + switch( maConvParam.GetType() ) + { + case SC_CONVERSION_SPELLCHECK: aText = ScGlobal::GetRscString( STR_UNDO_SPELLING ); break; + case SC_CONVERSION_HANGULHANJA: aText = ScGlobal::GetRscString( STR_UNDO_HANGULHANJA ); break; + case SC_CONVERSION_CHINESE_TRANSL: aText = ScGlobal::GetRscString( STR_UNDO_CHINESE_TRANSLATION ); break; + default: DBG_ERRORFILE( "ScUndoConversion::GetComment - unknown conversion type" ); + } + return aText; +} + + +//---------------------------------------------------------------------------- + +void ScUndoConversion::DoChange( ScDocument* pRefDoc, const ScAddress& rCursorPos ) +{ + if (pRefDoc) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ShowTable( rCursorPos.Tab() ); + + SetViewMarkData( aMarkData ); + + SCTAB nTabCount = pDoc->GetTableCount(); + // Undo/Redo-doc has only selected tables + + sal_Bool bMulti = aMarkData.IsMultiMarked(); + pRefDoc->CopyToDocument( 0, 0, 0, + MAXCOL, MAXROW, nTabCount-1, + IDF_CONTENTS, bMulti, pDoc, &aMarkData ); + pDocShell->PostPaintGridAll(); + } + else + { + OSL_FAIL("Kein Un-/RedoDoc bei Un-/RedoSpelling"); + } +} + + +//---------------------------------------------------------------------------- + +void ScUndoConversion::Undo() +{ + BeginUndo(); + DoChange( pUndoDoc, aCursorPos ); + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoConversion::Redo() +{ + BeginRedo(); + DoChange( pRedoDoc, aNewCursorPos ); + SetChangeTrack(); + EndRedo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoConversion::Repeat( SfxRepeatTarget& rTarget ) +{ + if( rTarget.ISA( ScTabViewTarget ) ) + ((ScTabViewTarget&)rTarget).GetViewShell()->DoSheetConversion( maConvParam, sal_True ); +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoConversion::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return rTarget.ISA( ScTabViewTarget ); +} + + +//============================================================================ +// class ScUndoRefConversion +// +// cell reference conversion + +//---------------------------------------------------------------------------- + +ScUndoRefConversion::ScUndoRefConversion( ScDocShell* pNewDocShell, + const ScRange& aMarkRange, const ScMarkData& rMark, + ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, sal_Bool bNewMulti, sal_uInt16 nNewFlag) : +ScSimpleUndo( pNewDocShell ), +aMarkData ( rMark ), +pUndoDoc ( pNewUndoDoc ), +pRedoDoc ( pNewRedoDoc ), +aRange ( aMarkRange ), +bMulti ( bNewMulti ), +nFlags ( nNewFlag ) +{ + SetChangeTrack(); +} + +ScUndoRefConversion::~ScUndoRefConversion() +{ + delete pUndoDoc; + delete pRedoDoc; +} + +String ScUndoRefConversion::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe" +} + +void ScUndoRefConversion::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack && (nFlags & IDF_FORMULA) ) + pChangeTrack->AppendContentsIfInRefDoc( pUndoDoc, + nStartChangeAction, nEndChangeAction ); + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoRefConversion::DoChange( ScDocument* pRefDoc) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + ShowTable(aRange); + + SetViewMarkData( aMarkData ); + + ScRange aCopyRange = aRange; + SCTAB nTabCount = pDoc->GetTableCount(); + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pRefDoc->CopyToDocument( aCopyRange, nFlags, bMulti, pDoc, &aMarkData ); + pDocShell->PostPaint( aRange, PAINT_GRID); + pDocShell->PostDataChanged(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->CellContentChanged(); +} +void ScUndoRefConversion::Undo() +{ + BeginUndo(); + if (pUndoDoc) + DoChange(pUndoDoc); + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + EndUndo(); +} + +void ScUndoRefConversion::Redo() +{ + BeginRedo(); + if (pRedoDoc) + DoChange(pRedoDoc); + SetChangeTrack(); + EndRedo(); +} + +void ScUndoRefConversion::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->DoRefConversion(); +} + +sal_Bool ScUndoRefConversion::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} +//============================================================================ +// class ScUndoRefreshLink +// +// Link aktualisieren / aendern + +//---------------------------------------------------------------------------- + +ScUndoRefreshLink::ScUndoRefreshLink( ScDocShell* pNewDocShell, + ScDocument* pNewUndoDoc ) + // + : ScSimpleUndo( pNewDocShell ), + // + pUndoDoc( pNewUndoDoc ), + pRedoDoc( NULL ) +{ +} + + +//---------------------------------------------------------------------------- + +ScUndoRefreshLink::~ScUndoRefreshLink() +{ + delete pUndoDoc; + delete pRedoDoc; +} + + +//---------------------------------------------------------------------------- + +String ScUndoRefreshLink::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_UPDATELINK ); +} + + +//---------------------------------------------------------------------------- + +void ScUndoRefreshLink::Undo() +{ + BeginUndo(); + + sal_Bool bMakeRedo = !pRedoDoc; + if (bMakeRedo) + pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); + + sal_Bool bFirst = sal_True; + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nCount; nTab++) + if (pUndoDoc->HasTable(nTab)) + { + ScRange aRange(0,0,nTab,MAXCOL,MAXROW,nTab); + if (bMakeRedo) + { + if (bFirst) + pRedoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); + else + pRedoDoc->AddUndoTab( nTab, nTab, true, true ); + bFirst = false; + pDoc->CopyToDocument(aRange, IDF_ALL, false, pRedoDoc); + pRedoDoc->SetLink( nTab, + pDoc->GetLinkMode(nTab), + pDoc->GetLinkDoc(nTab), + pDoc->GetLinkFlt(nTab), + pDoc->GetLinkOpt(nTab), + pDoc->GetLinkTab(nTab), + pDoc->GetLinkRefreshDelay(nTab) ); + } + + pDoc->DeleteAreaTab( aRange,IDF_ALL ); + pUndoDoc->CopyToDocument( aRange, IDF_ALL, false, pDoc ); + pDoc->SetLink( nTab, pUndoDoc->GetLinkMode(nTab), pUndoDoc->GetLinkDoc(nTab), + pUndoDoc->GetLinkFlt(nTab), pUndoDoc->GetLinkOpt(nTab), + pUndoDoc->GetLinkTab(nTab), + pUndoDoc->GetLinkRefreshDelay(nTab) ); + } + + pDocShell->PostPaintGridAll(); + + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoRefreshLink::Redo() +{ + DBG_ASSERT(pRedoDoc, "Kein RedoDoc bei ScUndoRefreshLink::Redo"); + + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nCount; nTab++) + if (pRedoDoc->HasTable(nTab)) + { + ScRange aRange(0,0,nTab,MAXCOL,MAXROW,nTab); + + pDoc->DeleteAreaTab( aRange, IDF_ALL ); + pRedoDoc->CopyToDocument( aRange, IDF_ALL, false, pDoc ); + pDoc->SetLink( nTab, + pRedoDoc->GetLinkMode(nTab), + pRedoDoc->GetLinkDoc(nTab), + pRedoDoc->GetLinkFlt(nTab), + pRedoDoc->GetLinkOpt(nTab), + pRedoDoc->GetLinkTab(nTab), + pRedoDoc->GetLinkRefreshDelay(nTab) ); + } + + pDocShell->PostPaintGridAll(); + + EndUndo(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoRefreshLink::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoRefreshLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +//---------------------------------------------------------------------------- + +ScAreaLink* lcl_FindAreaLink( sfx2::LinkManager* pLinkManager, const String& rDoc, + const String& rFlt, const String& rOpt, + const String& rSrc, const ScRange& rDest ) +{ + const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks(); + sal_uInt16 nCount = pLinkManager->GetLinks().Count(); + for (sal_uInt16 i=0; i<nCount; i++) + { + ::sfx2::SvBaseLink* pBase = *rLinks[i]; + if (pBase->ISA(ScAreaLink)) + if ( ((ScAreaLink*)pBase)->IsEqual( rDoc, rFlt, rOpt, rSrc, rDest ) ) + return (ScAreaLink*)pBase; + } + + OSL_FAIL("ScAreaLink nicht gefunden"); + return NULL; +} + + +//============================================================================ +// class ScUndoInsertAreaLink +// +// Bereichs-Verknuepfung einfuegen + +//---------------------------------------------------------------------------- + +ScUndoInsertAreaLink::ScUndoInsertAreaLink( ScDocShell* pShell, + const String& rDoc, + const String& rFlt, const String& rOpt, + const String& rArea, const ScRange& rDestRange, + sal_uLong nRefresh ) + // + : ScSimpleUndo ( pShell ), + // + aDocName ( rDoc ), + aFltName ( rFlt ), + aOptions ( rOpt ), + aAreaName ( rArea ), + aRange ( rDestRange ), + nRefreshDelay ( nRefresh ) +{ +} + + +//---------------------------------------------------------------------------- + +ScUndoInsertAreaLink::~ScUndoInsertAreaLink() +{ +} + + +//---------------------------------------------------------------------------- + +String ScUndoInsertAreaLink::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK ); +} + + +//---------------------------------------------------------------------------- + +void ScUndoInsertAreaLink::Undo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + + ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aDocName, aFltName, aOptions, + aAreaName, aRange ); + if (pLink) + pLinkManager->Remove( pLink ); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator +} + + +//---------------------------------------------------------------------------- + +void ScUndoInsertAreaLink::Redo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + + ScAreaLink* pLink = new ScAreaLink( pDocShell, aDocName, aFltName, aOptions, + aAreaName, aRange.aStart, nRefreshDelay ); + pLink->SetInCreate( sal_True ); + pLink->SetDestArea( aRange ); + pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aDocName, &aFltName, &aAreaName ); + pLink->Update(); + pLink->SetInCreate( false ); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator +} + + +//---------------------------------------------------------------------------- + +void ScUndoInsertAreaLink::Repeat(SfxRepeatTarget& /* rTarget */) +{ + //! .... +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoInsertAreaLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +//============================================================================ +// class ScUndoRemoveAreaLink +// +// Bereichs-Verknuepfung loeschen + +//---------------------------------------------------------------------------- + +ScUndoRemoveAreaLink::ScUndoRemoveAreaLink( ScDocShell* pShell, + const String& rDoc, const String& rFlt, const String& rOpt, + const String& rArea, const ScRange& rDestRange, + sal_uLong nRefresh ) + // + : ScSimpleUndo ( pShell ), + // + aDocName ( rDoc ), + aFltName ( rFlt ), + aOptions ( rOpt ), + aAreaName ( rArea ), + aRange ( rDestRange ), + nRefreshDelay ( nRefresh ) +{ +} + + +//---------------------------------------------------------------------------- + +ScUndoRemoveAreaLink::~ScUndoRemoveAreaLink() +{ +} + + +//---------------------------------------------------------------------------- + +String ScUndoRemoveAreaLink::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_REMOVELINK ); //! eigener Text ?? +} + + +//---------------------------------------------------------------------------- + +void ScUndoRemoveAreaLink::Undo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + + ScAreaLink* pLink = new ScAreaLink( pDocShell, aDocName, aFltName, aOptions, + aAreaName, aRange.aStart, nRefreshDelay ); + pLink->SetInCreate( sal_True ); + pLink->SetDestArea( aRange ); + pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aDocName, &aFltName, &aAreaName ); + pLink->Update(); + pLink->SetInCreate( false ); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator +} + + +//---------------------------------------------------------------------------- + +void ScUndoRemoveAreaLink::Redo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + + ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aDocName, aFltName, aOptions, + aAreaName, aRange ); + if (pLink) + pLinkManager->Remove( pLink ); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator +} + + +//---------------------------------------------------------------------------- + +void ScUndoRemoveAreaLink::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoRemoveAreaLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +//============================================================================ +// class ScUndoUpdateAreaLink +// +// Bereichs-Verknuepfung aktualisieren + +//---------------------------------------------------------------------------- + +ScUndoUpdateAreaLink::ScUndoUpdateAreaLink( ScDocShell* pShell, + const String& rOldD, const String& rOldF, const String& rOldO, + const String& rOldA, const ScRange& rOldR, sal_uLong nOldRD, + const String& rNewD, const String& rNewF, const String& rNewO, + const String& rNewA, const ScRange& rNewR, sal_uLong nNewRD, + ScDocument* pUndo, ScDocument* pRedo, sal_Bool bDoInsert ) + // + : ScSimpleUndo( pShell ), + // + aOldDoc ( rOldD ), + aOldFlt ( rOldF ), + aOldOpt ( rOldO ), + aOldArea ( rOldA ), + aOldRange ( rOldR ), + aNewDoc ( rNewD ), + aNewFlt ( rNewF ), + aNewOpt ( rNewO ), + aNewArea ( rNewA ), + aNewRange ( rNewR ), + pUndoDoc ( pUndo ), + pRedoDoc ( pRedo ), + nOldRefresh ( nOldRD ), + nNewRefresh ( nNewRD ), + bWithInsert ( bDoInsert ) +{ + DBG_ASSERT( aOldRange.aStart == aNewRange.aStart, "AreaLink verschoben ?" ); +} + + +//---------------------------------------------------------------------------- + +ScUndoUpdateAreaLink::~ScUndoUpdateAreaLink() +{ + delete pUndoDoc; + delete pRedoDoc; +} + + +//---------------------------------------------------------------------------- + +String ScUndoUpdateAreaLink::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_UPDATELINK ); //! eigener Text ?? +} + + +//---------------------------------------------------------------------------- + +void ScUndoUpdateAreaLink::DoChange( const sal_Bool bUndo ) const +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + SCCOL nEndX = Max( aOldRange.aEnd.Col(), aNewRange.aEnd.Col() ); + SCROW nEndY = Max( aOldRange.aEnd.Row(), aNewRange.aEnd.Row() ); + SCTAB nEndZ = Max( aOldRange.aEnd.Tab(), aNewRange.aEnd.Tab() ); //? + + if ( bUndo ) + { + if ( bWithInsert ) + { + pDoc->FitBlock( aNewRange, aOldRange ); + pDoc->DeleteAreaTab( aOldRange, IDF_ALL & ~IDF_NOTE ); + pUndoDoc->UndoToDocument( aOldRange, IDF_ALL & ~IDF_NOTE, false, pDoc ); + } + else + { + ScRange aCopyRange( aOldRange.aStart, ScAddress(nEndX,nEndY,nEndZ) ); + pDoc->DeleteAreaTab( aCopyRange, IDF_ALL & ~IDF_NOTE ); + pUndoDoc->CopyToDocument( aCopyRange, IDF_ALL & ~IDF_NOTE, false, pDoc ); + } + } + else + { + if ( bWithInsert ) + { + pDoc->FitBlock( aOldRange, aNewRange ); + pDoc->DeleteAreaTab( aNewRange, IDF_ALL & ~IDF_NOTE ); + pRedoDoc->CopyToDocument( aNewRange, IDF_ALL & ~IDF_NOTE, false, pDoc ); + } + else + { + ScRange aCopyRange( aOldRange.aStart, ScAddress(nEndX,nEndY,nEndZ) ); + pDoc->DeleteAreaTab( aCopyRange, IDF_ALL & ~IDF_NOTE ); + pRedoDoc->CopyToDocument( aCopyRange, IDF_ALL & ~IDF_NOTE, false, pDoc ); + } + } + + ScRange aWorkRange( aNewRange.aStart, ScAddress( nEndX, nEndY, nEndZ ) ); + pDoc->ExtendMerge( aWorkRange, sal_True ); + + // Paint + + if ( aNewRange.aEnd.Col() != aOldRange.aEnd.Col() ) + aWorkRange.aEnd.SetCol(MAXCOL); + if ( aNewRange.aEnd.Row() != aOldRange.aEnd.Row() ) + aWorkRange.aEnd.SetRow(MAXROW); + + if ( !pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), aWorkRange.aStart.Tab() ) ) + pDocShell->PostPaint( aWorkRange, PAINT_GRID ); + + pDocShell->PostDataChanged(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->CellContentChanged(); +} + + +//---------------------------------------------------------------------------- + +void ScUndoUpdateAreaLink::Undo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aNewDoc, aNewFlt, aNewOpt, + aNewArea, aNewRange ); + if (pLink) + { + pLink->SetSource( aOldDoc, aOldFlt, aOldOpt, aOldArea ); // alte Werte im Link + pLink->SetDestArea( aOldRange ); + pLink->SetRefreshDelay( nOldRefresh ); + } + + DoChange(sal_True); +} + + +//---------------------------------------------------------------------------- + +void ScUndoUpdateAreaLink::Redo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aOldDoc, aOldFlt, aOldOpt, + aOldArea, aOldRange ); + if (pLink) + { + pLink->SetSource( aNewDoc, aNewFlt, aNewOpt, aNewArea ); // neue Werte im Link + pLink->SetDestArea( aNewRange ); + pLink->SetRefreshDelay( nNewRefresh ); + } + + DoChange(false); +} + + +//---------------------------------------------------------------------------- + +void ScUndoUpdateAreaLink::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScUndoUpdateAreaLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undocell.cxx b/sc/source/ui/undo/undocell.cxx new file mode 100644 index 000000000000..9743cf42c193 --- /dev/null +++ b/sc/source/ui/undo/undocell.cxx @@ -0,0 +1,1147 @@ +/* -*- 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_sc.hxx" + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <editeng/editobj.hxx> +#include <svl/zforlist.hxx> +#include <sfx2/app.hxx> + +#include "undocell.hxx" +#include "document.hxx" +#include "docpool.hxx" +#include "patattr.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "cell.hxx" +#include "target.hxx" +#include "undoolk.hxx" +#include "detdata.hxx" +#include "stlpool.hxx" +#include "printfun.hxx" +#include "rangenam.hxx" +#include "chgtrack.hxx" +#include "sc.hrc" +#include "docuno.hxx" + +using ::boost::shared_ptr; + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1(ScUndoCursorAttr, ScSimpleUndo); +TYPEINIT1(ScUndoEnterData, ScSimpleUndo); +TYPEINIT1(ScUndoEnterValue, ScSimpleUndo); +TYPEINIT1(ScUndoPutCell, ScSimpleUndo); +TYPEINIT1(ScUndoPageBreak, ScSimpleUndo); +TYPEINIT1(ScUndoPrintZoom, ScSimpleUndo); +TYPEINIT1(ScUndoThesaurus, ScSimpleUndo); +TYPEINIT1(ScUndoReplaceNote, ScSimpleUndo); +TYPEINIT1(ScUndoShowHideNote, ScSimpleUndo); +TYPEINIT1(ScUndoDetective, ScSimpleUndo); +TYPEINIT1(ScUndoRangeNames, ScSimpleUndo); + + +// ----------------------------------------------------------------------- +// +// Attribute auf Cursor anwenden +// + +ScUndoCursorAttr::ScUndoCursorAttr( ScDocShell* pNewDocShell, + SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab, + const ScPatternAttr* pOldPat, const ScPatternAttr* pNewPat, + const ScPatternAttr* pApplyPat, sal_Bool bAutomatic ) : + ScSimpleUndo( pNewDocShell ), + nCol( nNewCol ), + nRow( nNewRow ), + nTab( nNewTab ), + pOldEditData( static_cast<EditTextObject*>(NULL) ), + pNewEditData( static_cast<EditTextObject*>(NULL) ), + bIsAutomatic( bAutomatic ) +{ + ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool(); + pNewPattern = (ScPatternAttr*) &pPool->Put( *pNewPat ); + pOldPattern = (ScPatternAttr*) &pPool->Put( *pOldPat ); + pApplyPattern = (ScPatternAttr*) &pPool->Put( *pApplyPat ); +} + +ScUndoCursorAttr::~ScUndoCursorAttr() +{ + ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool(); + pPool->Remove(*pNewPattern); + pPool->Remove(*pOldPattern); + pPool->Remove(*pApplyPattern); +} + +String ScUndoCursorAttr::GetComment() const +{ + //! eigener Text fuer automatische Attributierung + + sal_uInt16 nId = STR_UNDO_CURSORATTR; // "Attribute" + return ScGlobal::GetRscString( nId ); +} + +void ScUndoCursorAttr::SetEditData( EditTextObject* pOld, EditTextObject* pNew ) +{ + pOldEditData.reset(pOld); + pNewEditData.reset(pNew); +} + +void ScUndoCursorAttr::DoChange( const ScPatternAttr* pWhichPattern, const shared_ptr<EditTextObject>& pEditData ) const +{ + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->SetPattern( nCol, nRow, nTab, *pWhichPattern, true ); + + ScBaseCell* pCell; + pDoc->GetCell(nCol, nRow, nTab, pCell); + if (pCell && pCell->GetCellType() == CELLTYPE_EDIT && pEditData.get()) + static_cast<ScEditCell*>(pCell)->SetData(pEditData.get(), NULL); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->SetTabNo( nTab ); + pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false ); + pViewShell->AdjustBlockHeight(); + } + + const SfxItemSet& rApplySet = pApplyPattern->GetItemSet(); + sal_Bool bPaintExt = ( rApplySet.GetItemState( ATTR_SHADOW, sal_True ) != SFX_ITEM_DEFAULT || + rApplySet.GetItemState( ATTR_CONDITIONAL, sal_True ) != SFX_ITEM_DEFAULT ); + sal_Bool bPaintRows = ( rApplySet.GetItemState( ATTR_HOR_JUSTIFY, sal_True ) != SFX_ITEM_DEFAULT ); + + sal_uInt16 nFlags = SC_PF_TESTMERGE; + if (bPaintExt) + nFlags |= SC_PF_LINES; + if (bPaintRows) + nFlags |= SC_PF_WHOLEROWS; + pDocShell->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nFlags ); +} + +void ScUndoCursorAttr::Undo() +{ + BeginUndo(); + DoChange(pOldPattern, pOldEditData); + + if ( bIsAutomatic ) + { + // wenn automatische Formatierung rueckgaengig gemacht wird, + // soll auch nicht weiter automatisch formatiert werden: + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->ForgetFormatArea(); + } + + EndUndo(); +} + +void ScUndoCursorAttr::Redo() +{ + BeginRedo(); + DoChange(pNewPattern, pNewEditData); + EndRedo(); +} + +void ScUndoCursorAttr::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->ApplySelectionPattern( *pApplyPattern ); +} + +sal_Bool ScUndoCursorAttr::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Daten eingeben +// + +ScUndoEnterData::ScUndoEnterData( ScDocShell* pNewDocShell, + SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab, + SCTAB nNewCount, SCTAB* pNewTabs, ScBaseCell** ppOldData, + sal_Bool* pHasForm, sal_uLong* pOldForm, + const String& rNewStr, EditTextObject* pObj ) : + ScSimpleUndo( pNewDocShell ), + aNewString( rNewStr ), + pTabs( pNewTabs ), + ppOldCells( ppOldData ), + pHasFormat( pHasForm ), + pOldFormats( pOldForm ), + pNewEditData( pObj ), + nCol( nNewCol ), + nRow( nNewRow ), + nTab( nNewTab ), + nCount( nNewCount ) +{ + SetChangeTrack(); +} + +ScUndoEnterData::~ScUndoEnterData() +{ + for (sal_uInt16 i=0; i<nCount; i++) + if (ppOldCells[i]) + ppOldCells[i]->Delete(); + delete[] ppOldCells; + + delete[] pHasFormat; + delete[] pOldFormats; + delete[] pTabs; + + delete pNewEditData; +} + +String ScUndoEnterData::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe" +} + +void ScUndoEnterData::DoChange() const +{ + // Zeilenhoehe anpassen + //! nur wenn noetig (alte oder neue EditZelle, oder Attribute) ?? + for (sal_uInt16 i=0; i<nCount; i++) + pDocShell->AdjustRowHeight( nRow, nRow, pTabs[i] ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->SetTabNo( nTab ); + pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false ); + } + + pDocShell->PostDataChanged(); +} + +void ScUndoEnterData::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + { + nEndChangeAction = pChangeTrack->GetActionMax() + 1; + ScAddress aPos( nCol, nRow, nTab ); + for (sal_uInt16 i=0; i<nCount; i++) + { + aPos.SetTab( pTabs[i] ); + sal_uLong nFormat = 0; + if ( pHasFormat && pOldFormats ) + { + if ( pHasFormat[i] ) + nFormat = pOldFormats[i]; + } + pChangeTrack->AppendContent( aPos, ppOldCells[i], nFormat ); + } + if ( nEndChangeAction > pChangeTrack->GetActionMax() ) + nEndChangeAction = 0; // nichts appended + } + else + nEndChangeAction = 0; +} + +void ScUndoEnterData::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + for (sal_uInt16 i=0; i<nCount; i++) + { + ScBaseCell* pNewCell = ppOldCells[i] ? ppOldCells[i]->CloneWithoutNote( *pDoc, SC_CLONECELL_STARTLISTENING ) : 0; + pDoc->PutCell( nCol, nRow, pTabs[i], pNewCell ); + + if (pHasFormat && pOldFormats) + { + if ( pHasFormat[i] ) + pDoc->ApplyAttr( nCol, nRow, pTabs[i], + SfxUInt32Item( ATTR_VALUE_FORMAT, pOldFormats[i] ) ); + else + { + ScPatternAttr aPattern( *pDoc->GetPattern( nCol, nRow, pTabs[i] ) ); + aPattern.GetItemSet().ClearItem( ATTR_VALUE_FORMAT ); + pDoc->SetPattern( nCol, nRow, pTabs[i], aPattern, sal_True ); + } + } + pDocShell->PostPaintCell( nCol, nRow, pTabs[i] ); + } + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack && nEndChangeAction >= sal::static_int_cast<sal_uLong>(nCount) ) + pChangeTrack->Undo( nEndChangeAction - nCount + 1, nEndChangeAction ); + + DoChange(); + EndUndo(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocShell->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + for ( sal_uInt16 i = 0; i < nCount; ++i ) + { + aChangeRanges.Append( ScRange( nCol, nRow, pTabs[i] ) ); + } + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } +} + +void ScUndoEnterData::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + for (sal_uInt16 i=0; i<nCount; i++) + { + if (pNewEditData) + pDoc->PutCell( nCol, nRow, pTabs[i], new ScEditCell( pNewEditData, + pDoc, NULL ) ); + else + pDoc->SetString( nCol, nRow, pTabs[i], aNewString ); + pDocShell->PostPaintCell( nCol, nRow, pTabs[i] ); + } + + SetChangeTrack(); + + DoChange(); + EndRedo(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocShell->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + for ( sal_uInt16 i = 0; i < nCount; ++i ) + { + aChangeRanges.Append( ScRange( nCol, nRow, pTabs[i] ) ); + } + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } +} + +void ScUndoEnterData::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + String aTemp = aNewString; + ((ScTabViewTarget&)rTarget).GetViewShell()->EnterDataAtCursor( aTemp ); + } +} + +sal_Bool ScUndoEnterData::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Wert aendern +// + +ScUndoEnterValue::ScUndoEnterValue( ScDocShell* pNewDocShell, const ScAddress& rNewPos, + ScBaseCell* pUndoCell, double nVal, sal_Bool bHeight ) : + ScSimpleUndo( pNewDocShell ), + aPos ( rNewPos ), + pOldCell ( pUndoCell ), + nValue ( nVal ), + bNeedHeight ( bHeight ) +{ + SetChangeTrack(); +} + +ScUndoEnterValue::~ScUndoEnterValue() +{ + if (pOldCell) + pOldCell->Delete(); +} + +String ScUndoEnterValue::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe" +} + +void ScUndoEnterValue::SetChangeTrack() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + { + nEndChangeAction = pChangeTrack->GetActionMax() + 1; + pChangeTrack->AppendContent( aPos, pOldCell ); + if ( nEndChangeAction > pChangeTrack->GetActionMax() ) + nEndChangeAction = 0; // nichts appended + } + else + nEndChangeAction = 0; +} + +void ScUndoEnterValue::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScBaseCell* pNewCell = pOldCell ? pOldCell->CloneWithoutNote( *pDoc, SC_CLONECELL_STARTLISTENING ) : 0; + + pDoc->PutCell( aPos, pNewCell ); + + pDocShell->PostPaintCell( aPos ); + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nEndChangeAction, nEndChangeAction ); + + EndUndo(); +} + +void ScUndoEnterValue::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->SetValue( aPos.Col(), aPos.Row(), aPos.Tab(), nValue ); + pDocShell->PostPaintCell( aPos ); + + SetChangeTrack(); + + EndRedo(); +} + +void ScUndoEnterValue::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + +sal_Bool ScUndoEnterValue::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +// ----------------------------------------------------------------------- +// +// Beliebige Zelle eingeben +// + +ScUndoPutCell::ScUndoPutCell( ScDocShell* pNewDocShell, const ScAddress& rNewPos, + ScBaseCell* pUndoCell, ScBaseCell* pRedoCell, sal_Bool bHeight ) : + ScSimpleUndo( pNewDocShell ), + aPos ( rNewPos ), + pOldCell ( pUndoCell ), + pEnteredCell( pRedoCell ), + bNeedHeight ( bHeight ) +{ + SetChangeTrack(); +} + +ScUndoPutCell::~ScUndoPutCell() +{ + if (pOldCell) + pOldCell->Delete(); + if (pEnteredCell) + pEnteredCell->Delete(); +} + +String ScUndoPutCell::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe" +} + +void ScUndoPutCell::SetChangeTrack() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + { + nEndChangeAction = pChangeTrack->GetActionMax() + 1; + pChangeTrack->AppendContent( aPos, pOldCell ); + if ( nEndChangeAction > pChangeTrack->GetActionMax() ) + nEndChangeAction = 0; // nichts appended + } + else + nEndChangeAction = 0; +} + +void ScUndoPutCell::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScBaseCell* pNewCell = pOldCell ? pOldCell->CloneWithoutNote( *pDoc, aPos, SC_CLONECELL_STARTLISTENING ) : 0; + + pDoc->PutCell( aPos.Col(), aPos.Row(), aPos.Tab(), pNewCell ); + + pDocShell->PostPaintCell( aPos ); + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nEndChangeAction, nEndChangeAction ); + + EndUndo(); +} + +void ScUndoPutCell::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScBaseCell* pNewCell = pEnteredCell ? pEnteredCell->CloneWithoutNote( *pDoc, aPos, SC_CLONECELL_STARTLISTENING ) : 0; + + pDoc->PutCell( aPos.Col(), aPos.Row(), aPos.Tab(), pNewCell ); + + pDocShell->PostPaintCell( aPos ); + + SetChangeTrack(); + + EndRedo(); +} + +void ScUndoPutCell::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + +sal_Bool ScUndoPutCell::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +// ----------------------------------------------------------------------- +// +// Seitenumbrueche +// + +ScUndoPageBreak::ScUndoPageBreak( ScDocShell* pNewDocShell, + SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab, + sal_Bool bNewColumn, sal_Bool bNewInsert ) : + ScSimpleUndo( pNewDocShell ), + nCol( nNewCol ), + nRow( nNewRow ), + nTab( nNewTab ), + bColumn( bNewColumn ), + bInsert( bNewInsert ) +{ +} + +ScUndoPageBreak::~ScUndoPageBreak() +{ +} + +String ScUndoPageBreak::GetComment() const +{ + //"Spaltenumbruch" | "Zeilenumbruch" "einfuegen" | "loeschen" + return String ( bColumn ? + ( bInsert ? + ScGlobal::GetRscString( STR_UNDO_INSCOLBREAK ) : + ScGlobal::GetRscString( STR_UNDO_DELCOLBREAK ) + ) : + ( bInsert ? + ScGlobal::GetRscString( STR_UNDO_INSROWBREAK ) : + ScGlobal::GetRscString( STR_UNDO_DELROWBREAK ) + ) ); +} + +void ScUndoPageBreak::DoChange( sal_Bool bInsertP ) const +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + if (pViewShell) + { + pViewShell->SetTabNo( nTab ); + pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false ); + + if (bInsertP) + pViewShell->InsertPageBreak(bColumn, false); + else + pViewShell->DeletePageBreak(bColumn, false); + + pDocShell->GetDocument()->InvalidatePageBreaks(nTab); + } +} + +void ScUndoPageBreak::Undo() +{ + BeginUndo(); + DoChange(!bInsert); + EndUndo(); +} + +void ScUndoPageBreak::Redo() +{ + BeginRedo(); + DoChange(bInsert); + EndRedo(); +} + +void ScUndoPageBreak::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + + if (bInsert) + rViewShell.InsertPageBreak(bColumn, sal_True); + else + rViewShell.DeletePageBreak(bColumn, sal_True); + } +} + +sal_Bool ScUndoPageBreak::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// ----------------------------------------------------------------------- +// +// Druck-Skalierung +// + +ScUndoPrintZoom::ScUndoPrintZoom( ScDocShell* pNewDocShell, + SCTAB nT, sal_uInt16 nOS, sal_uInt16 nOP, sal_uInt16 nNS, sal_uInt16 nNP ) : + ScSimpleUndo( pNewDocShell ), + nTab( nT ), + nOldScale( nOS ), + nOldPages( nOP ), + nNewScale( nNS ), + nNewPages( nNP ) +{ +} + +ScUndoPrintZoom::~ScUndoPrintZoom() +{ +} + +String ScUndoPrintZoom::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_PRINTSCALE ); +} + +void ScUndoPrintZoom::DoChange( sal_Bool bUndo ) +{ + sal_uInt16 nScale = bUndo ? nOldScale : nNewScale; + sal_uInt16 nPages = bUndo ? nOldPages : nNewPages; + + ScDocument* pDoc = pDocShell->GetDocument(); + String aStyleName = pDoc->GetPageStyle( nTab ); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE ); + DBG_ASSERT( pStyleSheet, "PageStyle not found" ); + if ( pStyleSheet ) + { + SfxItemSet& rSet = pStyleSheet->GetItemSet(); + rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) ); + rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) ); + + ScPrintFunc aPrintFunc( pDocShell, pDocShell->GetPrinter(), nTab ); + aPrintFunc.UpdatePages(); + } +} + +void ScUndoPrintZoom::Undo() +{ + BeginUndo(); + DoChange(sal_True); + EndUndo(); +} + +void ScUndoPrintZoom::Redo() +{ + BeginRedo(); + DoChange(false); + EndRedo(); +} + +void ScUndoPrintZoom::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + ScViewData* pViewData = rViewShell.GetViewData(); + pViewData->GetDocShell()->SetPrintZoom( pViewData->GetTabNo(), nNewScale, nNewPages ); + } +} + +sal_Bool ScUndoPrintZoom::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Thesaurus +// + +ScUndoThesaurus::ScUndoThesaurus( ScDocShell* pNewDocShell, + SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab, + const String& rNewUndoStr, const EditTextObject* pUndoTObj, + const String& rNewRedoStr, const EditTextObject* pRedoTObj) : + ScSimpleUndo( pNewDocShell ), + nCol( nNewCol ), + nRow( nNewRow ), + nTab( nNewTab ), + aUndoStr( rNewUndoStr ), + aRedoStr( rNewRedoStr ) +{ + pUndoTObject = (pUndoTObj) ? pUndoTObj->Clone() : NULL; + pRedoTObject = (pRedoTObj) ? pRedoTObj->Clone() : NULL; + + ScBaseCell* pOldCell; + if ( pUndoTObject ) + pOldCell = new ScEditCell( pUndoTObject, pDocShell->GetDocument(), NULL ); + else + pOldCell = new ScStringCell( aUndoStr ); + SetChangeTrack( pOldCell ); + pOldCell->Delete(); +} + +ScUndoThesaurus::~ScUndoThesaurus() +{ + delete pUndoTObject; + delete pRedoTObject; +} + +String ScUndoThesaurus::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_THESAURUS ); // "Thesaurus" +} + +void ScUndoThesaurus::SetChangeTrack( ScBaseCell* pOldCell ) +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + { + nEndChangeAction = pChangeTrack->GetActionMax() + 1; + pChangeTrack->AppendContent( ScAddress( nCol, nRow, nTab ), pOldCell ); + if ( nEndChangeAction > pChangeTrack->GetActionMax() ) + nEndChangeAction = 0; // nichts appended + } + else + nEndChangeAction = 0; +} + +void ScUndoThesaurus::DoChange( sal_Bool bUndo, const String& rStr, + const EditTextObject* pTObj ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->SetTabNo( nTab ); + pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, false, false ); + } + + if (pTObj) + { + ScBaseCell* pCell; + pDoc->GetCell( nCol, nRow, nTab, pCell ); + if (pCell) + { + if (pCell->GetCellType() == CELLTYPE_EDIT ) + { + ScEditCell* pNewCell = new ScEditCell( pTObj, pDoc, NULL ); + pDoc->PutCell( nCol, nRow, nTab, pNewCell ); + if ( !bUndo ) + SetChangeTrack( pCell ); + } + else + { + OSL_FAIL("Nicht CELLTYPE_EDIT bei Un/RedoThesaurus"); + } + } + } + else + { + ScBaseCell* pCell = NULL; + if ( !bUndo ) + pDoc->GetCell( nCol, nRow, nTab, pCell ); + pDoc->SetString( nCol, nRow, nTab, rStr ); + if ( !bUndo ) + SetChangeTrack( pCell ); + } + + pDocShell->PostPaintCell( nCol, nRow, nTab ); +} + +void ScUndoThesaurus::Undo() +{ + BeginUndo(); + DoChange( sal_True, aUndoStr, pUndoTObject ); + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nEndChangeAction, nEndChangeAction ); + EndUndo(); +} + +void ScUndoThesaurus::Redo() +{ + BeginRedo(); + DoChange( false, aRedoStr, pRedoTObject ); + EndRedo(); +} + +void ScUndoThesaurus::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->DoThesaurus( sal_True ); +} + +sal_Bool ScUndoThesaurus::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ============================================================================ + +ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos, + const ScNoteData& rNoteData, bool bInsert, SdrUndoAction* pDrawUndo ) : + ScSimpleUndo( &rDocShell ), + maPos( rPos ), + mpDrawUndo( pDrawUndo ) +{ + DBG_ASSERT( rNoteData.mpCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note caption" ); + (bInsert ? maNewData : maOldData) = rNoteData; +} + +ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos, + const ScNoteData& rOldData, const ScNoteData& rNewData, SdrUndoAction* pDrawUndo ) : + ScSimpleUndo( &rDocShell ), + maPos( rPos ), + maOldData( rOldData ), + maNewData( rNewData ), + mpDrawUndo( pDrawUndo ) +{ + DBG_ASSERT( maOldData.mpCaption || maNewData.mpCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" ); + DBG_ASSERT( !maOldData.mxInitData.get() && !maNewData.mxInitData.get(), "ScUndoReplaceNote::ScUndoReplaceNote - unexpected unitialized note" ); +} + +ScUndoReplaceNote::~ScUndoReplaceNote() +{ + DeleteSdrUndoAction( mpDrawUndo ); +} + +void ScUndoReplaceNote::Undo() +{ + BeginUndo(); + DoSdrUndoAction( mpDrawUndo, pDocShell->GetDocument() ); + /* Undo insert -> remove new note. + Undo remove -> insert old note. + Undo replace -> remove new note, insert old note. */ + DoRemoveNote( maNewData ); + DoInsertNote( maOldData ); + pDocShell->PostPaintCell( maPos ); + EndUndo(); +} + +void ScUndoReplaceNote::Redo() +{ + BeginRedo(); + RedoSdrUndoAction( mpDrawUndo ); + /* Redo insert -> insert new note. + Redo remove -> remove old note. + Redo replace -> remove old note, insert new note. */ + DoRemoveNote( maOldData ); + DoInsertNote( maNewData ); + pDocShell->PostPaintCell( maPos ); + EndRedo(); +} + +void ScUndoReplaceNote::Repeat( SfxRepeatTarget& /*rTarget*/ ) +{ +} + +sal_Bool ScUndoReplaceNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const +{ + return false; +} + +String ScUndoReplaceNote::GetComment() const +{ + return ScGlobal::GetRscString( maNewData.mpCaption ? + (maOldData.mpCaption ? STR_UNDO_EDITNOTE : STR_UNDO_INSERTNOTE) : STR_UNDO_DELETENOTE ); +} + +void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData ) +{ + if( rNoteData.mpCaption ) + { + ScDocument& rDoc = *pDocShell->GetDocument(); + DBG_ASSERT( !rDoc.GetNote( maPos ), "ScUndoReplaceNote::DoInsertNote - unexpected cell note" ); + ScPostIt* pNote = new ScPostIt( rDoc, maPos, rNoteData, false ); + rDoc.TakeNote( maPos, pNote ); + } +} + +void ScUndoReplaceNote::DoRemoveNote( const ScNoteData& rNoteData ) +{ + if( rNoteData.mpCaption ) + { + ScDocument& rDoc = *pDocShell->GetDocument(); + DBG_ASSERT( rDoc.GetNote( maPos ), "ScUndoReplaceNote::DoRemoveNote - missing cell note" ); + if( ScPostIt* pNote = rDoc.ReleaseNote( maPos ) ) + { + /* Forget pointer to caption object to suppress removing the + caption object from the drawing layer while deleting pNote + (removing the caption is done by a drawing undo action). */ + pNote->ForgetCaption(); + delete pNote; + } + } +} + +// ============================================================================ + +ScUndoShowHideNote::ScUndoShowHideNote( ScDocShell& rDocShell, const ScAddress& rPos, bool bShow ) : + ScSimpleUndo( &rDocShell ), + maPos( rPos ), + mbShown( bShow ) +{ +} + +ScUndoShowHideNote::~ScUndoShowHideNote() +{ +} + +void ScUndoShowHideNote::Undo() +{ + BeginUndo(); + if( ScPostIt* pNote = pDocShell->GetDocument()->GetNote( maPos ) ) + pNote->ShowCaption( maPos, !mbShown ); + EndUndo(); +} + +void ScUndoShowHideNote::Redo() +{ + BeginRedo(); + if( ScPostIt* pNote = pDocShell->GetDocument()->GetNote( maPos ) ) + pNote->ShowCaption( maPos, mbShown ); + EndRedo(); +} + +void ScUndoShowHideNote::Repeat( SfxRepeatTarget& /*rTarget*/ ) +{ +} + +sal_Bool ScUndoShowHideNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const +{ + return false; +} + +String ScUndoShowHideNote::GetComment() const +{ + return ScGlobal::GetRscString( mbShown ? STR_UNDO_SHOWNOTE : STR_UNDO_HIDENOTE ); +} + +// ============================================================================ + +// ----------------------------------------------------------------------- +// +// Detektiv +// + +ScUndoDetective::ScUndoDetective( ScDocShell* pNewDocShell, + SdrUndoAction* pDraw, const ScDetOpData* pOperation, + ScDetOpList* pUndoList ) : + ScSimpleUndo( pNewDocShell ), + pOldList ( pUndoList ), + nAction ( 0 ), + pDrawUndo ( pDraw ) +{ + bIsDelete = ( pOperation == NULL ); + if (!bIsDelete) + { + nAction = (sal_uInt16) pOperation->GetOperation(); + aPos = pOperation->GetPos(); + } +} + +ScUndoDetective::~ScUndoDetective() +{ + DeleteSdrUndoAction( pDrawUndo ); + delete pOldList; +} + +String ScUndoDetective::GetComment() const +{ + sal_uInt16 nId = STR_UNDO_DETDELALL; + if ( !bIsDelete ) + switch ( (ScDetOpType) nAction ) + { + case SCDETOP_ADDSUCC: nId = STR_UNDO_DETADDSUCC; break; + case SCDETOP_DELSUCC: nId = STR_UNDO_DETDELSUCC; break; + case SCDETOP_ADDPRED: nId = STR_UNDO_DETADDPRED; break; + case SCDETOP_DELPRED: nId = STR_UNDO_DETDELPRED; break; + case SCDETOP_ADDERROR: nId = STR_UNDO_DETADDERROR; break; + } + + return ScGlobal::GetRscString( nId ); +} + + +void ScUndoDetective::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + DoSdrUndoAction(pDrawUndo, pDoc); + + if (bIsDelete) + { + if ( pOldList ) + pDoc->SetDetOpList( new ScDetOpList(*pOldList) ); + } + else + { + // Eintrag aus der Liste loeschen + + ScDetOpList* pList = pDoc->GetDetOpList(); + if (pList && pList->Count()) + { + sal_uInt16 nPos = pList->Count() - 1; + ScDetOpData* pData = (*pList)[nPos]; + if ( pData->GetOperation() == (ScDetOpType) nAction && pData->GetPos() == aPos ) + pList->DeleteAndDestroy( nPos, 1 ); + else + { + OSL_FAIL("Detektiv-Eintrag in der Liste nicht gefunden"); + } + } + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->RecalcPPT(); //! use broadcast instead? + + EndUndo(); +} + +void ScUndoDetective::Redo() +{ + BeginRedo(); + + RedoSdrUndoAction(pDrawUndo); + + ScDocument* pDoc = pDocShell->GetDocument(); + + if (bIsDelete) + pDoc->ClearDetectiveOperations(); + else + pDoc->AddDetectiveOperation( ScDetOpData( aPos, (ScDetOpType) nAction ) ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->RecalcPPT(); //! use broadcast instead? + + EndRedo(); +} + +void ScUndoDetective::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // hammanich +} + +sal_Bool ScUndoDetective::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + +// ----------------------------------------------------------------------- +// +// Benannte Bereiche +// + +ScUndoRangeNames::ScUndoRangeNames( ScDocShell* pNewDocShell, + ScRangeName* pOld, ScRangeName* pNew ) : + ScSimpleUndo( pNewDocShell ), + pOldRanges ( pOld ), + pNewRanges ( pNew ) +{ +} + +ScUndoRangeNames::~ScUndoRangeNames() +{ + delete pOldRanges; + delete pNewRanges; +} + +String ScUndoRangeNames::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_RANGENAMES ); +} + +void ScUndoRangeNames::DoChange( sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->CompileNameFormula( sal_True ); // CreateFormulaString + + if ( bUndo ) + pDoc->SetRangeName( new ScRangeName( *pOldRanges ) ); + else + pDoc->SetRangeName( new ScRangeName( *pNewRanges ) ); + + pDoc->CompileNameFormula( false ); // CompileFormulaString + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); +} + +void ScUndoRangeNames::Undo() +{ + BeginUndo(); + DoChange( sal_True ); + EndUndo(); +} + +void ScUndoRangeNames::Redo() +{ + BeginRedo(); + DoChange( false ); + EndRedo(); +} + +void ScUndoRangeNames::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // hammanich +} + +sal_Bool ScUndoRangeNames::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx new file mode 100644 index 000000000000..b1c3bc5693ef --- /dev/null +++ b/sc/source/ui/undo/undodat.cxx @@ -0,0 +1,2235 @@ +/* -*- 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_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/app.hxx> + +#include "undodat.hxx" +#include "undoutil.hxx" +#include "undoolk.hxx" +#include "document.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "olinetab.hxx" +#include "dbcolect.hxx" +#include "rangenam.hxx" +#include "pivot.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "globalnames.hxx" +#include "target.hxx" +#include "chartarr.hxx" +#include "dbdocfun.hxx" +#include "olinefun.hxx" +#include "dpobject.hxx" +#include "attrib.hxx" +#include "hints.hxx" +#include "sc.hrc" +#include "chgtrack.hxx" // Amelia Wang +#include "refundo.hxx" // Amelia Wang + +// ----------------------------------------------------------------------- + +TYPEINIT1(ScUndoDoOutline, ScSimpleUndo); +TYPEINIT1(ScUndoMakeOutline, ScSimpleUndo); +TYPEINIT1(ScUndoOutlineLevel, ScSimpleUndo); +TYPEINIT1(ScUndoOutlineBlock, ScSimpleUndo); +TYPEINIT1(ScUndoRemoveAllOutlines, ScSimpleUndo); +TYPEINIT1(ScUndoAutoOutline, ScSimpleUndo); +TYPEINIT1(ScUndoSubTotals, ScDBFuncUndo); +TYPEINIT1(ScUndoSort, ScDBFuncUndo); +TYPEINIT1(ScUndoQuery, ScDBFuncUndo); +TYPEINIT1(ScUndoAutoFilter, ScDBFuncUndo); +TYPEINIT1(ScUndoDBData, ScSimpleUndo); +TYPEINIT1(ScUndoImportData, ScSimpleUndo); +TYPEINIT1(ScUndoRepeatDB, ScSimpleUndo); +TYPEINIT1(ScUndoDataPilot, ScSimpleUndo); +TYPEINIT1(ScUndoConsolidate, ScSimpleUndo); +TYPEINIT1(ScUndoChartData, ScSimpleUndo); +TYPEINIT1(ScUndoDataForm, SfxUndoAction); // amelia + +// ----------------------------------------------------------------------- + + +// +// Outline-Gruppen ein- oder ausblenden +// + +ScUndoDoOutline::ScUndoDoOutline( ScDocShell* pNewDocShell, + SCCOLROW nNewStart, SCCOLROW nNewEnd, SCTAB nNewTab, + ScDocument* pNewUndoDoc, sal_Bool bNewColumns, + sal_uInt16 nNewLevel, sal_uInt16 nNewEntry, sal_Bool bNewShow ) : + ScSimpleUndo( pNewDocShell ), + nStart( nNewStart ), + nEnd( nNewEnd ), + nTab( nNewTab ), + pUndoDoc( pNewUndoDoc ), + bColumns( bNewColumns ), + nLevel( nNewLevel ), + nEntry( nNewEntry ), + bShow( bNewShow ) +{ +} + +ScUndoDoOutline::~ScUndoDoOutline() +{ + delete pUndoDoc; +} + +String ScUndoDoOutline::GetComment() const +{ // Detail einblenden" "Detail ausblenden" + return bShow ? + ScGlobal::GetRscString( STR_UNDO_DOOUTLINE ) : + ScGlobal::GetRscString( STR_UNDO_REDOOUTLINE ); +} + +void ScUndoDoOutline::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + // Tabelle muss vorher umgeschaltet sein (#46952#) !!! + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + // inverse Funktion ausfuehren + + if (bShow) + pViewShell->HideOutline( bColumns, nLevel, nEntry, false, false ); + else + pViewShell->ShowOutline( bColumns, nLevel, nEntry, false, false ); + + // Original Spalten-/Zeilenstatus + + if (bColumns) + pUndoDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, + static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, false, pDoc); + else + pUndoDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, false, pDoc ); + + pViewShell->UpdateScrollBars(); + + pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_GRID|PAINT_LEFT|PAINT_TOP); + + EndUndo(); +} + +void ScUndoDoOutline::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + // Tabelle muss vorher umgeschaltet sein (#46952#) !!! + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + if (bShow) + pViewShell->ShowOutline( bColumns, nLevel, nEntry, false ); + else + pViewShell->HideOutline( bColumns, nLevel, nEntry, false ); + + EndRedo(); +} + +void ScUndoDoOutline::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoDoOutline::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // geht nicht +} + +// +// Outline-Gruppen erzeugen oder loeschen +// + +ScUndoMakeOutline::ScUndoMakeOutline( ScDocShell* pNewDocShell, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, + ScOutlineTable* pNewUndoTab, sal_Bool bNewColumns, sal_Bool bNewMake ) : + ScSimpleUndo( pNewDocShell ), + aBlockStart( nStartX, nStartY, nStartZ ), + aBlockEnd( nEndX, nEndY, nEndZ ), + pUndoTable( pNewUndoTab ), + bColumns( bNewColumns ), + bMake( bNewMake ) +{ +} + +ScUndoMakeOutline::~ScUndoMakeOutline() +{ + delete pUndoTable; +} + +String ScUndoMakeOutline::GetComment() const +{ // "Gruppierung" "Gruppierung aufheben" + return bMake ? + ScGlobal::GetRscString( STR_UNDO_MAKEOUTLINE ) : + ScGlobal::GetRscString( STR_UNDO_REMAKEOUTLINE ); +} + +void ScUndoMakeOutline::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + SCTAB nTab = aBlockStart.Tab(); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart, aBlockEnd ); + + pDoc->SetOutlineTable( nTab, pUndoTable ); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_GRID|PAINT_LEFT|PAINT_TOP|PAINT_SIZE); + + EndUndo(); +} + +void ScUndoMakeOutline::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart, aBlockEnd ); + + if (bMake) + pViewShell->MakeOutline( bColumns, false ); + else + pViewShell->RemoveOutline( bColumns, false ); + + pDocShell->PostPaint(0,0,aBlockStart.Tab(),MAXCOL,MAXROW,aBlockEnd.Tab(),PAINT_GRID); + + EndRedo(); +} + +void ScUndoMakeOutline::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + + if (bMake) + rViewShell.MakeOutline( bColumns, sal_True ); + else + rViewShell.RemoveOutline( bColumns, sal_True ); + } +} + +sal_Bool ScUndoMakeOutline::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// +// Outline-Ebene auswaehlen +// + +ScUndoOutlineLevel::ScUndoOutlineLevel( ScDocShell* pNewDocShell, + SCCOLROW nNewStart, SCCOLROW nNewEnd, SCTAB nNewTab, + ScDocument* pNewUndoDoc, ScOutlineTable* pNewUndoTab, + sal_Bool bNewColumns, sal_uInt16 nNewLevel ) : + ScSimpleUndo( pNewDocShell ), + nStart( nNewStart ), + nEnd( nNewEnd ), + nTab( nNewTab ), + pUndoDoc( pNewUndoDoc ), + pUndoTable( pNewUndoTab ), + bColumns( bNewColumns ), + nLevel( nNewLevel ) +{ +} + +ScUndoOutlineLevel::~ScUndoOutlineLevel() +{ + delete pUndoDoc; + delete pUndoTable; +} + +String ScUndoOutlineLevel::GetComment() const +{ // "Gliederungsebene auswaehlen"; + return ScGlobal::GetRscString( STR_UNDO_OUTLINELEVEL ); +} + +void ScUndoOutlineLevel::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + // Original Outline-Table + + pDoc->SetOutlineTable( nTab, pUndoTable ); + + // Original Spalten-/Zeilenstatus + + if (bColumns) + pUndoDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, + static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, false, pDoc); + else + pUndoDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, false, pDoc ); + + pDoc->UpdatePageBreaks( nTab ); + + pViewShell->UpdateScrollBars(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_GRID|PAINT_LEFT|PAINT_TOP); + + EndUndo(); +} + +void ScUndoOutlineLevel::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + // Tabelle muss vorher umgeschaltet sein (#46952#) !!! + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pViewShell->SelectLevel( bColumns, nLevel, false ); + + EndRedo(); +} + +void ScUndoOutlineLevel::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->SelectLevel( bColumns, nLevel, sal_True ); +} + +sal_Bool ScUndoOutlineLevel::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// +// Outline ueber Blockmarken ein- oder ausblenden +// + +ScUndoOutlineBlock::ScUndoOutlineBlock( ScDocShell* pNewDocShell, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, + ScDocument* pNewUndoDoc, ScOutlineTable* pNewUndoTab, sal_Bool bNewShow ) : + ScSimpleUndo( pNewDocShell ), + aBlockStart( nStartX, nStartY, nStartZ ), + aBlockEnd( nEndX, nEndY, nEndZ ), + pUndoDoc( pNewUndoDoc ), + pUndoTable( pNewUndoTab ), + bShow( bNewShow ) +{ +} + +ScUndoOutlineBlock::~ScUndoOutlineBlock() +{ + delete pUndoDoc; + delete pUndoTable; +} + +String ScUndoOutlineBlock::GetComment() const +{ // "Detail einblenden" "Detail ausblenden" + return bShow ? + ScGlobal::GetRscString( STR_UNDO_DOOUTLINEBLK ) : + ScGlobal::GetRscString( STR_UNDO_REDOOUTLINEBLK ); +} + +void ScUndoOutlineBlock::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + SCTAB nTab = aBlockStart.Tab(); + + // Original Outline-Table + + pDoc->SetOutlineTable( nTab, pUndoTable ); + + // Original Spalten-/Zeilenstatus + + SCCOLROW nStartCol = aBlockStart.Col(); + SCCOLROW nEndCol = aBlockEnd.Col(); + SCCOLROW nStartRow = aBlockStart.Row(); + SCCOLROW nEndRow = aBlockEnd.Row(); + + if (!bShow) + { // Groesse des ausgeblendeten Blocks + sal_uInt16 nLevel; + pUndoTable->GetColArray()->FindTouchedLevel( nStartCol, nEndCol, nLevel ); + pUndoTable->GetColArray()->ExtendBlock( nLevel, nStartCol, nEndCol ); + pUndoTable->GetRowArray()->FindTouchedLevel( nStartRow, nEndRow, nLevel ); + pUndoTable->GetRowArray()->ExtendBlock( nLevel, nStartRow, nEndRow ); + } + + pUndoDoc->CopyToDocument( static_cast<SCCOL>(nStartCol), 0, nTab, + static_cast<SCCOL>(nEndCol), MAXROW, nTab, IDF_NONE, false, pDoc ); + pUndoDoc->CopyToDocument( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab, IDF_NONE, false, pDoc ); + + pDoc->UpdatePageBreaks( nTab ); + + pViewShell->UpdateScrollBars(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_GRID|PAINT_LEFT|PAINT_TOP); + + EndUndo(); +} + +void ScUndoOutlineBlock::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart, aBlockEnd ); + if (bShow) + pViewShell->ShowMarkedOutlines( false ); + else + pViewShell->HideMarkedOutlines( false ); + + EndRedo(); +} + +void ScUndoOutlineBlock::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + + if (bShow) + rViewShell.ShowMarkedOutlines( sal_True ); + else + rViewShell.HideMarkedOutlines( sal_True ); + } +} + +sal_Bool ScUndoOutlineBlock::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// +// alle Outlines loeschen +// + +ScUndoRemoveAllOutlines::ScUndoRemoveAllOutlines( ScDocShell* pNewDocShell, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, + ScDocument* pNewUndoDoc, ScOutlineTable* pNewUndoTab ) : + ScSimpleUndo( pNewDocShell ), + aBlockStart( nStartX, nStartY, nStartZ ), + aBlockEnd( nEndX, nEndY, nEndZ ), + pUndoDoc( pNewUndoDoc ), + pUndoTable( pNewUndoTab ) +{ +} + +ScUndoRemoveAllOutlines::~ScUndoRemoveAllOutlines() +{ + delete pUndoDoc; + delete pUndoTable; +} + +String ScUndoRemoveAllOutlines::GetComment() const +{ // "Gliederung entfernen" + return ScGlobal::GetRscString( STR_UNDO_REMOVEALLOTLNS ); +} + +void ScUndoRemoveAllOutlines::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + SCTAB nTab = aBlockStart.Tab(); + + // Original Outline-Table + + pDoc->SetOutlineTable( nTab, pUndoTable ); + + // Original Spalten-/Zeilenstatus + + SCCOL nStartCol = aBlockStart.Col(); + SCCOL nEndCol = aBlockEnd.Col(); + SCROW nStartRow = aBlockStart.Row(); + SCROW nEndRow = aBlockEnd.Row(); + + pUndoDoc->CopyToDocument( nStartCol, 0, nTab, nEndCol, MAXROW, nTab, IDF_NONE, false, pDoc ); + pUndoDoc->CopyToDocument( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab, IDF_NONE, false, pDoc ); + + pDoc->UpdatePageBreaks( nTab ); + + pViewShell->UpdateScrollBars(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_GRID|PAINT_LEFT|PAINT_TOP|PAINT_SIZE); + + EndUndo(); +} + +void ScUndoRemoveAllOutlines::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + // Tabelle muss vorher umgeschaltet sein (#46952#) !!! + + SCTAB nTab = aBlockStart.Tab(); + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pViewShell->RemoveAllOutlines( false ); + + EndRedo(); +} + +void ScUndoRemoveAllOutlines::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->RemoveAllOutlines( sal_True ); +} + +sal_Bool ScUndoRemoveAllOutlines::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// +// Auto-Outline +// + +ScUndoAutoOutline::ScUndoAutoOutline( ScDocShell* pNewDocShell, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, + ScDocument* pNewUndoDoc, ScOutlineTable* pNewUndoTab ) : + ScSimpleUndo( pNewDocShell ), + aBlockStart( nStartX, nStartY, nStartZ ), + aBlockEnd( nEndX, nEndY, nEndZ ), + pUndoDoc( pNewUndoDoc ), + pUndoTable( pNewUndoTab ) +{ +} + +ScUndoAutoOutline::~ScUndoAutoOutline() +{ + delete pUndoDoc; + delete pUndoTable; +} + +String ScUndoAutoOutline::GetComment() const +{ // "Auto-Gliederung" + return ScGlobal::GetRscString( STR_UNDO_AUTOOUTLINE ); +} + +void ScUndoAutoOutline::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + SCTAB nTab = aBlockStart.Tab(); + + // Original Outline-Table + + pDoc->SetOutlineTable( nTab, pUndoTable ); + + // Original Spalten-/Zeilenstatus + + if (pUndoDoc && pUndoTable) + { + SCCOLROW nStartCol; + SCCOLROW nStartRow; + SCCOLROW nEndCol; + SCCOLROW nEndRow; + pUndoTable->GetColArray()->GetRange( nStartCol, nEndCol ); + pUndoTable->GetRowArray()->GetRange( nStartRow, nEndRow ); + + pUndoDoc->CopyToDocument( static_cast<SCCOL>(nStartCol), 0, nTab, + static_cast<SCCOL>(nEndCol), MAXROW, nTab, IDF_NONE, false, + pDoc); + pUndoDoc->CopyToDocument( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab, IDF_NONE, false, pDoc ); + + pViewShell->UpdateScrollBars(); + } + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_GRID|PAINT_LEFT|PAINT_TOP|PAINT_SIZE); + + EndUndo(); +} + +void ScUndoAutoOutline::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + SCTAB nTab = aBlockStart.Tab(); + if (pViewShell) + { + // Tabelle muss vorher umgeschaltet sein (#46952#) !!! + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + } + + ScRange aRange( aBlockStart.Col(), aBlockStart.Row(), nTab, + aBlockEnd.Col(), aBlockEnd.Row(), nTab ); + ScOutlineDocFunc aFunc( *pDocShell ); + aFunc.AutoOutline( aRange, false, false ); + + // auf der View markieren + // Wenn's beim Aufruf eine Mehrfachselektion war, ist es jetzt der + // umschliessende Bereich... + + if (pViewShell) + pViewShell->MarkRange( aRange ); + + EndRedo(); +} + +void ScUndoAutoOutline::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->AutoOutline( sal_True ); +} + +sal_Bool ScUndoAutoOutline::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// +// Zwischenergebnisse +// + +ScUndoSubTotals::ScUndoSubTotals( ScDocShell* pNewDocShell, SCTAB nNewTab, + const ScSubTotalParam& rNewParam, SCROW nNewEndY, + ScDocument* pNewUndoDoc, ScOutlineTable* pNewUndoTab, + ScRangeName* pNewUndoRange, ScDBCollection* pNewUndoDB ) : + ScDBFuncUndo( pNewDocShell, ScRange( rNewParam.nCol1, rNewParam.nRow1, nNewTab, + rNewParam.nCol2, rNewParam.nRow2, nNewTab ) ), + nTab( nNewTab ), + aParam( rNewParam ), + nNewEndRow( nNewEndY ), + pUndoDoc( pNewUndoDoc ), + pUndoTable( pNewUndoTab ), + pUndoRange( pNewUndoRange ), + pUndoDB( pNewUndoDB ) +{ +} + +ScUndoSubTotals::~ScUndoSubTotals() +{ + delete pUndoDoc; + delete pUndoTable; + delete pUndoRange; + delete pUndoDB; +} + +String ScUndoSubTotals::GetComment() const +{ // "Teilergebnisse" + return ScGlobal::GetRscString( STR_UNDO_SUBTOTALS ); +} + +void ScUndoSubTotals::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + if (nNewEndRow > aParam.nRow2) + { + pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, aParam.nRow2+1, static_cast<SCSIZE>(nNewEndRow-aParam.nRow2) ); + } + else if (nNewEndRow < aParam.nRow2) + { + pDoc->InsertRow( 0,nTab, MAXCOL,nTab, nNewEndRow+1, static_cast<SCSIZE>(aParam.nRow2-nNewEndRow) ); + } + + + // Original Outline-Table + + pDoc->SetOutlineTable( nTab, pUndoTable ); + + // Original Spalten-/Zeilenstatus + + if (pUndoDoc && pUndoTable) + { + SCCOLROW nStartCol; + SCCOLROW nStartRow; + SCCOLROW nEndCol; + SCCOLROW nEndRow; + pUndoTable->GetColArray()->GetRange( nStartCol, nEndCol ); + pUndoTable->GetRowArray()->GetRange( nStartRow, nEndRow ); + + pUndoDoc->CopyToDocument( static_cast<SCCOL>(nStartCol), 0, nTab, + static_cast<SCCOL>(nEndCol), MAXROW, nTab, IDF_NONE, false, + pDoc); + pUndoDoc->CopyToDocument( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab, IDF_NONE, false, pDoc ); + + pViewShell->UpdateScrollBars(); + } + + // Original-Daten & Referenzen + + ScUndoUtil::MarkSimpleBlock( pDocShell, 0, aParam.nRow1+1, nTab, + MAXCOL, aParam.nRow2, nTab ); + + pDoc->DeleteAreaTab( 0,aParam.nRow1+1, MAXCOL,aParam.nRow2, nTab, IDF_ALL ); + + pUndoDoc->CopyToDocument( 0, aParam.nRow1+1, nTab, MAXCOL, aParam.nRow2, nTab, + IDF_NONE, false, pDoc ); // Flags + pUndoDoc->UndoToDocument( 0, aParam.nRow1+1, nTab, MAXCOL, aParam.nRow2, nTab, + IDF_ALL, false, pDoc ); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aParam.nCol1,aParam.nRow1,nTab, + aParam.nCol2,aParam.nRow2,nTab ); + + if (pUndoRange) + pDoc->SetRangeName( new ScRangeName( *pUndoRange ) ); + if (pUndoDB) + pDoc->SetDBCollection( new ScDBCollection( *pUndoDB ), sal_True ); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_GRID|PAINT_LEFT|PAINT_TOP|PAINT_SIZE); + pDocShell->PostDataChanged(); + + EndUndo(); +} + +void ScUndoSubTotals::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aParam.nCol1,aParam.nRow1,nTab, + aParam.nCol2,aParam.nRow2,nTab ); + pViewShell->DoSubTotals( aParam, false ); + + EndRedo(); +} + +void ScUndoSubTotals::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoSubTotals::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // geht nicht wegen Spaltennummern +} + +// +// Sortieren +// + +ScUndoSort::ScUndoSort( ScDocShell* pNewDocShell, + SCTAB nNewTab, const ScSortParam& rParam, + sal_Bool bQuery, ScDocument* pNewUndoDoc, ScDBCollection* pNewUndoDB, + const ScRange* pDest ) : + ScDBFuncUndo( pNewDocShell, ScRange( rParam.nCol1, rParam.nRow1, nNewTab, + rParam.nCol2, rParam.nRow2, nNewTab ) ), + nTab( nNewTab ), + aSortParam( rParam ), + bRepeatQuery( bQuery ), + pUndoDoc( pNewUndoDoc ), + pUndoDB( pNewUndoDB ), + bDestArea( false ) +{ + if ( pDest ) + { + bDestArea = sal_True; + aDestRange = *pDest; + } +} + +ScUndoSort::~ScUndoSort() +{ + delete pUndoDoc; + delete pUndoDB; +} + +String ScUndoSort::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_SORT ); +} + +void ScUndoSort::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + SCCOL nStartCol = aSortParam.nCol1; + SCROW nStartRow = aSortParam.nRow1; + SCCOL nEndCol = aSortParam.nCol2; + SCROW nEndRow = aSortParam.nRow2; + SCTAB nSortTab = nTab; + if ( !aSortParam.bInplace ) + { + nStartCol = aSortParam.nDestCol; + nStartRow = aSortParam.nDestRow; + nEndCol = nStartCol + ( aSortParam.nCol2 - aSortParam.nCol1 ); + nEndRow = nStartRow + ( aSortParam.nRow2 - aSortParam.nRow1 ); + nSortTab = aSortParam.nDestTab; + } + + ScUndoUtil::MarkSimpleBlock( pDocShell, nStartCol, nStartRow, nSortTab, + nEndCol, nEndRow, nSortTab ); + + // do not delete/copy note captions, they are handled in drawing undo (ScDBFuncUndo::mpDrawUndo) + pDoc->DeleteAreaTab( nStartCol,nStartRow, nEndCol,nEndRow, nSortTab, IDF_ALL|IDF_NOCAPTIONS ); + pUndoDoc->CopyToDocument( nStartCol, nStartRow, nSortTab, nEndCol, nEndRow, nSortTab, + IDF_ALL|IDF_NOCAPTIONS, false, pDoc ); + + if (bDestArea) + { + // do not delete/copy note captions, they are handled in drawing undo (ScDBFuncUndo::mpDrawUndo) + pDoc->DeleteAreaTab( aDestRange, IDF_ALL|IDF_NOCAPTIONS ); + pUndoDoc->CopyToDocument( aDestRange, IDF_ALL|IDF_NOCAPTIONS, false, pDoc ); + } + + // Zeilenhoehen immer (wegen automatischer Anpassung) + //! auf ScBlockUndo umstellen +// if (bRepeatQuery) + pUndoDoc->CopyToDocument( 0, nStartRow, nSortTab, MAXCOL, nEndRow, nSortTab, + IDF_NONE, false, pDoc ); + + if (pUndoDB) + pDoc->SetDBCollection( new ScDBCollection( *pUndoDB ), sal_True ); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nSortTab ) + pViewShell->SetTabNo( nSortTab ); + + pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_GRID|PAINT_LEFT|PAINT_TOP|PAINT_SIZE); + pDocShell->PostDataChanged(); + + EndUndo(); +} + +void ScUndoSort::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pViewShell->MarkRange( ScRange( aSortParam.nCol1, aSortParam.nRow1, nTab, + aSortParam.nCol2, aSortParam.nRow2, nTab ) ); + + pViewShell->Sort( aSortParam, false ); + + // Quellbereich painten wegen Markierung + if ( !aSortParam.bInplace ) + pDocShell->PostPaint( aSortParam.nCol1, aSortParam.nRow1, nTab, + aSortParam.nCol2, aSortParam.nRow2, nTab, PAINT_GRID ); + + EndRedo(); +} + +void ScUndoSort::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoSort::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // geht nicht wegen Spaltennummern +} + +// +// Filtern +// + +ScUndoQuery::ScUndoQuery( ScDocShell* pNewDocShell, SCTAB nNewTab, const ScQueryParam& rParam, + ScDocument* pNewUndoDoc, ScDBCollection* pNewUndoDB, + const ScRange* pOld, sal_Bool bSize, const ScRange* pAdvSrc ) : + ScDBFuncUndo( pNewDocShell, ScRange( rParam.nCol1, rParam.nRow1, nNewTab, + rParam.nCol2, rParam.nRow2, nNewTab ) ), + pDrawUndo( NULL ), + nTab( nNewTab ), + aQueryParam( rParam ), + pUndoDoc( pNewUndoDoc ), + pUndoDB( pNewUndoDB ), + bIsAdvanced( false ), + bDestArea( false ), + bDoSize( bSize ) +{ + if ( pOld ) + { + bDestArea = sal_True; + aOldDest = *pOld; + } + if ( pAdvSrc ) + { + bIsAdvanced = sal_True; + aAdvSource = *pAdvSrc; + } + + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); +} + +ScUndoQuery::~ScUndoQuery() +{ + delete pUndoDoc; + delete pUndoDB; + DeleteSdrUndoAction( pDrawUndo ); +} + +String ScUndoQuery::GetComment() const +{ // "Filtern"; + return ScGlobal::GetRscString( STR_UNDO_QUERY ); +} + +void ScUndoQuery::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + sal_Bool bCopy = !aQueryParam.bInplace; + SCCOL nDestEndCol = 0; + SCROW nDestEndRow = 0; + if (bCopy) + { + nDestEndCol = aQueryParam.nDestCol + ( aQueryParam.nCol2-aQueryParam.nCol1 ); + nDestEndRow = aQueryParam.nDestRow + ( aQueryParam.nRow2-aQueryParam.nRow1 ); + + ScDBData* pData = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow, + aQueryParam.nDestTab, sal_True ); + if (pData) + { + ScRange aNewDest; + pData->GetArea( aNewDest ); + nDestEndCol = aNewDest.aEnd.Col(); + nDestEndRow = aNewDest.aEnd.Row(); + } + + if ( bDoSize && bDestArea ) + { + // aDestRange ist der alte Bereich + pDoc->FitBlock( ScRange( + aQueryParam.nDestCol, aQueryParam.nDestRow, aQueryParam.nDestTab, + nDestEndCol, nDestEndRow, aQueryParam.nDestTab ), + aOldDest ); + } + + ScUndoUtil::MarkSimpleBlock( pDocShell, + aQueryParam.nDestCol, aQueryParam.nDestRow, aQueryParam.nDestTab, + nDestEndCol, nDestEndRow, aQueryParam.nDestTab ); + pDoc->DeleteAreaTab( aQueryParam.nDestCol, aQueryParam.nDestRow, + nDestEndCol, nDestEndRow, aQueryParam.nDestTab, IDF_ALL ); + + pViewShell->DoneBlockMode(); + + pUndoDoc->CopyToDocument( aQueryParam.nDestCol, aQueryParam.nDestRow, aQueryParam.nDestTab, + nDestEndCol, nDestEndRow, aQueryParam.nDestTab, + IDF_ALL, false, pDoc ); + // Attribute werden immer mitkopiert (#49287#) + + // Rest von altem Bereich + if ( bDestArea && !bDoSize ) + { + pDoc->DeleteAreaTab( aOldDest, IDF_ALL ); + pUndoDoc->CopyToDocument( aOldDest, IDF_ALL, false, pDoc ); + } + } + else + pUndoDoc->CopyToDocument( 0, aQueryParam.nRow1, nTab, MAXCOL, aQueryParam.nRow2, nTab, + IDF_NONE, false, pDoc ); + + if (pUndoDB) + pDoc->SetDBCollection( new ScDBCollection( *pUndoDB ), sal_True ); + + if (!bCopy) + { + pDoc->InvalidatePageBreaks(nTab); + pDoc->UpdatePageBreaks( nTab ); + } + + ScRange aDirtyRange( 0 , aQueryParam.nRow1, nTab, + MAXCOL, aQueryParam.nRow2, nTab ); + pDoc->SetDirty( aDirtyRange ); + + DoSdrUndoAction( pDrawUndo, pDoc ); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + // Paint + + if (bCopy) + { + SCCOL nEndX = nDestEndCol; + SCROW nEndY = nDestEndRow; + if (bDestArea) + { + if ( aOldDest.aEnd.Col() > nEndX ) + nEndX = aOldDest.aEnd.Col(); + if ( aOldDest.aEnd.Row() > nEndY ) + nEndY = aOldDest.aEnd.Row(); + } + if (bDoSize) + nEndY = MAXROW; + pDocShell->PostPaint( aQueryParam.nDestCol, aQueryParam.nDestRow, aQueryParam.nDestTab, + nEndX, nEndY, aQueryParam.nDestTab, PAINT_GRID ); + } + else + pDocShell->PostPaint( 0, aQueryParam.nRow1, nTab, MAXCOL, MAXROW, nTab, + PAINT_GRID | PAINT_LEFT ); + pDocShell->PostDataChanged(); + + EndUndo(); +} + +void ScUndoQuery::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + if ( bIsAdvanced ) + pViewShell->Query( aQueryParam, &aAdvSource, false ); + else + pViewShell->Query( aQueryParam, NULL, false ); + + EndRedo(); +} + +void ScUndoQuery::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoQuery::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // geht nicht wegen Spaltennummern +} + +// +// Show or hide AutoFilter buttons (doesn't include filter settings) +// + +ScUndoAutoFilter::ScUndoAutoFilter( ScDocShell* pNewDocShell, const ScRange& rRange, + const String& rName, sal_Bool bSet ) : + ScDBFuncUndo( pNewDocShell, rRange ), + aDBName( rName ), + bFilterSet( bSet ) +{ +} + +ScUndoAutoFilter::~ScUndoAutoFilter() +{ +} + +String ScUndoAutoFilter::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_QUERY ); // same as ScUndoQuery +} + +void ScUndoAutoFilter::DoChange( sal_Bool bUndo ) +{ + sal_Bool bNewFilter = bUndo ? !bFilterSet : bFilterSet; + + sal_uInt16 nIndex; + ScDocument* pDoc = pDocShell->GetDocument(); + ScDBData* pDBData=NULL; + if (rtl::OUString(aDBName) == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME))) + { + SCTAB nTab = aOriginalRange.aStart.Tab(); + pDBData = pDoc->GetAnonymousDBData(nTab); + } + else + { + ScDBCollection* pColl = pDoc->GetDBCollection(); + if (pColl->SearchName( aDBName, nIndex )) + pDBData = (*pColl)[nIndex]; + } + + + if ( pDBData ) + { + pDBData->SetAutoFilter( bNewFilter ); + + SCCOL nRangeX1; + SCROW nRangeY1; + SCCOL nRangeX2; + SCROW nRangeY2; + SCTAB nRangeTab; + pDBData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); + + if ( bNewFilter ) + pDoc->ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO ); + else + pDoc->RemoveFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO ); + + pDocShell->PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID ); + } +} + +void ScUndoAutoFilter::Undo() +{ + BeginUndo(); + DoChange( sal_True ); + EndUndo(); +} + +void ScUndoAutoFilter::Redo() +{ + BeginRedo(); + DoChange( false ); + EndRedo(); +} + +void ScUndoAutoFilter::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoAutoFilter::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + +// +// Datenbankbereiche aendern (Dialog) +// + +ScUndoDBData::ScUndoDBData( ScDocShell* pNewDocShell, + ScDBCollection* pNewUndoColl, ScDBCollection* pNewRedoColl ) : + ScSimpleUndo( pNewDocShell ), + pUndoColl( pNewUndoColl ), + pRedoColl( pNewRedoColl ) +{ +} + +ScUndoDBData::~ScUndoDBData() +{ + delete pUndoColl; + delete pRedoColl; +} + +String ScUndoDBData::GetComment() const +{ // "Datenbankbereiche aendern"; + return ScGlobal::GetRscString( STR_UNDO_DBDATA ); +} + +void ScUndoDBData::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + sal_Bool bOldAutoCalc = pDoc->GetAutoCalc(); + pDoc->SetAutoCalc( false ); // unnoetige Berechnungen vermeiden + pDoc->CompileDBFormula( sal_True ); // CreateFormulaString + pDoc->SetDBCollection( new ScDBCollection(*pUndoColl), sal_True ); + pDoc->CompileDBFormula( false ); // CompileFormulaString + pDoc->SetAutoCalc( bOldAutoCalc ); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) ); + + EndUndo(); +} + +void ScUndoDBData::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + sal_Bool bOldAutoCalc = pDoc->GetAutoCalc(); + pDoc->SetAutoCalc( false ); // unnoetige Berechnungen vermeiden + pDoc->CompileDBFormula( sal_True ); // CreateFormulaString + pDoc->SetDBCollection( new ScDBCollection(*pRedoColl), sal_True ); + pDoc->CompileDBFormula( false ); // CompileFormulaString + pDoc->SetAutoCalc( bOldAutoCalc ); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) ); + + EndRedo(); +} + +void ScUndoDBData::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoDBData::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // geht nicht +} + +// +// Import +// + +ScUndoImportData::ScUndoImportData( ScDocShell* pNewDocShell, SCTAB nNewTab, + const ScImportParam& rParam, SCCOL nNewEndX, SCROW nNewEndY, + SCCOL nNewFormula, + ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, + ScDBData* pNewUndoData, ScDBData* pNewRedoData ) : + ScSimpleUndo( pNewDocShell ), + nTab( nNewTab ), + aImportParam( rParam ), + nEndCol( nNewEndX ), + nEndRow( nNewEndY ), + pUndoDoc( pNewUndoDoc ), + pRedoDoc( pNewRedoDoc ), + pUndoDBData( pNewUndoData ), + pRedoDBData( pNewRedoData ), + nFormulaCols( nNewFormula ), + bRedoFilled( false ) +{ + // redo doc doesn't contain imported data (but everything else) +} + +ScUndoImportData::~ScUndoImportData() +{ + delete pUndoDoc; + delete pRedoDoc; + delete pUndoDBData; + delete pRedoDBData; +} + +String ScUndoImportData::GetComment() const +{ // "Importieren"; + return ScGlobal::GetRscString( STR_UNDO_IMPORTDATA ); +} + +void ScUndoImportData::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aImportParam.nCol1,aImportParam.nRow1,nTab, + nEndCol,nEndRow,nTab ); + + SCTAB nTable; + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + ScDBData* pCurrentData = NULL; + if (pUndoDBData && pRedoDBData) + { + pRedoDBData->GetArea( nTable, nCol1, nRow1, nCol2, nRow2 ); + pCurrentData = ScUndoUtil::GetOldDBData( pRedoDBData, pDoc, nTab, + nCol1, nRow1, nCol2, nRow2 ); + + if ( !bRedoFilled ) + { + // read redo data from document at first undo + // imported data is deleted later anyway, + // so now delete each column after copying to save memory (#41216#) + + sal_Bool bOldAutoCalc = pDoc->GetAutoCalc(); + pDoc->SetAutoCalc( false ); // outside of the loop + for (SCCOL nCopyCol = nCol1; nCopyCol <= nCol2; nCopyCol++) + { + pDoc->CopyToDocument( nCopyCol,nRow1,nTab, nCopyCol,nRow2,nTab, + IDF_CONTENTS & ~IDF_NOTE, false, pRedoDoc ); + pDoc->DeleteAreaTab( nCopyCol,nRow1, nCopyCol,nRow2, nTab, IDF_CONTENTS & ~IDF_NOTE ); + pDoc->DoColResize( nTab, nCopyCol, nCopyCol, 0 ); + } + pDoc->SetAutoCalc( bOldAutoCalc ); + bRedoFilled = sal_True; + } + } + sal_Bool bMoveCells = pUndoDBData && pRedoDBData && + pRedoDBData->IsDoSize(); // in alt und neu gleich + if (bMoveCells) + { + // Undo: erst die neuen Daten loeschen, dann FitBlock rueckwaerts + + ScRange aOld, aNew; + pUndoDBData->GetArea( aOld ); + pRedoDBData->GetArea( aNew ); + + pDoc->DeleteAreaTab( aNew.aStart.Col(), aNew.aStart.Row(), + aNew.aEnd.Col(), aNew.aEnd.Row(), nTab, IDF_ALL & ~IDF_NOTE ); + + aOld.aEnd.SetCol( aOld.aEnd.Col() + nFormulaCols ); // FitBlock auch fuer Formeln + aNew.aEnd.SetCol( aNew.aEnd.Col() + nFormulaCols ); + pDoc->FitBlock( aNew, aOld, false ); // rueckwaerts + } + else + pDoc->DeleteAreaTab( aImportParam.nCol1,aImportParam.nRow1, + nEndCol,nEndRow, nTab, IDF_ALL & ~IDF_NOTE ); + + pUndoDoc->CopyToDocument( aImportParam.nCol1,aImportParam.nRow1,nTab, + nEndCol+nFormulaCols,nEndRow,nTab, + IDF_ALL & ~IDF_NOTE, false, pDoc ); + + if (pCurrentData) + { + *pCurrentData = *pUndoDBData; + + pUndoDBData->GetArea( nTable, nCol1, nRow1, nCol2, nRow2 ); + ScUndoUtil::MarkSimpleBlock( pDocShell, nCol1, nRow1, nTable, nCol2, nRow2, nTable ); + } + +// erack! it's broadcasted +// pDoc->SetDirty(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + if (bMoveCells) + pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); + else + pDocShell->PostPaint( aImportParam.nCol1,aImportParam.nRow1,nTab, + nEndCol,nEndRow,nTab, PAINT_GRID ); + pDocShell->PostDataChanged(); + + EndUndo(); +} + +void ScUndoImportData::Redo() +{ + BeginRedo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aImportParam.nCol1,aImportParam.nRow1,nTab, + nEndCol,nEndRow,nTab ); + + SCTAB nTable; + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + ScDBData* pCurrentData = NULL; + if (pUndoDBData && pRedoDBData) + { + pUndoDBData->GetArea( nTable, nCol1, nRow1, nCol2, nRow2 ); + pCurrentData = ScUndoUtil::GetOldDBData( pUndoDBData, pDoc, nTab, + nCol1, nRow1, nCol2, nRow2 ); + } + sal_Bool bMoveCells = pUndoDBData && pRedoDBData && + pRedoDBData->IsDoSize(); // in alt und neu gleich + if (bMoveCells) + { + // Redo: FitBlock, dann Daten loeschen (noetig fuer CopyToDocument) + + ScRange aOld, aNew; + pUndoDBData->GetArea( aOld ); + pRedoDBData->GetArea( aNew ); + + aOld.aEnd.SetCol( aOld.aEnd.Col() + nFormulaCols ); // FitBlock auch fuer Formeln + aNew.aEnd.SetCol( aNew.aEnd.Col() + nFormulaCols ); + pDoc->FitBlock( aOld, aNew ); + + pDoc->DeleteAreaTab( aNew.aStart.Col(), aNew.aStart.Row(), + aNew.aEnd.Col(), aNew.aEnd.Row(), nTab, IDF_ALL & ~IDF_NOTE ); + + pRedoDoc->CopyToDocument( aNew, IDF_ALL & ~IDF_NOTE, false, pDoc ); // incl. Formeln + } + else + { + pDoc->DeleteAreaTab( aImportParam.nCol1,aImportParam.nRow1, + nEndCol,nEndRow, nTab, IDF_ALL & ~IDF_NOTE ); + pRedoDoc->CopyToDocument( aImportParam.nCol1,aImportParam.nRow1,nTab, + nEndCol,nEndRow,nTab, IDF_ALL & ~IDF_NOTE, false, pDoc ); + } + + if (pCurrentData) + { + *pCurrentData = *pRedoDBData; + + pRedoDBData->GetArea( nTable, nCol1, nRow1, nCol2, nRow2 ); + ScUndoUtil::MarkSimpleBlock( pDocShell, nCol1, nRow1, nTable, nCol2, nRow2, nTable ); + } + +// erack! it's broadcasted +// pDoc->SetDirty(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + if (bMoveCells) + pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); + else + pDocShell->PostPaint( aImportParam.nCol1,aImportParam.nRow1,nTab, + nEndCol,nEndRow,nTab, PAINT_GRID ); + pDocShell->PostDataChanged(); + + EndRedo(); +} + +void ScUndoImportData::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell(); + + SCTAB nDummy; + ScImportParam aNewParam(aImportParam); + ScDBData* pDBData = rViewShell.GetDBData(); + pDBData->GetArea( nDummy, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 ); + + rViewShell.ImportData( aNewParam ); + } +} + +sal_Bool ScUndoImportData::CanRepeat(SfxRepeatTarget& rTarget) const +{ + // Repeat nur fuer Import per DB-Bereich, dann ist pUndoDBData gesetzt + + if (pUndoDBData) + return (rTarget.ISA(ScTabViewTarget)); + else + return false; // Adressbuch +} + +// +// Operationen wiederholen +// + +ScUndoRepeatDB::ScUndoRepeatDB( ScDocShell* pNewDocShell, SCTAB nNewTab, + SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY, + SCROW nResultEndRow, SCCOL nCurX, SCROW nCurY, + ScDocument* pNewUndoDoc, ScOutlineTable* pNewUndoTab, + ScRangeName* pNewUndoRange, ScDBCollection* pNewUndoDB, + const ScRange* pOldQ, const ScRange* pNewQ ) : + ScSimpleUndo( pNewDocShell ), + aBlockStart( nStartX,nStartY,nNewTab ), + aBlockEnd( nEndX,nEndY,nNewTab ), + nNewEndRow( nResultEndRow ), + aCursorPos( nCurX,nCurY,nNewTab ), + pUndoDoc( pNewUndoDoc ), + pUndoTable( pNewUndoTab ), + pUndoRange( pNewUndoRange ), + pUndoDB( pNewUndoDB ), + bQuerySize( false ) +{ + if ( pOldQ && pNewQ ) + { + aOldQuery = *pOldQ; + aNewQuery = *pNewQ; + bQuerySize = sal_True;; + } +} + +ScUndoRepeatDB::~ScUndoRepeatDB() +{ + delete pUndoDoc; + delete pUndoTable; + delete pUndoRange; + delete pUndoDB; +} + +String ScUndoRepeatDB::GetComment() const +{ // "Wiederholen"; //! bessere Beschreibung! + return ScGlobal::GetRscString( STR_UNDO_REPEATDB ); +} + +void ScUndoRepeatDB::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + SCTAB nTab = aBlockStart.Tab(); + + if (bQuerySize) + { + pDoc->FitBlock( aNewQuery, aOldQuery, false ); + + if ( aNewQuery.aEnd.Col() == aOldQuery.aEnd.Col() ) + { + SCCOL nFormulaCols = 0; + SCCOL nCol = aOldQuery.aEnd.Col() + 1; + SCROW nRow = aOldQuery.aStart.Row() + 1; //! Header testen + while ( nCol <= MAXCOL && + pDoc->GetCellType(ScAddress( nCol, nRow, nTab )) == CELLTYPE_FORMULA ) + ++nCol, ++nFormulaCols; + + if ( nFormulaCols > 0 ) + { + ScRange aOldForm = aOldQuery; + aOldForm.aStart.SetCol( aOldQuery.aEnd.Col() + 1 ); + aOldForm.aEnd.SetCol( aOldQuery.aEnd.Col() + nFormulaCols ); + ScRange aNewForm = aOldForm; + aNewForm.aEnd.SetRow( aNewQuery.aEnd.Row() ); + pDoc->FitBlock( aNewForm, aOldForm, false ); + } + } + } + + //! Daten von Filter in anderen Bereich fehlen noch !!!!!!!!!!!!!!!!! + + if (nNewEndRow > aBlockEnd.Row()) + { + pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, aBlockEnd.Row()+1, static_cast<SCSIZE>(nNewEndRow-aBlockEnd.Row()) ); + } + else if (nNewEndRow < aBlockEnd.Row()) + { + pDoc->InsertRow( 0,nTab, MAXCOL,nTab, nNewEndRow+1, static_cast<SCSIZE>(nNewEndRow-aBlockEnd.Row()) ); + } + + // Original Outline-Table + + pDoc->SetOutlineTable( nTab, pUndoTable ); + + // Original Spalten-/Zeilenstatus + + if (pUndoDoc && pUndoTable) + { + SCCOLROW nStartCol; + SCCOLROW nStartRow; + SCCOLROW nEndCol; + SCCOLROW nEndRow; + pUndoTable->GetColArray()->GetRange( nStartCol, nEndCol ); + pUndoTable->GetRowArray()->GetRange( nStartRow, nEndRow ); + + pUndoDoc->CopyToDocument( static_cast<SCCOL>(nStartCol), 0, nTab, + static_cast<SCCOL>(nEndCol), MAXROW, nTab, IDF_NONE, false, + pDoc ); + pUndoDoc->CopyToDocument( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab, IDF_NONE, false, pDoc ); + + pViewShell->UpdateScrollBars(); + } + + // Original-Daten & Referenzen + + ScUndoUtil::MarkSimpleBlock( pDocShell, 0, aBlockStart.Row(), nTab, + MAXCOL, aBlockEnd.Row(), nTab ); + pDoc->DeleteAreaTab( 0, aBlockStart.Row(), + MAXCOL, aBlockEnd.Row(), nTab, IDF_ALL ); + + pUndoDoc->CopyToDocument( 0, aBlockStart.Row(), nTab, MAXCOL, aBlockEnd.Row(), nTab, + IDF_NONE, false, pDoc ); // Flags + pUndoDoc->UndoToDocument( 0, aBlockStart.Row(), nTab, MAXCOL, aBlockEnd.Row(), nTab, + IDF_ALL, false, pDoc ); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart.Col(),aBlockStart.Row(),nTab, + aBlockEnd.Col(),aBlockEnd.Row(),nTab ); + + if (pUndoRange) + pDoc->SetRangeName( new ScRangeName( *pUndoRange ) ); + if (pUndoDB) + pDoc->SetDBCollection( new ScDBCollection( *pUndoDB ), sal_True ); + +// erack! it's broadcasted +// pDoc->SetDirty(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_GRID|PAINT_LEFT|PAINT_TOP|PAINT_SIZE); + pDocShell->PostDataChanged(); + + EndUndo(); +} + +void ScUndoRepeatDB::Redo() +{ + BeginRedo(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + SCTAB nTab = aBlockStart.Tab(); + + SCTAB nVisTab = pViewShell->GetViewData()->GetTabNo(); + if ( nVisTab != nTab ) + pViewShell->SetTabNo( nTab ); + + ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockStart.Col(),aBlockStart.Row(),nTab, + aBlockEnd.Col(),aBlockEnd.Row(),nTab ); + pViewShell->SetCursor( aCursorPos.Col(), aCursorPos.Row() ); + + pViewShell->RepeatDB( false ); + + EndRedo(); +} + +void ScUndoRepeatDB::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->RepeatDB( sal_True ); +} + +sal_Bool ScUndoRepeatDB::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// +// data pilot +// + +ScUndoDataPilot::ScUndoDataPilot( ScDocShell* pNewDocShell, + ScDocument* pOldDoc, ScDocument* pNewDoc, + const ScDPObject* pOldObj, const ScDPObject* pNewObj, sal_Bool bMove ) : + ScSimpleUndo( pNewDocShell ), + pOldUndoDoc( pOldDoc ), + pNewUndoDoc( pNewDoc ), + pOldDPObject( NULL ), + pNewDPObject( NULL ), + bAllowMove( bMove ) +{ + if (pOldObj) + pOldDPObject = new ScDPObject( *pOldObj ); + if (pNewObj) + pNewDPObject = new ScDPObject( *pNewObj ); +} + +ScUndoDataPilot::~ScUndoDataPilot() +{ + delete pOldDPObject; + delete pNewDPObject; + delete pOldUndoDoc; + delete pNewUndoDoc; +} + +String ScUndoDataPilot::GetComment() const +{ + sal_uInt16 nIndex; + if ( pOldUndoDoc && pNewUndoDoc ) + nIndex = STR_UNDO_PIVOT_MODIFY; + else if ( pNewUndoDoc ) + nIndex = STR_UNDO_PIVOT_NEW; + else + nIndex = STR_UNDO_PIVOT_DELETE; + + return ScGlobal::GetRscString( nIndex ); +} + +void ScUndoDataPilot::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + + ScRange aOldRange; + ScRange aNewRange; + + if ( pNewDPObject && pNewUndoDoc ) + { + aNewRange = pNewDPObject->GetOutRange(); + pDoc->DeleteAreaTab( aNewRange, IDF_ALL ); + pNewUndoDoc->CopyToDocument( aNewRange, IDF_ALL, false, pDoc ); + } + if ( pOldDPObject && pOldUndoDoc ) + { + aOldRange = pOldDPObject->GetOutRange(); + pDoc->DeleteAreaTab( aOldRange, IDF_ALL ); + pOldUndoDoc->CopyToDocument( aOldRange, IDF_ALL, false, pDoc ); + } + + // update objects in collection + + if ( pNewDPObject ) + { + // find updated object + //! find by name! + + ScDPObject* pDocObj = pDoc->GetDPAtCursor( + aNewRange.aStart.Col(), aNewRange.aStart.Row(), aNewRange.aStart.Tab() ); + DBG_ASSERT(pDocObj, "DPObject not found"); + if (pDocObj) + { + if ( pOldDPObject ) + { + // restore old settings + pOldDPObject->WriteSourceDataTo( *pDocObj ); + ScDPSaveData* pData = pOldDPObject->GetSaveData(); + if (pData) + pDocObj->SetSaveData(*pData); + pDocObj->SetOutRange( pOldDPObject->GetOutRange() ); + pOldDPObject->WriteTempDataTo( *pDocObj ); + } + else + { + // delete inserted object + pDoc->GetDPCollection()->FreeTable(pDocObj); + } + } + } + else if ( pOldDPObject ) + { + // re-insert deleted object + + ScDPObject* pDestObj = new ScDPObject( *pOldDPObject ); + pDestObj->SetAlive(sal_True); + if ( !pDoc->GetDPCollection()->InsertNewTable(pDestObj) ) + { + OSL_FAIL("cannot insert DPObject"); + DELETEZ( pDestObj ); + } + } + + if (pNewUndoDoc) + pDocShell->PostPaint( aNewRange, PAINT_GRID, SC_PF_LINES ); + if (pOldUndoDoc) + pDocShell->PostPaint( aOldRange, PAINT_GRID, SC_PF_LINES ); + pDocShell->PostDataChanged(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + //! set current sheet + } + + if (pNewDPObject) + { + // notify API objects + pDoc->BroadcastUno( ScDataPilotModifiedHint( pNewDPObject->GetName() ) ); + } + + EndUndo(); +} + +void ScUndoDataPilot::Redo() +{ + BeginRedo(); + + //! copy output data instead of repeating the change, + //! in case external data have changed! + + ScDocument* pDoc = pDocShell->GetDocument(); + + ScDPObject* pSourceObj = NULL; + if ( pOldDPObject ) + { + // find object to modify + //! find by name! + + ScRange aOldRange = pOldDPObject->GetOutRange(); + pSourceObj = pDoc->GetDPAtCursor( + aOldRange.aStart.Col(), aOldRange.aStart.Row(), aOldRange.aStart.Tab() ); + DBG_ASSERT(pSourceObj, "DPObject not found"); + } + + ScDBDocFunc aFunc( *pDocShell ); + aFunc.DataPilotUpdate( pSourceObj, pNewDPObject, false, false, bAllowMove ); // no new undo action + + EndRedo(); +} + +void ScUndoDataPilot::Repeat(SfxRepeatTarget& /* rTarget */) +{ + //! allow deletion +} + +sal_Bool ScUndoDataPilot::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + //! allow deletion + return false; +} + + +// +// Konsolidieren +// + +ScUndoConsolidate::ScUndoConsolidate( ScDocShell* pNewDocShell, const ScArea& rArea, + const ScConsolidateParam& rPar, ScDocument* pNewUndoDoc, + sal_Bool bReference, SCROW nInsCount, ScOutlineTable* pTab, + ScDBData* pData ) : + ScSimpleUndo( pNewDocShell ), + aDestArea( rArea ), + pUndoDoc( pNewUndoDoc ), + aParam( rPar ), + bInsRef( bReference ), + nInsertCount( nInsCount ), + pUndoTab( pTab ), + pUndoData( pData ) +{ +} + +ScUndoConsolidate::~ScUndoConsolidate() +{ + delete pUndoDoc; + delete pUndoTab; + delete pUndoData; +} + +String ScUndoConsolidate::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_CONSOLIDATE ); +} + +void ScUndoConsolidate::Undo() +{ + BeginUndo(); + + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTab = aDestArea.nTab; + + ScRange aOldRange; + if (pUndoData) + pUndoData->GetArea(aOldRange); + + if (bInsRef) + { + // Zeilen loeschen + pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, aDestArea.nRowStart, nInsertCount ); + + // Outlines + pDoc->SetOutlineTable( nTab, pUndoTab ); + + // Zeilenstatus + pUndoDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, false, pDoc ); + + // Daten & Referenzen + pDoc->DeleteAreaTab( 0,aDestArea.nRowStart, MAXCOL,aDestArea.nRowEnd, nTab, IDF_ALL ); + pUndoDoc->UndoToDocument( 0, aDestArea.nRowStart, nTab, + MAXCOL, aDestArea.nRowEnd, nTab, + IDF_ALL, false, pDoc ); + + // Original-Bereich + if (pUndoData) + { + pDoc->DeleteAreaTab(aOldRange, IDF_ALL); + pUndoDoc->CopyToDocument(aOldRange, IDF_ALL, false, pDoc); + } + + pDocShell->PostPaint( 0,aDestArea.nRowStart,nTab, MAXCOL,MAXROW,nTab, + PAINT_GRID | PAINT_LEFT | PAINT_SIZE ); + } + else + { + pDoc->DeleteAreaTab( aDestArea.nColStart,aDestArea.nRowStart, + aDestArea.nColEnd,aDestArea.nRowEnd, nTab, IDF_ALL ); + pUndoDoc->CopyToDocument( aDestArea.nColStart, aDestArea.nRowStart, nTab, + aDestArea.nColEnd, aDestArea.nRowEnd, nTab, + IDF_ALL, false, pDoc ); + + // Original-Bereich + if (pUndoData) + { + pDoc->DeleteAreaTab(aOldRange, IDF_ALL); + pUndoDoc->CopyToDocument(aOldRange, IDF_ALL, false, pDoc); + } + + SCCOL nEndX = aDestArea.nColEnd; + SCROW nEndY = aDestArea.nRowEnd; + if ( pUndoData ) + { + if ( aOldRange.aEnd.Col() > nEndX ) + nEndX = aOldRange.aEnd.Col(); + if ( aOldRange.aEnd.Row() > nEndY ) + nEndY = aOldRange.aEnd.Row(); + } + pDocShell->PostPaint( aDestArea.nColStart, aDestArea.nRowStart, nTab, + nEndX, nEndY, nTab, PAINT_GRID ); + } + + // DB-Bereich wieder anpassen + if (pUndoData) + { + ScDBCollection* pColl = pDoc->GetDBCollection(); + if (pColl) + { + sal_uInt16 nIndex; + if (pColl->SearchName( pUndoData->GetName(), nIndex )) + { + ScDBData* pDocData = (*pColl)[nIndex]; + if (pDocData) + *pDocData = *pUndoData; + } + else + { + OSL_FAIL("alte DB-Daten nicht gefunden"); + } + } + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + SCTAB nViewTab = pViewShell->GetViewData()->GetTabNo(); + if ( nViewTab != nTab ) + pViewShell->SetTabNo( nTab ); + } + + EndUndo(); +} + +void ScUndoConsolidate::Redo() +{ + BeginRedo(); + + pDocShell->DoConsolidate( aParam, false ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + SCTAB nViewTab = pViewShell->GetViewData()->GetTabNo(); + if ( nViewTab != aParam.nTab ) + pViewShell->SetTabNo( aParam.nTab ); + } + + EndRedo(); +} + +void ScUndoConsolidate::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoConsolidate::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +// +// Quell-Daten von Chart aendern +// + +void ScUndoChartData::Init() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + aOldRangeListRef = new ScRangeList; + pDoc->GetOldChartParameters( aChartName, *aOldRangeListRef, bOldColHeaders, bOldRowHeaders ); +} + +ScUndoChartData::ScUndoChartData( ScDocShell* pNewDocShell, const String& rName, + const ScRange& rNew, sal_Bool bColHdr, sal_Bool bRowHdr, + sal_Bool bAdd ) : + ScSimpleUndo( pNewDocShell ), + aChartName( rName ), + bNewColHeaders( bColHdr ), + bNewRowHeaders( bRowHdr ), + bAddRange( bAdd ) +{ + aNewRangeListRef = new ScRangeList; + aNewRangeListRef->Append( rNew ); + + Init(); +} + +ScUndoChartData::ScUndoChartData( ScDocShell* pNewDocShell, const String& rName, + const ScRangeListRef& rNew, sal_Bool bColHdr, sal_Bool bRowHdr, + sal_Bool bAdd ) : + ScSimpleUndo( pNewDocShell ), + aChartName( rName ), + aNewRangeListRef( rNew ), + bNewColHeaders( bColHdr ), + bNewRowHeaders( bRowHdr ), + bAddRange( bAdd ) +{ + Init(); +} + +ScUndoChartData::~ScUndoChartData() +{ +} + +String ScUndoChartData::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_CHARTDATA ); +} + +void ScUndoChartData::Undo() +{ + BeginUndo(); + + pDocShell->GetDocument()->UpdateChartArea( aChartName, aOldRangeListRef, + bOldColHeaders, bOldRowHeaders, false ); + + EndUndo(); +} + +void ScUndoChartData::Redo() +{ + BeginRedo(); + + pDocShell->GetDocument()->UpdateChartArea( aChartName, aNewRangeListRef, + bNewColHeaders, bNewRowHeaders, bAddRange ); + + EndRedo(); +} + +void ScUndoChartData::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoChartData::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + +// Amelia Wang +ScUndoDataForm::ScUndoDataForm( ScDocShell* pNewDocShell, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, + const ScMarkData& rMark, + ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, + sal_uInt16 nNewFlags, + ScRefUndoData* pRefData, + void* /*pFill1*/, void* /*pFill2*/, void* /*pFill3*/, + sal_Bool bRedoIsFilled ) : + ScBlockUndo( pNewDocShell, ScRange( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), SC_UNDO_SIMPLE ), + aMarkData( rMark ), + pUndoDoc( pNewUndoDoc ), + pRedoDoc( pNewRedoDoc ), + nFlags( nNewFlags ), + pRefUndoData( pRefData ), + pRefRedoData( NULL ), + bRedoFilled( bRedoIsFilled ) +{ + // pFill1,pFill2,pFill3 are there so the ctor calls for simple paste (without cutting) + // don't have to be changed and branched for 641. + // They can be removed later. + + if ( !aMarkData.IsMarked() ) // no cell marked: + aMarkData.SetMarkArea( aBlockRange ); // mark paste block + + if ( pRefUndoData ) + pRefUndoData->DeleteUnchanged( pDocShell->GetDocument() ); + + SetChangeTrack(); +} + +ScUndoDataForm::~ScUndoDataForm() +{ + delete pUndoDoc; + delete pRedoDoc; + delete pRefUndoData; + delete pRefRedoData; +} + +String ScUndoDataForm::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_PASTE ); +} + +void ScUndoDataForm::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack && (nFlags & IDF_CONTENTS) ) + pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc, + nStartChangeAction, nEndChangeAction, SC_CACM_PASTE ); + else + nStartChangeAction = nEndChangeAction = 0; +} + + +void ScUndoDataForm::Undo() +{ + BeginUndo(); + DoChange( true ); + ShowTable( aBlockRange ); + EndUndo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); +} + +void ScUndoDataForm::Redo() +{ + BeginRedo(); + ScDocument* pDoc = pDocShell->GetDocument(); + EnableDrawAdjust( pDoc, false ); //! include in ScBlockUndo? + DoChange( false ); + EnableDrawAdjust( pDoc, true ); //! include in ScBlockUndo? + EndRedo(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); +} + +void ScUndoDataForm::Repeat(SfxRepeatTarget& /*rTarget*/) +{ +} + +sal_Bool ScUndoDataForm::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +void ScUndoDataForm::DoChange( const sal_Bool bUndo ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + // RefUndoData for redo is created before first undo + // (with DeleteUnchanged after the DoUndo call) + sal_Bool bCreateRedoData = ( bUndo && pRefUndoData && !pRefRedoData ); + if ( bCreateRedoData ) + pRefRedoData = new ScRefUndoData( pDoc ); + + ScRefUndoData* pWorkRefData = bUndo ? pRefUndoData : pRefRedoData; + + // fuer Undo immer alle oder keine Inhalte sichern + sal_uInt16 nUndoFlags = IDF_NONE; + if (nFlags & IDF_CONTENTS) + nUndoFlags |= IDF_CONTENTS; + if (nFlags & IDF_ATTRIB) + nUndoFlags |= IDF_ATTRIB; + + sal_Bool bPaintAll = false; + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + SCTAB nTabCount = pDoc->GetTableCount(); + if ( bUndo && !bRedoFilled ) + { + if (!pRedoDoc) + { + sal_Bool bColInfo = ( aBlockRange.aStart.Row()==0 && aBlockRange.aEnd.Row()==MAXROW ); + sal_Bool bRowInfo = ( aBlockRange.aStart.Col()==0 && aBlockRange.aEnd.Col()==MAXCOL ); + + pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); + pRedoDoc->InitUndoSelected( pDoc, aMarkData, bColInfo, bRowInfo ); + } + // read "redo" data from the document in the first undo + // all sheets - CopyToDocument skips those that don't exist in pRedoDoc + ScRange aCopyRange = aBlockRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pDoc->CopyToDocument( aCopyRange, 1, false, pRedoDoc ); + bRedoFilled = true; + } + + sal_uInt16 nExtFlags = 0; + pDocShell->UpdatePaintExt( nExtFlags, aBlockRange ); + + for ( sal_uInt16 i=0; i <= ( aBlockRange.aEnd.Col() - aBlockRange.aStart.Col() ); i++ ) + { + String aOldString; + pUndoDoc->GetString( aBlockRange.aStart.Col()+i , aBlockRange.aStart.Row() , aBlockRange.aStart.Tab() , aOldString ); + pDoc->SetString( aBlockRange.aStart.Col()+i , aBlockRange.aStart.Row() , aBlockRange.aStart.Tab() , aOldString ); + } + + if (pWorkRefData) + { + pWorkRefData->DoUndo( pDoc, true ); // TRUE = bSetChartRangeLists for SetChartListenerCollection + if ( pDoc->RefreshAutoFilter( 0,0, MAXCOL,MAXROW, aBlockRange.aStart.Tab() ) ) + bPaintAll = true; + } + + if ( bCreateRedoData && pRefRedoData ) + pRefRedoData->DeleteUnchanged( pDoc ); + + if ( bUndo ) + { + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + } + else + SetChangeTrack(); + + ScRange aDrawRange( aBlockRange ); + pDoc->ExtendMerge( aDrawRange, true ); // only needed for single sheet (text/rtf etc.) + sal_uInt16 nPaint = PAINT_GRID; + if (bPaintAll) + { + aDrawRange.aStart.SetCol(0); + aDrawRange.aStart.SetRow(0); + aDrawRange.aEnd.SetCol(MAXCOL); + aDrawRange.aEnd.SetRow(MAXROW); + nPaint |= PAINT_TOP | PAINT_LEFT; +/*A*/ if (pViewShell) + pViewShell->AdjustBlockHeight(false); + } + else + { + if ( aBlockRange.aStart.Row() == 0 && aBlockRange.aEnd.Row() == MAXROW ) // ganze Spalte + { + nPaint |= PAINT_TOP; + aDrawRange.aEnd.SetCol(MAXCOL); + } + if ( aBlockRange.aStart.Col() == 0 && aBlockRange.aEnd.Col() == MAXCOL ) // ganze Zeile + { + nPaint |= PAINT_LEFT; + aDrawRange.aEnd.SetRow(MAXROW); + } +/*A*/ if ((pViewShell) && pViewShell->AdjustBlockHeight(false)) + { + aDrawRange.aStart.SetCol(0); + aDrawRange.aStart.SetRow(0); + aDrawRange.aEnd.SetCol(MAXCOL); + aDrawRange.aEnd.SetRow(MAXROW); + nPaint |= PAINT_LEFT; + } + pDocShell->UpdatePaintExt( nExtFlags, aDrawRange ); + } + + if ( !bUndo ) // draw redo after updating row heights + RedoSdrUndoAction( pDrawUndo ); //! include in ScBlockUndo? + + pDocShell->PostPaint( aDrawRange, nPaint, nExtFlags ); + + pDocShell->PostDataChanged(); + if (pViewShell) + pViewShell->CellContentChanged(); +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undodraw.cxx b/sc/source/ui/undo/undodraw.cxx new file mode 100644 index 000000000000..8a263080ae1d --- /dev/null +++ b/sc/source/ui/undo/undodraw.cxx @@ -0,0 +1,198 @@ +/* -*- 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_sc.hxx" + + + +//------------------------------------------------------------------ + +// TOOLS +#define _BIGINT_HXX +#define _SFXMULTISEL_HXX +#define _STACK_HXX +#define _QUEUE_HXX +#define _DYNARR_HXX +#define _TREELIST_HXX +#define _CACHESTR_HXX +#define _NEW_HXX +#define _DYNARY_HXX +#define _SVMEMPOOL_HXX +#define _CACHESTR_HXX +#define _SV_MULTISEL_HXX + +//SV +#define _CONFIG_HXX +#define _CURSOR_HXX +#define _FONTDLG_HXX +#define _PRVWIN_HXX +#define _HELP_HXX +#define _MDIWIN_HXX +#define _SPIN_HXX +#define _FILDLG_HXX +#define _COLDLG_HXX +#define _SOUND_HXX + + +#define SI_NOITEMS +#define _SI_NOSBXCONTROLS +#define _SI_NOOTHERFORMS +#define _SI_NOCONTROL +#define _SI_NOSBXCONTROLS +#define _SIDLL_HXX + +// SFX +#define _SFXAPPWIN_HXX +#define _SFX_SAVEOPT_HXX +#define _SFXPRNMON_HXX +#define _INTRO_HXX +#define _SFXMSGDESCR_HXX +#define _SFXMSGPOOL_HXX +#define _SFXFILEDLG_HXX +#define _PASSWD_HXX +#define _SFXTBXCTRL_HXX +#define _SFXSTBITEM_HXX +#define _SFXMNUITEM_HXX +#define _SFXIMGMGR_HXX +#define _SFXTBXMGR_HXX +#define _SFXSTBMGR_HXX +#define _SFX_MINFITEM_HXX +#define _SFXEVENT_HXX + +// INCLUDE --------------------------------------------------------------- + +#include <svx/svdundo.hxx> + +#include "undodraw.hxx" +#include "docsh.hxx" + + +// ----------------------------------------------------------------------- + +TYPEINIT1(ScUndoDraw, SfxUndoAction); + +// ----------------------------------------------------------------------- + +ScUndoDraw::ScUndoDraw( SfxUndoAction* pUndo, ScDocShell* pDocSh ) : + pDrawUndo( pUndo ), + pDocShell( pDocSh ) +{ +} + +ScUndoDraw::~ScUndoDraw() +{ + delete pDrawUndo; +} + +void ScUndoDraw::ForgetDrawUndo() +{ + pDrawUndo = NULL; // nicht loeschen (Draw-Undo muss dann von aussen gemerkt werden) +} + +String ScUndoDraw::GetComment() const +{ + if (pDrawUndo) + return pDrawUndo->GetComment(); + else + return String(); +} + +String ScUndoDraw::GetRepeatComment(SfxRepeatTarget& rTarget) const +{ + if (pDrawUndo) + return pDrawUndo->GetRepeatComment(rTarget); + else + return String(); +} + +sal_uInt16 ScUndoDraw::GetId() const +{ + if (pDrawUndo) + return pDrawUndo->GetId(); + else + return 0; +} + +sal_Bool ScUndoDraw::IsLinked() +{ + if (pDrawUndo) + return pDrawUndo->IsLinked(); + else + return false; +} + +void ScUndoDraw::SetLinked( sal_Bool bIsLinked ) +{ + if (pDrawUndo) + pDrawUndo->SetLinked(bIsLinked); +} + +sal_Bool ScUndoDraw::Merge( SfxUndoAction* pNextAction ) +{ + if (pDrawUndo) + return pDrawUndo->Merge(pNextAction); + else + return false; +} + +void ScUndoDraw::Undo() +{ + if (pDrawUndo) + { + pDrawUndo->Undo(); + pDocShell->SetDrawModified(); + } +} + +void ScUndoDraw::Redo() +{ + if (pDrawUndo) + { + pDrawUndo->Redo(); + pDocShell->SetDrawModified(); + } +} + +void ScUndoDraw::Repeat(SfxRepeatTarget& rTarget) +{ + if (pDrawUndo) + pDrawUndo->Repeat(rTarget); +} + +sal_Bool ScUndoDraw::CanRepeat(SfxRepeatTarget& rTarget) const +{ + if (pDrawUndo) + return pDrawUndo->CanRepeat(rTarget); + else + return false; +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undoolk.cxx b/sc/source/ui/undo/undoolk.cxx new file mode 100644 index 000000000000..843c275ef0cb --- /dev/null +++ b/sc/source/ui/undo/undoolk.cxx @@ -0,0 +1,104 @@ +/* -*- 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_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <svx/svdundo.hxx> + +#include "document.hxx" +#include "drwlayer.hxx" + + +// STATIC DATA ----------------------------------------------------------- + +// ----------------------------------------------------------------------- + +SdrUndoAction* GetSdrUndoAction( ScDocument* pDoc ) +{ + ScDrawLayer* pLayer = pDoc->GetDrawLayer(); + if (pLayer) + return pLayer->GetCalcUndo(); // muss vorhanden sein + else + return NULL; +} + +void DoSdrUndoAction( SdrUndoAction* pUndoAction, ScDocument* pDoc ) +{ + if ( pUndoAction ) + pUndoAction->Undo(); + else + { + // if no drawing layer existed when the action was created, + // but it was created after that, there is no draw undo action, + // and after undo there might be a drawing layer with a wrong page count. + // The drawing layer must have been empty in that case, so any missing + // pages can just be created now. + + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + if ( pDrawLayer ) + { + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nPages = static_cast<SCTAB>(pDrawLayer->GetPageCount()); + while ( nPages < nTabCount ) + { + pDrawLayer->ScAddPage( nPages ); + ++nPages; + } + } + } +} + + +void RedoSdrUndoAction( SdrUndoAction* pUndoAction ) +{ + // DoSdrUndoAction/RedoSdrUndoAction is called even if the pointer is null + + if ( pUndoAction ) + pUndoAction->Redo(); +} + +void DeleteSdrUndoAction( SdrUndoAction* pUndoAction ) +{ + delete pUndoAction; +} + +void EnableDrawAdjust( ScDocument* pDoc, sal_Bool bEnable ) +{ + ScDrawLayer* pLayer = pDoc->GetDrawLayer(); + if (pLayer) + pLayer->EnableAdjust(bEnable); +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undorangename.cxx b/sc/source/ui/undo/undorangename.cxx new file mode 100644 index 000000000000..d384bc8b91d3 --- /dev/null +++ b/sc/source/ui/undo/undorangename.cxx @@ -0,0 +1,117 @@ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Kohei Yoshida <kyoshida@novell.com> (Novell, Inc.) + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "undorangename.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "docfunc.hxx" +#include "sc.hrc" + +#include "sfx2/app.hxx" + +#include <memory> + +using ::std::auto_ptr; + +ScUndoAllRangeNames::ScUndoAllRangeNames( + ScDocShell* pDocSh, + const ScRangeName* pOldGlobal, const ScRangeName* pNewGlobal, + const ScRangeName::TabNameCopyMap &rOldLocal, const ScRangeName::TabNameCopyMap &rNewLocal) : + ScSimpleUndo(pDocSh) +{ + if (pOldGlobal) + maOldGlobalNames = *pOldGlobal; + if (pNewGlobal) + maNewGlobalNames = *pNewGlobal; + + // Copy sheet-local names. + ScRangeName::TabNameCopyMap::const_iterator itr, itrEnd; + for (itr = rOldLocal.begin(), itrEnd = rOldLocal.end(); itr != itrEnd; ++itr) + { + auto_ptr<ScRangeName> p(new ScRangeName(*itr->second)); + maOldLocalNames.insert(itr->first, p); + } + + for (itr = rNewLocal.begin(), itrEnd = rNewLocal.end(); itr != itrEnd; ++itr) + { + auto_ptr<ScRangeName> p(new ScRangeName(*itr->second)); + maNewLocalNames.insert(itr->first, p); + } +} + +ScUndoAllRangeNames::~ScUndoAllRangeNames() +{ +} + +void ScUndoAllRangeNames::Undo() +{ + DoChange(maOldGlobalNames, maOldLocalNames); +} + +void ScUndoAllRangeNames::Redo() +{ + DoChange(maNewGlobalNames, maNewLocalNames); +} + +void ScUndoAllRangeNames::Repeat(SfxRepeatTarget& /*rTarget*/) +{ +} + +sal_Bool ScUndoAllRangeNames::CanRepeat(SfxRepeatTarget& /*rTarget*/) const +{ + return sal_False; +} + +String ScUndoAllRangeNames::GetComment() const +{ + return ScGlobal::GetRscString(STR_UNDO_RANGENAMES); +} + +void ScUndoAllRangeNames::DoChange(const ScRangeName& rGlobal, const ScRangeName::TabNameMap& rLocal) +{ + ScDocument& rDoc = *pDocShell->GetDocument(); + + rDoc.CompileNameFormula(true); + + // Global names. + if (rGlobal.empty()) + rDoc.SetRangeName(NULL); + else + rDoc.SetRangeName(new ScRangeName(rGlobal)); + + ScRangeName::TabNameCopyMap aCopy; + ScRangeName::copyLocalNames(rLocal, aCopy); + rDoc.SetAllTabRangeNames(aCopy); + + rDoc.CompileNameFormula(true); + + SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED)); +} + diff --git a/sc/source/ui/undo/undostyl.cxx b/sc/source/ui/undo/undostyl.cxx new file mode 100644 index 000000000000..f8286ed4b264 --- /dev/null +++ b/sc/source/ui/undo/undostyl.cxx @@ -0,0 +1,312 @@ +/* -*- 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_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <svl/itemset.hxx> +#include <vcl/virdev.hxx> + +#include "undostyl.hxx" +#include "docsh.hxx" +#include "docpool.hxx" +#include "stlpool.hxx" +#include "printfun.hxx" +#include "scmod.hxx" +#include "inputhdl.hxx" +#include "globstr.hrc" + +// ----------------------------------------------------------------------- + +TYPEINIT1(ScUndoModifyStyle, ScSimpleUndo); +TYPEINIT1(ScUndoApplyPageStyle, ScSimpleUndo); + +// ----------------------------------------------------------------------- +// +// modify style (cell or page style) +// + +ScStyleSaveData::ScStyleSaveData() : + pItems( NULL ) +{ +} + +ScStyleSaveData::ScStyleSaveData( const ScStyleSaveData& rOther ) : + aName( rOther.aName ), + aParent( rOther.aParent ) +{ + if (rOther.pItems) + pItems = new SfxItemSet( *rOther.pItems ); + else + pItems = NULL; +} + +ScStyleSaveData::~ScStyleSaveData() +{ + delete pItems; +} + +ScStyleSaveData& ScStyleSaveData::operator=( const ScStyleSaveData& rOther ) +{ + aName = rOther.aName; + aParent = rOther.aParent; + + delete pItems; + if (rOther.pItems) + pItems = new SfxItemSet( *rOther.pItems ); + else + pItems = NULL; + + return *this; +} + +void ScStyleSaveData::InitFromStyle( const SfxStyleSheetBase* pSource ) +{ + if ( pSource ) + { + aName = pSource->GetName(); + aParent = pSource->GetParent(); + delete pItems; + pItems = new SfxItemSet( ((SfxStyleSheetBase*)pSource)->GetItemSet() ); + } + else + *this = ScStyleSaveData(); // empty +} + +// ----------------------------------------------------------------------- + +ScUndoModifyStyle::ScUndoModifyStyle( ScDocShell* pDocSh, SfxStyleFamily eFam, + const ScStyleSaveData& rOld, const ScStyleSaveData& rNew ) : + ScSimpleUndo( pDocSh ), + eFamily( eFam ), + aOldData( rOld ), + aNewData( rNew ) +{ +} + +ScUndoModifyStyle::~ScUndoModifyStyle() +{ +} + +String ScUndoModifyStyle::GetComment() const +{ + sal_uInt16 nId = (eFamily == SFX_STYLE_FAMILY_PARA) ? + STR_UNDO_EDITCELLSTYLE : + STR_UNDO_EDITPAGESTYLE; + return ScGlobal::GetRscString( nId ); +} + +void lcl_DocStyleChanged( ScDocument* pDoc, SfxStyleSheetBase* pStyle, sal_Bool bRemoved ) +{ + //! move to document or docshell + + VirtualDevice aVDev; + Point aLogic = aVDev.LogicToPixel( Point(1000,1000), MAP_TWIP ); + double nPPTX = aLogic.X() / 1000.0; + double nPPTY = aLogic.Y() / 1000.0; + Fraction aZoom(1,1); + pDoc->StyleSheetChanged( pStyle, bRemoved, &aVDev, nPPTX, nPPTY, aZoom, aZoom ); + + ScInputHandler* pHdl = SC_MOD()->GetInputHdl(); + if (pHdl) + pHdl->ForgetLastPattern(); +} + +void ScUndoModifyStyle::DoChange( ScDocShell* pDocSh, const String& rName, + SfxStyleFamily eStyleFamily, const ScStyleSaveData& rData ) +{ + ScDocument* pDoc = pDocSh->GetDocument(); + ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool(); + String aNewName = rData.GetName(); + sal_Bool bDelete = ( aNewName.Len() == 0 ); // no new name -> delete style + sal_Bool bNew = ( rName.Len() == 0 && !bDelete ); // creating new style + + SfxStyleSheetBase* pStyle = NULL; + if ( rName.Len() ) + { + // find old style to modify + pStyle = pStlPool->Find( rName, eStyleFamily ); + DBG_ASSERT( pStyle, "style not found" ); + + if ( pStyle && !bDelete ) + { + // set new name + pStyle->SetName( aNewName ); + } + } + else if ( !bDelete ) + { + // create style (with new name) + pStyle = &pStlPool->Make( aNewName, eStyleFamily, SFXSTYLEBIT_USERDEF ); + + if ( eStyleFamily == SFX_STYLE_FAMILY_PARA ) + pDoc->GetPool()->CellStyleCreated( aNewName ); + } + + if ( pStyle ) + { + if ( bDelete ) + { + if ( eStyleFamily == SFX_STYLE_FAMILY_PARA ) + lcl_DocStyleChanged( pDoc, pStyle, sal_True ); // TRUE: remove usage of style + else + pDoc->RemovePageStyleInUse( rName ); + + // delete style + pStlPool->Remove( pStyle ); + } + else + { + // modify style + + String aNewParent = rData.GetParent(); + if ( aNewParent != pStyle->GetParent() ) + pStyle->SetParent( aNewParent ); + + SfxItemSet& rStyleSet = pStyle->GetItemSet(); + const SfxItemSet* pNewSet = rData.GetItems(); + DBG_ASSERT( pNewSet, "no ItemSet for style" ); + if (pNewSet) + rStyleSet.Set( *pNewSet, false ); + + if ( eStyleFamily == SFX_STYLE_FAMILY_PARA ) + { + lcl_DocStyleChanged( pDoc, pStyle, false ); // cell styles: row heights + } + else + { + // page styles + + if ( bNew && aNewName != rName ) + pDoc->RenamePageStyleInUse( rName, aNewName ); + + if (pNewSet) + pDoc->ModifyStyleSheet( *pStyle, *pNewSet ); + + pDocSh->PageStyleModified( aNewName, sal_True ); + } + } + } + + pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT ); + + //! undo/redo document modifications for deleted styles + //! undo/redo modifications of number formatter +} + +void ScUndoModifyStyle::Undo() +{ + BeginUndo(); + DoChange( pDocShell, aNewData.GetName(), eFamily, aOldData ); + EndUndo(); +} + +void ScUndoModifyStyle::Redo() +{ + BeginRedo(); + DoChange( pDocShell, aOldData.GetName(), eFamily, aNewData ); + EndRedo(); +} + +void ScUndoModifyStyle::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoModifyStyle::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // no repeat possible +} + +// ----------------------------------------------------------------------- +// +// apply page style +// +ScUndoApplyPageStyle::ApplyStyleEntry::ApplyStyleEntry( SCTAB nTab, const String& rOldStyle ) : + mnTab( nTab ), + maOldStyle( rOldStyle ) +{ +} + +ScUndoApplyPageStyle::ScUndoApplyPageStyle( ScDocShell* pDocSh, const String& rNewStyle ) : + ScSimpleUndo( pDocSh ), + maNewStyle( rNewStyle ) +{ +} + +ScUndoApplyPageStyle::~ScUndoApplyPageStyle() +{ +} + +void ScUndoApplyPageStyle::AddSheetAction( SCTAB nTab, const String& rOldStyle ) +{ + maEntries.push_back( ApplyStyleEntry( nTab, rOldStyle ) ); +} + +String ScUndoApplyPageStyle::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_APPLYPAGESTYLE ); +} + +void ScUndoApplyPageStyle::Undo() +{ + BeginUndo(); + for( ApplyStyleVec::const_iterator aIt = maEntries.begin(), aEnd = maEntries.end(); aIt != aEnd; ++aIt ) + { + pDocShell->GetDocument()->SetPageStyle( aIt->mnTab, aIt->maOldStyle ); + ScPrintFunc( pDocShell, pDocShell->GetPrinter(), aIt->mnTab ).UpdatePages(); + } + EndUndo(); +} + +void ScUndoApplyPageStyle::Redo() +{ + BeginRedo(); + for( ApplyStyleVec::const_iterator aIt = maEntries.begin(), aEnd = maEntries.end(); aIt != aEnd; ++aIt ) + { + pDocShell->GetDocument()->SetPageStyle( aIt->mnTab, maNewStyle ); + ScPrintFunc( pDocShell, pDocShell->GetPrinter(), aIt->mnTab ).UpdatePages(); + } + EndRedo(); +} + +void ScUndoApplyPageStyle::Repeat(SfxRepeatTarget& /* rTarget */) +{ + //! set same page style to current tab +} + +sal_Bool ScUndoApplyPageStyle::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undotab.cxx b/sc/source/ui/undo/undotab.cxx new file mode 100644 index 000000000000..97f2549711e1 --- /dev/null +++ b/sc/source/ui/undo/undotab.cxx @@ -0,0 +1,1680 @@ +/* -*- 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_sc.hxx" + +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <svl/smplhint.hxx> + +#include "undotab.hxx" +#include "document.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "sc.hrc" +#include "undoolk.hxx" +#include "target.hxx" +#include "uiitems.hxx" +#include "prnsave.hxx" +#include "printfun.hxx" +#include "chgtrack.hxx" +#include "tabprotection.hxx" +#include "viewdata.hxx" + +// for ScUndoRenameObject - might me moved to another file later +#include <svx/svditer.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdpage.hxx> +#include "drwlayer.hxx" +#include "scresid.hxx" + +#include <vector> + +extern sal_Bool bDrawIsInUndo; //! irgendwo als Member !!! + +using namespace com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; +using ::std::auto_ptr; +using ::std::vector; +using ::boost::shared_ptr; + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1(ScUndoInsertTab, SfxUndoAction); +TYPEINIT1(ScUndoInsertTables, SfxUndoAction); +TYPEINIT1(ScUndoDeleteTab, SfxUndoAction); +TYPEINIT1(ScUndoRenameTab, SfxUndoAction); +TYPEINIT1(ScUndoMoveTab, SfxUndoAction); +TYPEINIT1(ScUndoCopyTab, SfxUndoAction); +TYPEINIT1(ScUndoMakeScenario, SfxUndoAction); +TYPEINIT1(ScUndoImportTab, SfxUndoAction); +TYPEINIT1(ScUndoRemoveLink, SfxUndoAction); +TYPEINIT1(ScUndoShowHideTab, SfxUndoAction); +TYPEINIT1(ScUndoPrintRange, SfxUndoAction); +TYPEINIT1(ScUndoScenarioFlags, SfxUndoAction); +TYPEINIT1(ScUndoRenameObject, SfxUndoAction); +TYPEINIT1(ScUndoLayoutRTL, SfxUndoAction); +TYPEINIT1(ScUndoTabColor, SfxUndoAction); + + +// ----------------------------------------------------------------------- +// +// Tabelle einfuegen +// + +ScUndoInsertTab::ScUndoInsertTab( ScDocShell* pNewDocShell, + SCTAB nTabNum, + sal_Bool bApp, + const String& rNewName) : + ScSimpleUndo( pNewDocShell ), + sNewName( rNewName ), + pDrawUndo( NULL ), + nTab( nTabNum ), + bAppend( bApp ) +{ + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); + SetChangeTrack(); +} + +ScUndoInsertTab::~ScUndoInsertTab() +{ + DeleteSdrUndoAction( pDrawUndo ); +} + +String ScUndoInsertTab::GetComment() const +{ + if (bAppend) + return ScGlobal::GetRscString( STR_UNDO_APPEND_TAB ); + else + return ScGlobal::GetRscString( STR_UNDO_INSERT_TAB ); +} + +void ScUndoInsertTab::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + { + ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab ); + pChangeTrack->AppendInsert( aRange ); + nEndChangeAction = pChangeTrack->GetActionMax(); + } + else + nEndChangeAction = 0; +} + +void ScUndoInsertTab::Undo() +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + pViewShell->SetTabNo(nTab); + + pDocShell->SetInUndo( sal_True ); //! BeginUndo + bDrawIsInUndo = sal_True; + pViewShell->DeleteTable( nTab, false ); + bDrawIsInUndo = false; + pDocShell->SetInUndo( false ); //! EndUndo + + DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); + + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nEndChangeAction, nEndChangeAction ); + + // SetTabNo(...,sal_True) for all views to sync with drawing layer pages + pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) ); +} + +void ScUndoInsertTab::Redo() +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + RedoSdrUndoAction( pDrawUndo ); // Draw Redo first + + pDocShell->SetInUndo( sal_True ); //! BeginRedo + bDrawIsInUndo = sal_True; + if (bAppend) + pViewShell->AppendTable( sNewName, false ); + else + { + pViewShell->SetTabNo(nTab); + pViewShell->InsertTable( sNewName, nTab, false ); + } + bDrawIsInUndo = false; + pDocShell->SetInUndo( false ); //! EndRedo + + SetChangeTrack(); +} + +void ScUndoInsertTab::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). + Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); +} + +sal_Bool ScUndoInsertTab::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +// ----------------------------------------------------------------------- +// +// Tabellen einfuegen +// + +ScUndoInsertTables::ScUndoInsertTables( ScDocShell* pNewDocShell, + SCTAB nTabNum, + sal_Bool bApp,SvStrings *pNewNameList) : + ScSimpleUndo( pNewDocShell ), + pDrawUndo( NULL ), + nTab( nTabNum ), + bAppend( bApp ) +{ + pNameList = pNewNameList; + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); + + SetChangeTrack(); +} + +ScUndoInsertTables::~ScUndoInsertTables() +{ + String *pStr=NULL; + if(pNameList!=NULL) + { + for(int i=0;i<pNameList->Count();i++) + { + pStr=pNameList->GetObject(sal::static_int_cast<sal_uInt16>(i)); + delete pStr; + } + pNameList->Remove(0,pNameList->Count()); + delete pNameList; + } + DeleteSdrUndoAction( pDrawUndo ); +} + +String ScUndoInsertTables::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_INSERT_TAB ); +} + +void ScUndoInsertTables::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + { + nStartChangeAction = pChangeTrack->GetActionMax() + 1; + nEndChangeAction = 0; + ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab ); + for( int i = 0; i < pNameList->Count(); i++ ) + { + aRange.aStart.SetTab( sal::static_int_cast<SCTAB>( nTab + i ) ); + aRange.aEnd.SetTab( sal::static_int_cast<SCTAB>( nTab + i ) ); + pChangeTrack->AppendInsert( aRange ); + nEndChangeAction = pChangeTrack->GetActionMax(); + } + } + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoInsertTables::Undo() +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + pViewShell->SetTabNo(nTab); + + pDocShell->SetInUndo( sal_True ); //! BeginUndo + bDrawIsInUndo = sal_True; + + vector<SCTAB> TheTabs; + for(int i=0; i<pNameList->Count(); ++i) + { + TheTabs.push_back(nTab+i); + } + pViewShell->DeleteTables( TheTabs, false ); + TheTabs.clear(); + + bDrawIsInUndo = false; + pDocShell->SetInUndo( false ); //! EndUndo + + DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); + + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + + // SetTabNo(...,sal_True) for all views to sync with drawing layer pages + pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) ); +} + +void ScUndoInsertTables::Redo() +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + RedoSdrUndoAction( pDrawUndo ); // Draw Redo first + + pDocShell->SetInUndo( sal_True ); //! BeginRedo + bDrawIsInUndo = sal_True; + pViewShell->SetTabNo(nTab); + pViewShell->InsertTables( pNameList, nTab, static_cast<SCTAB>(pNameList->Count()),false ); + + bDrawIsInUndo = false; + pDocShell->SetInUndo( false ); //! EndRedo + + SetChangeTrack(); +} + +void ScUndoInsertTables::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). + Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); +} + +sal_Bool ScUndoInsertTables::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +//---------------------------------------------------------------------------------- +// +// Tabelle loeschen +// + +ScUndoDeleteTab::ScUndoDeleteTab( ScDocShell* pNewDocShell, const vector<SCTAB> &aTab, //SCTAB nNewTab, + ScDocument* pUndoDocument, ScRefUndoData* pRefData ) : + ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ) +{ + theTabs.insert(theTabs.end(), aTab.begin(), aTab.end() ); + SetChangeTrack(); +} + +ScUndoDeleteTab::~ScUndoDeleteTab() +{ + theTabs.clear(); +} + +String ScUndoDeleteTab::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_DELETE_TAB ); +} + +void ScUndoDeleteTab::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + { + sal_uLong nTmpChangeAction; + nStartChangeAction = pChangeTrack->GetActionMax() + 1; + nEndChangeAction = 0; + ScRange aRange( 0, 0, 0, MAXCOL, MAXROW, 0 ); + for ( unsigned int i = 0; i < theTabs.size(); ++i ) + { + aRange.aStart.SetTab( theTabs[i] ); + aRange.aEnd.SetTab( theTabs[i] ); + pChangeTrack->AppendDeleteRange( aRange, pRefUndoDoc, + nTmpChangeAction, nEndChangeAction, (short) i ); + } + } + else + nStartChangeAction = nEndChangeAction = 0; +} + +SCTAB lcl_GetVisibleTabBefore( ScDocument& rDoc, SCTAB nTab ) +{ + while ( nTab > 0 && !rDoc.IsVisible( nTab ) ) + --nTab; + + return nTab; +} + +void ScUndoDeleteTab::Undo() +{ + BeginUndo(); + unsigned int i=0; + ScDocument* pDoc = pDocShell->GetDocument(); + + sal_Bool bLink = false; + String aName; + + for(i=0; i<theTabs.size(); ++i) + { + SCTAB nTab = theTabs[i]; + pRefUndoDoc->GetName( nTab, aName ); + + bDrawIsInUndo = sal_True; + sal_Bool bOk = pDoc->InsertTab( nTab, aName ); + bDrawIsInUndo = false; + if (bOk) + { + pRefUndoDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,false, pDoc ); + + String aOldName; + pRefUndoDoc->GetName( nTab, aOldName ); + pDoc->RenameTab( nTab, aOldName, false ); + if (pRefUndoDoc->IsLinked(nTab)) + { + pDoc->SetLink( nTab, pRefUndoDoc->GetLinkMode(nTab), pRefUndoDoc->GetLinkDoc(nTab), + pRefUndoDoc->GetLinkFlt(nTab), pRefUndoDoc->GetLinkOpt(nTab), + pRefUndoDoc->GetLinkTab(nTab), pRefUndoDoc->GetLinkRefreshDelay(nTab) ); + bLink = sal_True; + } + + if ( pRefUndoDoc->IsScenario(nTab) ) + { + pDoc->SetScenario( nTab, sal_True ); + String aComment; + Color aColor; + sal_uInt16 nScenFlags; + pRefUndoDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags ); + pDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags ); + sal_Bool bActive = pRefUndoDoc->IsActiveScenario( nTab ); + pDoc->SetActiveScenario( nTab, bActive ); + } + pDoc->SetVisible( nTab, pRefUndoDoc->IsVisible( nTab ) ); + pDoc->SetTabBgColor( nTab, pRefUndoDoc->GetTabBgColor(nTab) ); + pDoc->SetSheetEvents( nTab, pRefUndoDoc->GetSheetEvents( nTab ) ); + + if ( pRefUndoDoc->IsTabProtected( nTab ) ) + pDoc->SetTabProtection(nTab, pRefUndoDoc->GetTabProtection(nTab)); + } + } + if (bLink) + { + pDocShell->UpdateLinks(); // Link-Manager updaten + } + + EndUndo(); // Draw-Undo muss vor dem Broadcast kommen! + + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + + for(i=0; i<theTabs.size(); ++i) + { + pDocShell->Broadcast( ScTablesHint( SC_TAB_INSERTED, theTabs[i]) ); + } + SfxApplication* pSfxApp = SFX_APP(); // Navigator + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) ); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); + + pDocShell->PostPaint(0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_ALL ); // incl. Extras + + // nicht ShowTable wegen SetTabNo(..., sal_True): + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->SetTabNo( lcl_GetVisibleTabBefore( *pDoc, theTabs[0] ), true ); +} + +void ScUndoDeleteTab::Redo() +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + pViewShell->SetTabNo( lcl_GetVisibleTabBefore( *pDocShell->GetDocument(), theTabs.front() ) ); + + RedoSdrUndoAction( pDrawUndo ); // Draw Redo first + + pDocShell->SetInUndo( sal_True ); //! BeginRedo + bDrawIsInUndo = sal_True; + pViewShell->DeleteTables( theTabs, false ); + bDrawIsInUndo = false; + pDocShell->SetInUndo( sal_True ); //! EndRedo + + SetChangeTrack(); + + // SetTabNo(...,sal_True) for all views to sync with drawing layer pages + pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) ); +} + +void ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ScTabViewShell* pViewShell = ((ScTabViewTarget&)rTarget).GetViewShell(); + pViewShell->DeleteTable( pViewShell->GetViewData()->GetTabNo(), sal_True ); + } +} + +sal_Bool ScUndoDeleteTab::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +//--------------------------------------------------------------------------------- +// +// Tabelle umbenennen +// + +ScUndoRenameTab::ScUndoRenameTab( ScDocShell* pNewDocShell, + SCTAB nT, + const String& rOldName, + const String& rNewName) : + ScSimpleUndo( pNewDocShell ), + nTab ( nT ) +{ + sOldName = rOldName; + sNewName = rNewName; +} + +ScUndoRenameTab::~ScUndoRenameTab() +{ +} + +String ScUndoRenameTab::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_RENAME_TAB ); +} + +void ScUndoRenameTab::DoChange( SCTAB nTabP, const String& rName ) const +{ + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->RenameTab( nTabP, rName ); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); // Navigator + + pDocShell->PostPaintGridAll(); + pDocShell->PostPaintExtras(); + pDocShell->PostDataChanged(); + + // Der Tabellenname koennte in einer Formel vorkommen... + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->UpdateInputHandler(); +} + +void ScUndoRenameTab::Undo() +{ + DoChange(nTab, sOldName); +} + +void ScUndoRenameTab::Redo() +{ + DoChange(nTab, sNewName); +} + +void ScUndoRenameTab::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // Repeat macht keinen Sinn +} + +sal_Bool ScUndoRenameTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +//---------------------------------------------------------------------------------- +// +// Tabelle verschieben +// + +ScUndoMoveTab::ScUndoMoveTab( + ScDocShell* pNewDocShell, vector<SCTAB>* pOldTabs, vector<SCTAB>* pNewTabs, + vector<OUString>* pOldNames, vector<OUString>* pNewNames) : + ScSimpleUndo( pNewDocShell ), + mpOldTabs(pOldTabs), mpNewTabs(pNewTabs), + mpOldNames(pOldNames), mpNewNames(pNewNames) +{ + if (mpOldNames && mpOldTabs->size() != mpOldNames->size()) + // The sizes differ. Something is wrong. + mpOldNames.reset(); + + if (mpNewNames && mpNewTabs->size() != mpNewNames->size()) + // The sizes differ. Something is wrong. + mpNewNames.reset(); +} + +ScUndoMoveTab::~ScUndoMoveTab() +{ +} + +String ScUndoMoveTab::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_MOVE_TAB ); +} + +void ScUndoMoveTab::DoChange( sal_Bool bUndo ) const +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + if (bUndo) // UnDo + { + for (size_t i = mpNewTabs->size(); i > 0; --i) + { + SCTAB nDestTab = (*mpNewTabs)[i-1]; + SCTAB nOldTab = (*mpOldTabs)[i-1]; + if (nDestTab > MAXTAB) // angehaengt ? + nDestTab = pDoc->GetTableCount() - 1; + + pDoc->MoveTab( nDestTab, nOldTab ); + pViewShell->GetViewData()->MoveTab( nDestTab, nOldTab ); + pViewShell->SetTabNo( nOldTab, true ); + if (mpOldNames) + { + const OUString& rOldName = (*mpOldNames)[i-1]; + pDoc->RenameTab(nOldTab, rOldName); + } + } + } + else + { + for (size_t i = 0, n = mpNewTabs->size(); i < n; ++i) + { + SCTAB nDestTab = (*mpNewTabs)[i]; + SCTAB nNewTab = nDestTab; + SCTAB nOldTab = (*mpOldTabs)[i]; + if (nDestTab > MAXTAB) // angehaengt ? + nDestTab = pDoc->GetTableCount() - 1; + + pDoc->MoveTab( nOldTab, nNewTab ); + pViewShell->GetViewData()->MoveTab( nOldTab, nNewTab ); + pViewShell->SetTabNo( nDestTab, true ); + if (mpNewNames) + { + const OUString& rNewName = (*mpNewNames)[i]; + pDoc->RenameTab(nNewTab, rNewName); + } + } + } + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); // Navigator + + pDocShell->PostPaintGridAll(); + pDocShell->PostPaintExtras(); + pDocShell->PostDataChanged(); +} + +void ScUndoMoveTab::Undo() +{ + DoChange( sal_True ); +} + +void ScUndoMoveTab::Redo() +{ + DoChange( false ); +} + +void ScUndoMoveTab::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // No Repeat ! ? ! +} + +sal_Bool ScUndoMoveTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +//---------------------------------------------------------------------------------- +// +// Copy table +// + +ScUndoCopyTab::ScUndoCopyTab( + ScDocShell* pNewDocShell, + vector<SCTAB>* pOldTabs, vector<SCTAB>* pNewTabs, + vector<OUString>* pNewNames) : + ScSimpleUndo( pNewDocShell ), + mpOldTabs(pOldTabs), + mpNewTabs(pNewTabs), + mpNewNames(pNewNames), + pDrawUndo( NULL ) +{ + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); + + if (mpNewNames && mpNewTabs->size() != mpNewNames->size()) + // The sizes differ. Something is wrong. + mpNewNames.reset(); +} + +ScUndoCopyTab::~ScUndoCopyTab() +{ + DeleteSdrUndoAction( pDrawUndo ); +} + +String ScUndoCopyTab::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_COPY_TAB ); +} + +void ScUndoCopyTab::DoChange() const +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + if (pViewShell) + pViewShell->SetTabNo((*mpOldTabs)[0],true); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); // Navigator + + pDocShell->PostPaintGridAll(); + pDocShell->PostPaintExtras(); + pDocShell->PostDataChanged(); +} + +void ScUndoCopyTab::Undo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + DoSdrUndoAction( pDrawUndo, pDoc ); // before the sheets are deleted + + vector<SCTAB>::const_reverse_iterator itr, itrEnd = mpNewTabs->rend(); + for (itr = mpNewTabs->rbegin(); itr != itrEnd; ++itr) + { + SCTAB nDestTab = *itr; + if (nDestTab > MAXTAB) // append? + nDestTab = pDoc->GetTableCount() - 1; + + bDrawIsInUndo = sal_True; + pDoc->DeleteTab(nDestTab); + bDrawIsInUndo = false; + } + + // ScTablesHint broadcasts after all sheets have been deleted, + // so sheets and draw pages are in sync! + + for (itr = mpNewTabs->rbegin(); itr != itrEnd; ++itr) + { + SCTAB nDestTab = *itr; + if (nDestTab > MAXTAB) // append? + nDestTab = pDoc->GetTableCount() - 1; + + pDocShell->Broadcast( ScTablesHint( SC_TAB_DELETED, nDestTab ) ); + } + + DoChange(); +} + +void ScUndoCopyTab::Redo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + SCTAB nDestTab = 0; + for (size_t i = 0, n = mpNewTabs->size(); i < n; ++i) + { + nDestTab = (*mpNewTabs)[i]; + SCTAB nNewTab = nDestTab; + SCTAB nOldTab = (*mpOldTabs)[i]; + if (nDestTab > MAXTAB) // angehaengt ? + nDestTab = pDoc->GetTableCount() - 1; + + bDrawIsInUndo = sal_True; + pDoc->CopyTab( nOldTab, nNewTab ); + bDrawIsInUndo = false; + + pViewShell->GetViewData()->MoveTab( nOldTab, nNewTab ); + + SCTAB nAdjSource = nOldTab; + if ( nNewTab <= nOldTab ) + ++nAdjSource; // new position of source table after CopyTab + + if ( pDoc->IsScenario(nAdjSource) ) + { + pDoc->SetScenario(nNewTab, sal_True ); + String aComment; + Color aColor; + sal_uInt16 nScenFlags; + pDoc->GetScenarioData(nAdjSource, aComment, aColor, nScenFlags ); + pDoc->SetScenarioData(nNewTab, aComment, aColor, nScenFlags ); + sal_Bool bActive = pDoc->IsActiveScenario(nAdjSource); + pDoc->SetActiveScenario(nNewTab, bActive ); + sal_Bool bVisible=pDoc->IsVisible(nAdjSource); + pDoc->SetVisible(nNewTab,bVisible ); + } + + if ( pDoc->IsTabProtected( nAdjSource ) ) + pDoc->CopyTabProtection(nAdjSource, nNewTab); + + if (mpNewNames) + { + const OUString& rName = (*mpNewNames)[i]; + pDoc->RenameTab(nNewTab, rName); + } + } + + RedoSdrUndoAction( pDrawUndo ); // after the sheets are inserted + + pViewShell->SetTabNo( nDestTab, sal_True ); // after draw-undo + + DoChange(); + +} + +void ScUndoCopyTab::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // kein Repeat ! ? ! +} + +sal_Bool ScUndoCopyTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + +//--------------------------------------------------------------------------------- +// +// Tab Bg Color +// + +ScUndoTabColor::ScUndoTabColor( + ScDocShell* pNewDocShell, SCTAB nT, const Color& aOTabBgColor, const Color& aNTabBgColor) : + ScSimpleUndo( pNewDocShell ) +{ + ScUndoTabColorInfo aInfo(nT); + aInfo.maOldTabBgColor = aOTabBgColor; + aInfo.maNewTabBgColor = aNTabBgColor; + aTabColorList.push_back(aInfo); +} + +ScUndoTabColor::ScUndoTabColor( + ScDocShell* pNewDocShell, + const ScUndoTabColorInfo::List& rUndoTabColorList) : + ScSimpleUndo(pNewDocShell), + aTabColorList(rUndoTabColorList) +{ +} + +ScUndoTabColor::~ScUndoTabColor() +{ +} + +String ScUndoTabColor::GetComment() const +{ + if (aTabColorList.size() > 1) + return ScGlobal::GetRscString(STR_UNDO_SET_MULTI_TAB_BG_COLOR); + return ScGlobal::GetRscString(STR_UNDO_SET_TAB_BG_COLOR); +} + +void ScUndoTabColor::DoChange(bool bUndoType) const +{ + ScDocument* pDoc = pDocShell->GetDocument(); + if (!pDoc) + return; + + size_t nTabColorCount = aTabColorList.size(); + for (size_t i = 0; i < nTabColorCount; ++i) + { + const ScUndoTabColorInfo& rTabColor = aTabColorList[i]; + pDoc->SetTabBgColor(rTabColor.mnTabId, + bUndoType ? rTabColor.maOldTabBgColor : rTabColor.maNewTabBgColor); + } + + pDocShell->PostPaintExtras(); + ScDocShellModificator aModificator( *pDocShell ); + aModificator.SetDocumentModified(); +} + +void ScUndoTabColor::Undo() +{ + DoChange(true); +} + +void ScUndoTabColor::Redo() +{ + DoChange(false); +} + +void ScUndoTabColor::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // No Repeat +} + +sal_Bool ScUndoTabColor::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + +// ----------------------------------------------------------------------- +// +// Szenario anlegen +// + +ScUndoMakeScenario::ScUndoMakeScenario( ScDocShell* pNewDocShell, + SCTAB nSrc, SCTAB nDest, + const String& rN, const String& rC, + const Color& rCol, sal_uInt16 nF, + const ScMarkData& rMark ) : + ScSimpleUndo( pNewDocShell ), + nSrcTab( nSrc ), + nDestTab( nDest ), + aName( rN ), + aComment( rC ), + aColor( rCol ), + nFlags( nF ), + aMarkData( rMark ), + pDrawUndo( NULL ) +{ + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); +} + +ScUndoMakeScenario::~ScUndoMakeScenario() +{ + DeleteSdrUndoAction( pDrawUndo ); +} + +String ScUndoMakeScenario::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_MAKESCENARIO ); +} + +void ScUndoMakeScenario::Undo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + pDocShell->SetInUndo( sal_True ); + bDrawIsInUndo = sal_True; + pDoc->DeleteTab( nDestTab ); + bDrawIsInUndo = false; + pDocShell->SetInUndo( false ); + + DoSdrUndoAction( pDrawUndo, pDoc ); + + pDocShell->PostPaint(0,0,nDestTab,MAXCOL,MAXROW,MAXTAB, PAINT_ALL); + pDocShell->PostDataChanged(); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->SetTabNo( nSrcTab, sal_True ); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + + // SetTabNo(...,sal_True) for all views to sync with drawing layer pages + pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) ); +} + +void ScUndoMakeScenario::Redo() +{ + SetViewMarkData( aMarkData ); + + RedoSdrUndoAction( pDrawUndo ); // Draw Redo first + + pDocShell->SetInUndo( sal_True ); + bDrawIsInUndo = sal_True; + + pDocShell->MakeScenario( nSrcTab, aName, aComment, aColor, nFlags, aMarkData, false ); + + bDrawIsInUndo = false; + pDocShell->SetInUndo( false ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->SetTabNo( nDestTab, sal_True ); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); +} + +void ScUndoMakeScenario::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + { + ((ScTabViewTarget&)rTarget).GetViewShell()->MakeScenario( aName, aComment, aColor, nFlags ); + } +} + +sal_Bool ScUndoMakeScenario::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Tabelle einfuegen +// + +ScUndoImportTab::ScUndoImportTab( ScDocShell* pShell, + SCTAB nNewTab, SCTAB nNewCount, sal_Bool bNewLink ) : + ScSimpleUndo( pShell ), + nTab( nNewTab ), + nCount( nNewCount ), + bLink( bNewLink ), + pRedoDoc( NULL ), + pDrawUndo( NULL ) +{ + pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); +} + +ScUndoImportTab::~ScUndoImportTab() +{ + delete pRedoDoc; + DeleteSdrUndoAction( pDrawUndo ); +} + +String ScUndoImportTab::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_INSERT_TAB ); +} + +void ScUndoImportTab::DoChange() const +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + if (pViewShell) + { + if(nTab<nTabCount) + { + pViewShell->SetTabNo(nTab,sal_True); + } + else + { + pViewShell->SetTabNo(nTab-1,sal_True); + } + } + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); // Navigator + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, + PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS ); +} + +void ScUndoImportTab::Undo() +{ + //! eingefuegte Bereichsnamen etc. + + SCTAB i; + ScDocument* pDoc = pDocShell->GetDocument(); + sal_Bool bMakeRedo = !pRedoDoc; + if (bMakeRedo) + { + pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); + pRedoDoc->InitUndo( pDoc, nTab,nTab+nCount-1, sal_True,sal_True ); + + String aOldName; + for (i=0; i<nCount; i++) + { + SCTAB nTabPos=nTab+i; + + pDoc->CopyToDocument(0,0,nTabPos, MAXCOL,MAXROW,nTabPos, IDF_ALL,false, pRedoDoc ); + pDoc->GetName( nTabPos, aOldName ); + pRedoDoc->RenameTab( nTabPos, aOldName, false ); + + if ( pDoc->IsScenario(nTabPos) ) + { + pRedoDoc->SetScenario(nTabPos, sal_True ); + String aComment; + Color aColor; + sal_uInt16 nScenFlags; + pDoc->GetScenarioData(nTabPos, aComment, aColor, nScenFlags ); + pRedoDoc->SetScenarioData(nTabPos, aComment, aColor, nScenFlags ); + sal_Bool bActive = pDoc->IsActiveScenario(nTabPos); + pRedoDoc->SetActiveScenario(nTabPos, bActive ); + sal_Bool bVisible=pDoc->IsVisible(nTabPos); + pRedoDoc->SetVisible(nTabPos,bVisible ); + } + + if ( pDoc->IsTabProtected( nTabPos ) ) + pRedoDoc->SetTabProtection(nTabPos, pDoc->GetTabProtection(nTabPos)); + } + + } + + DoSdrUndoAction( pDrawUndo, pDoc ); // before the sheets are deleted + + bDrawIsInUndo = sal_True; + for (i=0; i<nCount; i++) + pDoc->DeleteTab( nTab ); + bDrawIsInUndo = false; + + DoChange(); +} + +void ScUndoImportTab::Redo() +{ + if (!pRedoDoc) + { + OSL_FAIL("wo ist mein Redo-Document?"); + return; + } + + ScDocument* pDoc = pDocShell->GetDocument(); + String aName; + SCTAB i; + for (i=0; i<nCount; i++) // first insert all sheets (#63304#) + { + SCTAB nTabPos=nTab+i; + pRedoDoc->GetName(nTabPos,aName); + bDrawIsInUndo = sal_True; + pDoc->InsertTab(nTabPos,aName); + bDrawIsInUndo = false; + } + for (i=0; i<nCount; i++) // then copy into inserted sheets + { + SCTAB nTabPos=nTab+i; + pRedoDoc->CopyToDocument(0,0,nTabPos, MAXCOL,MAXROW,nTabPos, IDF_ALL,false, pDoc ); + + if ( pRedoDoc->IsScenario(nTabPos) ) + { + pDoc->SetScenario(nTabPos, sal_True ); + String aComment; + Color aColor; + sal_uInt16 nScenFlags; + pRedoDoc->GetScenarioData(nTabPos, aComment, aColor, nScenFlags ); + pDoc->SetScenarioData(nTabPos, aComment, aColor, nScenFlags ); + sal_Bool bActive = pRedoDoc->IsActiveScenario(nTabPos); + pDoc->SetActiveScenario(nTabPos, bActive ); + sal_Bool bVisible=pRedoDoc->IsVisible(nTabPos); + pDoc->SetVisible(nTabPos,bVisible ); + } + + if ( pRedoDoc->IsTabProtected( nTabPos ) ) + pDoc->SetTabProtection(nTabPos, pRedoDoc->GetTabProtection(nTabPos)); + } + + RedoSdrUndoAction( pDrawUndo ); // after the sheets are inserted + + DoChange(); +} + +void ScUndoImportTab::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). + Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); +} + +sal_Bool ScUndoImportTab::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + + +// ----------------------------------------------------------------------- +// +// Tabellen-Verknuepfung aufheben +// + +ScUndoRemoveLink::ScUndoRemoveLink( ScDocShell* pShell, const String& rDoc ) : + ScSimpleUndo( pShell ), + aDocName( rDoc ), + nCount( 0 ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + pTabs = new SCTAB[nTabCount]; + pModes = new sal_uInt8[nTabCount]; + pTabNames = new String[nTabCount]; + + for (SCTAB i=0; i<nTabCount; i++) + { + sal_uInt8 nMode = pDoc->GetLinkMode(i); + if (nMode) + if (pDoc->GetLinkDoc(i) == aDocName) + { + if (!nCount) + { + aFltName = pDoc->GetLinkFlt(i); + aOptions = pDoc->GetLinkOpt(i); + nRefreshDelay = pDoc->GetLinkRefreshDelay(i); + } + else + { + DBG_ASSERT(aFltName == pDoc->GetLinkFlt(i) && + aOptions == pDoc->GetLinkOpt(i), + "verschiedene Filter fuer ein Dokument?"); + } + pTabs[nCount] = i; + pModes[nCount] = nMode; + pTabNames[nCount] = pDoc->GetLinkTab(i); + ++nCount; + } + } +} + +ScUndoRemoveLink::~ScUndoRemoveLink() +{ + delete pTabs; + delete pModes; + delete[] pTabNames; +} + +String ScUndoRemoveLink::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_REMOVELINK ); +} + +void ScUndoRemoveLink::DoChange( sal_Bool bLink ) const +{ + ScDocument* pDoc = pDocShell->GetDocument(); + String aEmpty; + for (sal_uInt16 i=0; i<nCount; i++) + if (bLink) // establish link + pDoc->SetLink( pTabs[i], pModes[i], aDocName, aFltName, aOptions, pTabNames[i], nRefreshDelay ); + else // remove link + pDoc->SetLink( pTabs[i], SC_LINK_NONE, aEmpty, aEmpty, aEmpty, aEmpty, 0 ); + pDocShell->UpdateLinks(); +} + +void ScUndoRemoveLink::Undo() +{ + DoChange( sal_True ); +} + +void ScUndoRemoveLink::Redo() +{ + DoChange( false ); +} + +void ScUndoRemoveLink::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + +sal_Bool ScUndoRemoveLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +// ----------------------------------------------------------------------- +// +// Tabellen ein-/ausblenden +// + +ScUndoShowHideTab::ScUndoShowHideTab( ScDocShell* pShell, SCTAB nNewTab, sal_Bool bNewShow ) : + ScSimpleUndo( pShell ), + nTab( nNewTab ), + bShow( bNewShow ) +{ +} + +ScUndoShowHideTab::~ScUndoShowHideTab() +{ +} + +void ScUndoShowHideTab::DoChange( sal_Bool bShowP ) const +{ + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->SetVisible( nTab, bShowP ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->SetTabNo(nTab,sal_True); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pDocShell->SetDocumentModified(); +} + +void ScUndoShowHideTab::Undo() +{ + DoChange(!bShow); +} + +void ScUndoShowHideTab::Redo() +{ + DoChange(bShow); +} + +void ScUndoShowHideTab::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). + Execute( bShow ? FID_TABLE_SHOW : FID_TABLE_HIDE, + SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); +} + +sal_Bool ScUndoShowHideTab::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +String ScUndoShowHideTab::GetComment() const +{ + sal_uInt16 nId = bShow ? STR_UNDO_SHOWTAB : STR_UNDO_HIDETAB; + return ScGlobal::GetRscString( nId ); +} + +// ============================================================================ + +ScUndoDocProtect::ScUndoDocProtect(ScDocShell* pShell, auto_ptr<ScDocProtection> pProtectSettings) : + ScSimpleUndo(pShell), + mpProtectSettings(pProtectSettings) +{ +} + +ScUndoDocProtect::~ScUndoDocProtect() +{ +} + +void ScUndoDocProtect::DoProtect(bool bProtect) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + if (bProtect) + { + // set protection. + auto_ptr<ScDocProtection> pCopy(new ScDocProtection(*mpProtectSettings)); + pCopy->setProtected(true); + pDoc->SetDocProtection(pCopy.get()); + } + else + { + // remove protection. + pDoc->SetDocProtection(NULL); + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->UpdateLayerLocks(); + pViewShell->UpdateInputHandler(sal_True); // damit sofort wieder eingegeben werden kann + } + + pDocShell->PostPaintGridAll(); +} + +void ScUndoDocProtect::Undo() +{ + BeginUndo(); + DoProtect(!mpProtectSettings->isProtected()); + EndUndo(); +} + +void ScUndoDocProtect::Redo() +{ + BeginRedo(); + DoProtect(mpProtectSettings->isProtected()); + EndRedo(); +} + +void ScUndoDocProtect::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + +sal_Bool ScUndoDocProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // gippsnich +} + +String ScUndoDocProtect::GetComment() const +{ + sal_uInt16 nId = mpProtectSettings->isProtected() ? STR_UNDO_PROTECT_DOC : STR_UNDO_UNPROTECT_DOC; + return ScGlobal::GetRscString( nId ); +} + +// ============================================================================ + +ScUndoTabProtect::ScUndoTabProtect(ScDocShell* pShell, SCTAB nTab, auto_ptr<ScTableProtection> pProtectSettings) : + ScSimpleUndo(pShell), + mnTab(nTab), + mpProtectSettings(pProtectSettings) +{ +} + +ScUndoTabProtect::~ScUndoTabProtect() +{ +} + +void ScUndoTabProtect::DoProtect(bool bProtect) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + if (bProtect) + { + // set protection. + auto_ptr<ScTableProtection> pCopy(new ScTableProtection(*mpProtectSettings)); + pCopy->setProtected(true); + pDoc->SetTabProtection(mnTab, pCopy.get()); + } + else + { + // remove protection. + pDoc->SetTabProtection(mnTab, NULL); + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->UpdateLayerLocks(); + pViewShell->UpdateInputHandler(sal_True); // damit sofort wieder eingegeben werden kann + } + + pDocShell->PostPaintGridAll(); +} + +void ScUndoTabProtect::Undo() +{ + BeginUndo(); + DoProtect(!mpProtectSettings->isProtected()); + EndUndo(); +} + +void ScUndoTabProtect::Redo() +{ + BeginRedo(); + DoProtect(mpProtectSettings->isProtected()); + EndRedo(); +} + +void ScUndoTabProtect::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + +sal_Bool ScUndoTabProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // gippsnich +} + +String ScUndoTabProtect::GetComment() const +{ + sal_uInt16 nId = mpProtectSettings->isProtected() ? STR_UNDO_PROTECT_TAB : STR_UNDO_UNPROTECT_TAB; + return ScGlobal::GetRscString( nId ); +} + +// ----------------------------------------------------------------------- +// +// Druck-/Wiederholungsbereiche aendern +// + +ScUndoPrintRange::ScUndoPrintRange( ScDocShell* pShell, SCTAB nNewTab, + ScPrintRangeSaver* pOld, ScPrintRangeSaver* pNew ) : + ScSimpleUndo( pShell ), + nTab( nNewTab ), + pOldRanges( pOld ), + pNewRanges( pNew ) +{ +} + +ScUndoPrintRange::~ScUndoPrintRange() +{ + delete pOldRanges; + delete pNewRanges; +} + +void ScUndoPrintRange::DoChange(sal_Bool bUndo) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + if (bUndo) + pDoc->RestorePrintRanges( *pOldRanges ); + else + pDoc->RestorePrintRanges( *pNewRanges ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->SetTabNo( nTab ); + + ScPrintFunc( pDocShell, pDocShell->GetPrinter(), nTab ).UpdatePages(); + + pDocShell->PostPaint( ScRange(0,0,nTab,MAXCOL,MAXROW,nTab), PAINT_GRID ); +} + +void ScUndoPrintRange::Undo() +{ + BeginUndo(); + DoChange( sal_True ); + EndUndo(); +} + +void ScUndoPrintRange::Redo() +{ + BeginRedo(); + DoChange( false ); + EndRedo(); +} + +void ScUndoPrintRange::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + +sal_Bool ScUndoPrintRange::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; // gippsnich +} + +String ScUndoPrintRange::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_PRINTRANGES ); +} + + +//------------------------------------------------------------------------ + +//--------------------------------------------------------------------------------- +// +// Szenario-Flags +// + +ScUndoScenarioFlags::ScUndoScenarioFlags( ScDocShell* pNewDocShell, SCTAB nT, + const String& rON, const String& rNN, const String& rOC, const String& rNC, + const Color& rOCol, const Color& rNCol, sal_uInt16 nOF, sal_uInt16 nNF ) : + ScSimpleUndo( pNewDocShell ), + nTab ( nT ), + aOldName ( rON ), + aNewName ( rNN ), + aOldComment ( rOC ), + aNewComment ( rNC ), + aOldColor ( rOCol ), + aNewColor ( rNCol ), + nOldFlags ( nOF ), + nNewFlags ( nNF ) +{ +} + +ScUndoScenarioFlags::~ScUndoScenarioFlags() +{ +} + +String ScUndoScenarioFlags::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_EDITSCENARIO ); +} + +void ScUndoScenarioFlags::Undo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + pDoc->RenameTab( nTab, aOldName ); + pDoc->SetScenarioData( nTab, aOldComment, aOldColor, nOldFlags ); + + pDocShell->PostPaintGridAll(); + // Der Tabellenname koennte in einer Formel vorkommen... + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->UpdateInputHandler(); + + if ( aOldName != aNewName ) + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); +} + +void ScUndoScenarioFlags::Redo() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + pDoc->RenameTab( nTab, aNewName ); + pDoc->SetScenarioData( nTab, aNewComment, aNewColor, nNewFlags ); + + pDocShell->PostPaintGridAll(); + // Der Tabellenname koennte in einer Formel vorkommen... + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->UpdateInputHandler(); + + if ( aOldName != aNewName ) + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); +} + +void ScUndoScenarioFlags::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // Repeat macht keinen Sinn +} + +sal_Bool ScUndoScenarioFlags::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + + +//--------------------------------------------------------------------------------- +// +// rename object +// (move to different file?) +// + +ScUndoRenameObject::ScUndoRenameObject( ScDocShell* pNewDocShell, const String& rPN, + const String& rON, const String& rNN ) : + ScSimpleUndo( pNewDocShell ), + aPersistName( rPN ), + aOldName ( rON ), + aNewName ( rNN ) +{ +} + +ScUndoRenameObject::~ScUndoRenameObject() +{ +} + +String ScUndoRenameObject::GetComment() const +{ + // string resource shared with title for dialog + return String( ScResId(SCSTR_RENAMEOBJECT) ); +} + +SdrObject* ScUndoRenameObject::GetObject() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + if ( pDrawLayer ) + { + sal_uInt16 nCount = pDrawLayer->GetPageCount(); + for (sal_uInt16 nTab=0; nTab<nCount; nTab++) + { + SdrPage* pPage = pDrawLayer->GetPage(nTab); + DBG_ASSERT(pPage,"Page ?"); + + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && + ((SdrOle2Obj*)pObject)->GetPersistName() == aPersistName ) + { + return pObject; + } + + pObject = aIter.Next(); + } + } + } + OSL_FAIL("Object not found"); + return NULL; +} + +void ScUndoRenameObject::Undo() +{ + BeginUndo(); + SdrObject* pObj = GetObject(); + if ( pObj ) + pObj->SetName( aOldName ); + EndUndo(); +} + +void ScUndoRenameObject::Redo() +{ + BeginRedo(); + SdrObject* pObj = GetObject(); + if ( pObj ) + pObj->SetName( aNewName ); + EndRedo(); +} + +void ScUndoRenameObject::Repeat(SfxRepeatTarget& /* rTarget */) +{ +} + +sal_Bool ScUndoRenameObject::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return false; +} + +// ----------------------------------------------------------------------- +// +// Switch sheet between left-to-right and right-to-left +// + +ScUndoLayoutRTL::ScUndoLayoutRTL( ScDocShell* pShell, SCTAB nNewTab, sal_Bool bNewRTL ) : + ScSimpleUndo( pShell ), + nTab( nNewTab ), + bRTL( bNewRTL ) +{ +} + +ScUndoLayoutRTL::~ScUndoLayoutRTL() +{ +} + +void ScUndoLayoutRTL::DoChange( sal_Bool bNew ) +{ + pDocShell->SetInUndo( sal_True ); + + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->SetLayoutRTL( nTab, bNew ); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->SetTabNo(nTab,sal_True); + + pDocShell->SetDocumentModified(); + + pDocShell->SetInUndo( false ); +} + +void ScUndoLayoutRTL::Undo() +{ + DoChange(!bRTL); +} + +void ScUndoLayoutRTL::Redo() +{ + DoChange(bRTL); +} + +void ScUndoLayoutRTL::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). + Execute( FID_TAB_RTL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); +} + +sal_Bool ScUndoLayoutRTL::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} + +String ScUndoLayoutRTL::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_TAB_RTL ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/undoutil.cxx b/sc/source/ui/undo/undoutil.cxx new file mode 100644 index 000000000000..f022e0492ce6 --- /dev/null +++ b/sc/source/ui/undo/undoutil.cxx @@ -0,0 +1,137 @@ +/* -*- 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_sc.hxx" + +// System - Includes ----------------------------------------------------- + + + +// INCLUDE --------------------------------------------------------------- + +#include "undoutil.hxx" + +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "document.hxx" +#include "dbcolect.hxx" +#include "globstr.hrc" +#include "globalnames.hxx" +#include "global.hxx" + +void ScUndoUtil::MarkSimpleBlock( ScDocShell* pDocShell, + SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, + SCCOL nEndX, SCROW nEndY, SCTAB nEndZ ) +{ + if ( pDocShell->IsPaintLocked() ) + return; + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + SCTAB nViewTab = pViewShell->GetViewData()->GetTabNo(); + if ( nViewTab < nStartZ || nViewTab > nEndZ ) + pViewShell->SetTabNo( nStartZ ); + + pViewShell->DoneBlockMode(); + pViewShell->MoveCursorAbs( nStartX, nStartY, SC_FOLLOW_JUMP, false, false ); + pViewShell->InitOwnBlockMode(); + pViewShell->GetViewData()->GetMarkData(). + SetMarkArea( ScRange( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ) ); + pViewShell->MarkDataChanged(); + } +} + + +void ScUndoUtil::MarkSimpleBlock( ScDocShell* pDocShell, + const ScAddress& rBlockStart, + const ScAddress& rBlockEnd ) +{ + MarkSimpleBlock( pDocShell, rBlockStart.Col(), rBlockStart.Row(), rBlockStart.Tab(), + rBlockEnd.Col(), rBlockEnd.Row(), rBlockEnd.Tab() ); +} + + +void ScUndoUtil::MarkSimpleBlock( ScDocShell* pDocShell, + const ScRange& rRange ) +{ + MarkSimpleBlock( pDocShell, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(), + rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab() ); +} + + + +ScDBData* ScUndoUtil::GetOldDBData( ScDBData* pUndoData, ScDocument* pDoc, SCTAB nTab, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +{ + ScDBData* pRet = pDoc->GetDBAtArea( nTab, nCol1, nRow1, nCol2, nRow2 ); + + if (!pRet) + { + sal_Bool bWasTemp = false; + if ( pUndoData ) + { + String aName; + pUndoData->GetName( aName ); + if ( rtl::OUString(aName) == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME) ) ) + bWasTemp = sal_True; + } + DBG_ASSERT(bWasTemp, "Undo: didn't find database range"); + (void)bWasTemp; + pRet = pDoc->GetAnonymousDBData(nTab); + if (!pRet) + { + pRet = new ScDBData( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)), nTab, + nCol1,nRow1, nCol2,nRow2, sal_True, + pDoc->HasColHeader( nCol1,nRow1,nCol2,nRow2,nTab ) ); + pDoc->SetAnonymousDBData(nTab,pRet); + } + } + + return pRet; +} + + +void ScUndoUtil::PaintMore( ScDocShell* pDocShell, + const ScRange& rRange ) +{ + SCCOL nCol1 = rRange.aStart.Col(); + SCROW nRow1 = rRange.aStart.Row(); + SCCOL nCol2 = rRange.aEnd.Col(); + SCROW nRow2 = rRange.aEnd.Row(); + if (nCol1 > 0) --nCol1; + if (nRow1 > 0) --nRow1; + if (nCol2<MAXCOL) ++nCol2; + if (nRow2<MAXROW) ++nRow2; + + pDocShell->PostPaint( nCol1,nRow1,rRange.aStart.Tab(), + nCol2,nRow2,rRange.aEnd.Tab(), PAINT_GRID ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |