summaryrefslogtreecommitdiff
path: root/sc/source/ui/docshell/docfunc.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/docshell/docfunc.cxx')
-rw-r--r--sc/source/ui/docshell/docfunc.cxx4948
1 files changed, 4948 insertions, 0 deletions
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
new file mode 100644
index 000000000000..2f04f83934a9
--- /dev/null
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -0,0 +1,4948 @@
+/* -*- 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 <editeng/eeitem.hxx>
+
+#include <sfx2/app.hxx>
+#include <editeng/editobj.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <svx/svdundo.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/printer.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/sound.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/waitobj.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/PasswordHelper.hxx>
+
+#include <basic/sbstar.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/script/ModuleType.hpp>
+#include <com/sun/star/script/XLibraryContainer.hpp>
+#include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
+
+#include <list>
+
+#include "docfunc.hxx"
+
+#include "sc.hrc"
+
+#include "arealink.hxx"
+#include "attrib.hxx"
+#include "dociter.hxx"
+#include "autoform.hxx"
+#include "cell.hxx"
+#include "cellmergeoption.hxx"
+#include "detdata.hxx"
+#include "detfunc.hxx"
+#include "docpool.hxx"
+#include "docsh.hxx"
+#include "drwlayer.hxx"
+#include "editutil.hxx"
+#include "globstr.hrc"
+#include "olinetab.hxx"
+#include "patattr.hxx"
+#include "rangenam.hxx"
+#include "rangeutl.hxx"
+#include "refundo.hxx"
+#include "scresid.hxx"
+#include "stlpool.hxx"
+#include "stlsheet.hxx"
+#include "tablink.hxx"
+#include "tabvwsh.hxx"
+#include "uiitems.hxx"
+#include "undoblk.hxx"
+#include "undocell.hxx"
+#include "undodraw.hxx"
+#include "undotab.hxx"
+#include "waitoff.hxx"
+#include "sizedev.hxx"
+#include "scmod.hxx"
+#include "inputhdl.hxx"
+#include "inputwin.hxx"
+#include "editable.hxx"
+#include "compiler.hxx"
+#include "scui_def.hxx"
+#include "tabprotection.hxx"
+#include "clipparam.hxx"
+#include "externalrefmgr.hxx"
+#include "undorangename.hxx"
+
+#include <memory>
+#include <basic/basmgr.hxx>
+#include <boost/scoped_ptr.hpp>
+#include <set>
+#include <vector>
+
+using namespace com::sun::star;
+using ::com::sun::star::uno::Sequence;
+using ::std::vector;
+
+
+// STATIC DATA -----------------------------------------------------------
+
+//========================================================================
+
+IMPL_LINK( ScDocFunc, NotifyDrawUndo, SdrUndoAction*, pUndoAction )
+{
+ // #i101118# if drawing layer collects the undo actions, add it there
+ ScDrawLayer* pDrawLayer = rDocShell.GetDocument()->GetDrawLayer();
+ if( pDrawLayer && pDrawLayer->IsRecording() )
+ pDrawLayer->AddCalcUndo( pUndoAction );
+ else
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDraw( pUndoAction, &rDocShell ) );
+ rDocShell.SetDrawModified();
+
+ // the affected sheet isn't known, so all stream positions are invalidated
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, false);
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+
+// Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight)
+
+void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange )
+{
+ SCROW nRow = rRange.aStart.Row();
+ if ( nRow > 0 )
+ {
+ SCTAB nTab = rRange.aStart.Tab(); //! alle?
+ --nRow;
+ rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID );
+ }
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, sal_Bool bPaint )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if ( pDoc->IsImportingXML() )
+ {
+ // for XML import, all row heights are updated together after importing
+ return false;
+ }
+ if ( !pDoc->IsAdjustHeightEnabled() )
+ {
+ return false;
+ }
+
+ SCTAB nTab = rRange.aStart.Tab();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCROW nEndRow = rRange.aEnd.Row();
+
+ ScSizeDeviceProvider aProv( &rDocShell );
+ Fraction aOne(1,1);
+
+ sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(),
+ aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, false );
+
+ if ( bPaint && bChanged )
+ rDocShell.PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
+ PAINT_GRID | PAINT_LEFT );
+
+ return bChanged;
+}
+
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::DetectiveAddPred(const ScAddress& rPos)
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ rDocShell.MakeDrawLayer();
+ ScDocument* pDoc = rDocShell.GetDocument();
+ sal_Bool bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+sal_Bool ScDocFunc::DetectiveDelPred(const ScAddress& rPos)
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ sal_Bool bUndo(pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return false;
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+sal_Bool ScDocFunc::DetectiveAddSucc(const ScAddress& rPos)
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ rDocShell.MakeDrawLayer();
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ sal_Bool bUndo(pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowSucc( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+sal_Bool ScDocFunc::DetectiveDelSucc(const ScAddress& rPos)
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ sal_Bool bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return false;
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+sal_Bool ScDocFunc::DetectiveAddError(const ScAddress& rPos)
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ rDocShell.MakeDrawLayer();
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ sal_Bool bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+sal_Bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab)
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ rDocShell.MakeDrawLayer();
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ sal_Bool bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+
+ Window* pWaitWin = rDocShell.GetActiveDialogParent();
+ if (pWaitWin)
+ pWaitWin->EnterWait();
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ sal_Bool bOverflow;
+ sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (pWaitWin)
+ pWaitWin->LeaveWait();
+ if (bDone)
+ {
+ if (pUndo && bUndo)
+ {
+ pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID ) );
+ rDocShell.GetUndoManager()->AddUndoAction( pUndo );
+ }
+ aModificator.SetDocumentModified();
+ if ( bOverflow )
+ {
+ InfoBox( NULL,
+ ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute();
+ }
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+sal_Bool ScDocFunc::DetectiveDelAll(SCTAB nTab)
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ sal_Bool bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return false;
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpList* pOldList = pDoc->GetDetOpList();
+ ScDetOpList* pUndoList = NULL;
+ if (bUndo)
+ pUndoList = pOldList ? new ScDetOpList(*pOldList) : NULL;
+
+ pDoc->ClearDetectiveOperations();
+
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, NULL, pUndoList ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+sal_Bool ScDocFunc::DetectiveRefresh( sal_Bool bAutomatic )
+{
+ sal_Bool bDone = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ sal_Bool bUndo (pDoc->IsUndoEnabled());
+ ScDetOpList* pList = pDoc->GetDetOpList();
+ if ( pList && pList->Count() )
+ {
+ rDocShell.MakeDrawLayer();
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (bUndo)
+ pModel->BeginCalcUndo();
+
+ // Loeschen auf allen Tabellen
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS ); // don't remove circles
+
+ // Wiederholen
+
+ sal_uInt16 nCount = pList->Count();
+ for (sal_uInt16 i=0; i<nCount; i++)
+ {
+ ScDetOpData* pData = (*pList)[i];
+ if (pData)
+ {
+ ScAddress aPos = pData->GetPos();
+ ScDetectiveFunc aFunc( pDoc, aPos.Tab() );
+ SCCOL nCol = aPos.Col();
+ SCROW nRow = aPos.Row();
+ switch (pData->GetOperation())
+ {
+ case SCDETOP_ADDSUCC:
+ aFunc.ShowSucc( nCol, nRow );
+ break;
+ case SCDETOP_DELSUCC:
+ aFunc.DeleteSucc( nCol, nRow );
+ break;
+ case SCDETOP_ADDPRED:
+ aFunc.ShowPred( nCol, nRow );
+ break;
+ case SCDETOP_DELPRED:
+ aFunc.DeletePred( nCol, nRow );
+ break;
+ case SCDETOP_ADDERROR:
+ aFunc.ShowError( nCol, nRow );
+ break;
+ default:
+ OSL_FAIL("falsche Op bei DetectiveRefresh");
+ }
+ }
+ }
+
+ if (bUndo)
+ {
+ SdrUndoGroup* pUndo = pModel->GetCalcUndo();
+ if (pUndo)
+ {
+ pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH ) );
+ // wenn automatisch, an letzte Aktion anhaengen
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDraw( pUndo, &rDocShell ),
+ bAutomatic );
+ }
+ }
+ rDocShell.SetDrawModified();
+ bDone = sal_True;
+ }
+ return bDone;
+}
+
+static void lcl_collectAllPredOrSuccRanges(
+ const ScRangeList& rSrcRanges, vector<ScTokenRef>& rRefTokens, ScDocShell& rDocShell,
+ bool bPred)
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ vector<ScTokenRef> aRefTokens;
+ ScRangeList aSrcRanges(rSrcRanges);
+ if (aSrcRanges.empty())
+ return;
+ ScRange* p = aSrcRanges.front();
+ ScDetectiveFunc aDetFunc(pDoc, p->aStart.Tab());
+ ScRangeList aDestRanges;
+ for (size_t i = 0, n = aSrcRanges.size(); i < n; ++i)
+ {
+ p = aSrcRanges[i];
+ if (bPred)
+ {
+ aDetFunc.GetAllPreds(
+ p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), aRefTokens);
+ }
+ else
+ {
+ aDetFunc.GetAllSuccs(
+ p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), aRefTokens);
+ }
+ }
+ rRefTokens.swap(aRefTokens);
+}
+
+void ScDocFunc::DetectiveCollectAllPreds(const ScRangeList& rSrcRanges, vector<ScTokenRef>& rRefTokens)
+{
+ lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, true);
+}
+
+void ScDocFunc::DetectiveCollectAllSuccs(const ScRangeList& rSrcRanges, vector<ScTokenRef>& rRefTokens)
+{
+ lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, false);
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::DeleteContents( const ScMarkData& rMark, sal_uInt16 nFlags,
+ sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
+ {
+ OSL_FAIL("ScDocFunc::DeleteContents ohne Markierung");
+ return false;
+ }
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ ScEditableTester aTester( pDoc, rMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ ScRange aMarkRange;
+ sal_Bool bSimple = false;
+
+ ScMarkData aMultiMark = rMark;
+ aMultiMark.SetMarking(false); // fuer MarkToMulti
+
+ ScDocument* pUndoDoc = NULL;
+ sal_Bool bMulti = !bSimple && aMultiMark.IsMultiMarked();
+ if (!bSimple)
+ {
+ aMultiMark.MarkToMulti();
+ aMultiMark.GetMultiMarkArea( aMarkRange );
+ }
+ ScRange aExtendedRange(aMarkRange);
+ if (!bSimple)
+ {
+ if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) )
+ bMulti = false;
+ }
+
+ // keine Objekte auf geschuetzten Tabellen
+ sal_Bool bObjects = false;
+ if ( nFlags & IDF_OBJECTS )
+ {
+ bObjects = sal_True;
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (aMultiMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab))
+ bObjects = false;
+ }
+
+ sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted
+ if ( nFlags & IDF_ATTRIB )
+ rDocShell.UpdatePaintExt( nExtFlags, aMarkRange );
+
+ // Reihenfolge:
+ // 1) BeginDrawUndo
+ // 2) Objekte loeschen (DrawUndo wird gefuellt)
+ // 3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen
+ // 4) Inhalte loeschen
+
+ bool bDrawUndo = bObjects || (nFlags & IDF_NOTE);
+ if (bRecord && bDrawUndo)
+ pDoc->BeginDrawUndo();
+
+ if (bObjects)
+ {
+ if (bMulti)
+ pDoc->DeleteObjectsInSelection( aMultiMark );
+ else
+ pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
+ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
+ aMultiMark );
+ }
+
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, aMarkRange.aStart.Tab(), aMarkRange.aEnd.Tab() );
+
+ // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
+ // nur mit IDF_HARDATTR zu langsam ist:
+ sal_uInt16 nUndoDocFlags = nFlags;
+ if (nFlags & IDF_ATTRIB)
+ nUndoDocFlags |= IDF_ATTRIB;
+ if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute
+ nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert
+ if (nFlags & IDF_NOTE)
+ nUndoDocFlags |= IDF_CONTENTS; // copy all cells with their notes
+ // note captions are handled in drawing undo
+ nUndoDocFlags |= IDF_NOCAPTIONS;
+ pDoc->CopyToDocument( aExtendedRange, nUndoDocFlags, bMulti, pUndoDoc, &aMultiMark );
+ }
+
+//! HideAllCursors(); // falls Zusammenfassung aufgehoben wird
+ if (bSimple)
+ pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
+ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
+ aMultiMark, nFlags );
+ else
+ {
+ pDoc->DeleteSelection( nFlags, aMultiMark );
+ }
+
+ // add undo action after drawing undo is complete (objects and note captions)
+ if( bRecord )
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDeleteContents( &rDocShell, aMultiMark, aExtendedRange,
+ pUndoDoc, bMulti, nFlags, bDrawUndo ) );
+
+ if (!AdjustRowHeight( aExtendedRange ))
+ rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
+ else if (nExtFlags & SC_PF_LINES)
+ lcl_PaintAbove( rDocShell, aExtendedRange ); // fuer Linien ueber dem Bereich
+
+ aModificator.SetDocumentModified();
+
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::TransliterateText( const ScMarkData& rMark, sal_Int32 nType,
+ sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ ScEditableTester aTester( pDoc, rMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ ScRange aMarkRange;
+ ScMarkData aMultiMark = rMark;
+ aMultiMark.SetMarking(false); // for MarkToMulti
+ aMultiMark.MarkToMulti();
+ aMultiMark.GetMultiMarkArea( aMarkRange );
+
+ if (bRecord)
+ {
+ SCTAB nStartTab = aMarkRange.aStart.Tab();
+ SCTAB nTabCount = pDoc->GetTableCount();
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && rMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aMarkRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, sal_True, pUndoDoc, &aMultiMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTransliterate( &rDocShell, aMultiMark, pUndoDoc, nType ) );
+ }
+
+ pDoc->TransliterateText( aMultiMark, nType );
+
+ if (!AdjustRowHeight( aMarkRange ))
+ rDocShell.PostPaint( aMarkRange, PAINT_GRID );
+
+ aModificator.SetDocumentModified();
+
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::SetNormalString( const ScAddress& rPos, const String& rText, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ sal_Bool bUndo(pDoc->IsUndoEnabled());
+ ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ SCTAB* pTabs = NULL;
+ ScBaseCell** ppOldCells = NULL;
+ sal_Bool* pHasFormat = NULL;
+ sal_uLong* pOldFormats = NULL;
+ ScBaseCell* pDocCell = pDoc->GetCell( rPos );
+ sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
+ if (bUndo)
+ {
+ pTabs = new SCTAB[1];
+ pTabs[0] = rPos.Tab();
+ ppOldCells = new ScBaseCell*[1];
+ ppOldCells[0] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0;
+
+ pHasFormat = new sal_Bool[1];
+ pOldFormats = new sal_uLong[1];
+ const SfxPoolItem* pItem;
+ const ScPatternAttr* pPattern = pDoc->GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() );
+ if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
+ ATTR_VALUE_FORMAT,false,&pItem) )
+ {
+ pHasFormat[0] = sal_True;
+ pOldFormats[0] = ((const SfxUInt32Item*)pItem)->GetValue();
+ }
+ else
+ pHasFormat[0] = false;
+ }
+
+ pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText );
+
+ if (bUndo)
+ {
+ // wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden
+ rDocShell.GetUndoManager()->AddUndoAction(new ScUndoEnterData( &rDocShell, rPos.Col(),rPos.Row(),rPos.Tab(), 1,pTabs,
+ ppOldCells, pHasFormat, pOldFormats, rText, NULL ) );
+ }
+
+ if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) )
+ AdjustRowHeight( ScRange(rPos) );
+
+ rDocShell.PostPaintCell( rPos );
+ aModificator.SetDocumentModified();
+
+ // notify input handler here the same way as in PutCell
+ if (bApi)
+ NotifyInputHandler( rPos );
+
+ return sal_True;
+}
+
+sal_Bool ScDocFunc::PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+ ScDocument* pDoc = rDocShell.GetDocument();
+ sal_Bool bUndo (pDoc->IsUndoEnabled());
+ sal_Bool bXMLLoading(pDoc->IsImportingXML());
+
+ // #i925#; it is not neccessary to test whether the cell is editable on loading a XML document
+ if (!bXMLLoading)
+ {
+ ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ pNewCell->Delete();
+ return false;
+ }
+ }
+
+ sal_Bool bEditCell = ( pNewCell->GetCellType() == CELLTYPE_EDIT );
+ ScBaseCell* pDocCell = pDoc->GetCell( rPos );
+ sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
+ sal_Bool bHeight = ( bEditDeleted || bEditCell ||
+ pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) );
+
+ ScBaseCell* pUndoCell = (bUndo && pDocCell) ? pDocCell->CloneWithoutNote( *pDoc, rPos ) : 0;
+ ScBaseCell* pRedoCell = (bUndo && pNewCell) ? pNewCell->CloneWithoutNote( *pDoc, rPos ) : 0;
+
+ pDoc->PutCell( rPos, pNewCell );
+
+ // wegen ChangeTracking darf UndoAction erst nach PutCell angelegt werden
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoPutCell( &rDocShell, rPos, pUndoCell, pRedoCell, bHeight ) );
+ }
+
+ if (bHeight)
+ AdjustRowHeight( ScRange(rPos) );
+
+ if (!bXMLLoading)
+ rDocShell.PostPaintCell( rPos );
+
+ aModificator.SetDocumentModified();
+
+ // #i925#; it is not neccessary to notify on loading a XML document
+ // #103934#; notify editline and cell in edit mode
+ if (bApi && !bXMLLoading)
+ NotifyInputHandler( rPos );
+
+ return sal_True;
+}
+
+void ScDocFunc::NotifyInputHandler( const ScAddress& rPos )
+{
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh && pViewSh->GetViewData()->GetDocShell() == &rDocShell )
+ {
+ ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
+ if ( pInputHdl && pInputHdl->GetCursorPos() == rPos )
+ {
+ sal_Bool bIsEditMode(pInputHdl->IsEditMode());
+
+ // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
+ // (the cell shows the same like the InputWindow)
+ if (bIsEditMode)
+ pInputHdl->SetModified();
+ pViewSh->UpdateInputHandler(false, !bIsEditMode);
+ }
+ }
+}
+
+ struct ScMyRememberItem
+ {
+ sal_uInt16 nIndex;
+ SfxItemSet aItemSet;
+
+ ScMyRememberItem(const SfxItemSet& rItemSet, sal_uInt16 nTempIndex) :
+ nIndex(nTempIndex), aItemSet(rItemSet) {}
+ };
+
+ typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList;
+
+sal_Bool ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, sal_Bool bInterpret, sal_Bool bApi )
+{
+ // PutData ruft PutCell oder SetNormalString
+
+ sal_Bool bRet = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScEditAttrTester aTester( &rEngine );
+ sal_Bool bEditCell = aTester.NeedsObject();
+ if ( bEditCell )
+ {
+ // #i61702# With bLoseContent set, the content of rEngine isn't restored
+ // (used in loading XML, where after the removeActionLock call the API obejct's
+ // EditEngine isn't accessed again.
+ sal_Bool bLoseContent = pDoc->IsImportingXML();
+
+ sal_Bool bUpdateMode(rEngine.GetUpdateMode());
+ if (bUpdateMode)
+ rEngine.SetUpdateMode(false);
+
+ ScMyRememberItemList aRememberItems;
+ ScMyRememberItem* pRememberItem = NULL;
+
+ // All paragraph attributes must be removed before calling CreateTextObject,
+ // not only alignment, so the object doesn't contain the cell attributes as
+ // paragraph attributes. Before remove the attributes store they in a list to
+ // set they back to the EditEngine.
+ sal_uInt16 nCount = rEngine.GetParagraphCount();
+ for (sal_uInt16 i=0; i<nCount; i++)
+ {
+ const SfxItemSet& rOld = rEngine.GetParaAttribs( i );
+ if ( rOld.Count() )
+ {
+ if ( !bLoseContent )
+ {
+ pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i);
+ aRememberItems.push_back(pRememberItem);
+ }
+ rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) );
+ }
+ }
+
+ EditTextObject* pNewData = rEngine.CreateTextObject();
+ bRet = PutCell( rPos,
+ new ScEditCell( pNewData, pDoc, rEngine.GetEditTextObjectPool() ),
+ bApi );
+ delete pNewData;
+
+ // Set the paragraph attributes back to the EditEngine.
+ if (!aRememberItems.empty())
+ {
+// ScMyRememberItem* pRememberItem = NULL;
+ ScMyRememberItemList::iterator aItr = aRememberItems.begin();
+ while (aItr != aRememberItems.end())
+ {
+ pRememberItem = *aItr;
+ rEngine.SetParaAttribs(pRememberItem->nIndex, pRememberItem->aItemSet);
+ delete pRememberItem;
+ aItr = aRememberItems.erase(aItr);
+ }
+ }
+
+ // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
+ if ( bUpdateMode && !bLoseContent )
+ rEngine.SetUpdateMode(sal_True);
+ }
+ else
+ {
+ String aText = rEngine.GetText();
+ if ( bInterpret || !aText.Len() )
+ bRet = SetNormalString( rPos, aText, bApi );
+ else
+ bRet = PutCell( rPos, new ScStringCell( aText ), bApi );
+ }
+
+ if ( bRet && aTester.NeedsCellAttr() )
+ {
+ const SfxItemSet& rEditAttr = aTester.GetAttribs();
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetFromEditItemSet( &rEditAttr );
+ aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) );
+ aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY ); // wasn't removed above if no edit object
+ if ( aPattern.GetItemSet().Count() > 0 )
+ {
+ ScMarkData aMark;
+ aMark.SelectTable( rPos.Tab(), sal_True );
+ aMark.SetMarkArea( ScRange( rPos ) );
+ ApplyAttributes( aMark, aPattern, sal_True, bApi );
+ }
+ }
+
+ return bRet;
+}
+
+
+ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
+{
+ ScTokenArray* pCode = new ScTokenArray;
+ pCode->AddString( rText );
+ if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (rFormulaNmsp.Len() > 0) )
+ pCode->AddString( rFormulaNmsp );
+ return pCode;
+}
+
+
+ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos,
+ const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar, short* pRetFormatType )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScBaseCell* pNewCell = NULL;
+
+ if ( rText.Len() > 1 && rText.GetChar(0) == '=' )
+ {
+ ScTokenArray* pCode;
+ if ( pDoc->IsImportingXML() )
+ { // temporary formula string as string tokens
+ pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText, rFormulaNmsp, eGrammar );
+ pDoc->IncXMLImportedFormulaCount( rText.Len() );
+ }
+ else
+ {
+ ScCompiler aComp( pDoc, rPos );
+ aComp.SetGrammar(eGrammar);
+ pCode = aComp.CompileString( rText );
+ }
+ pNewCell = new ScFormulaCell( pDoc, rPos, pCode, eGrammar, MM_NONE );
+ delete pCode; // Zell-ctor hat das TokenArray kopiert
+ }
+ else if ( rText.Len() > 1 && rText.GetChar(0) == '\'' )
+ {
+ // for bEnglish, "'" at the beginning is always interpreted as text
+ // marker and stripped
+ pNewCell = ScBaseCell::CreateTextCell( rText.Copy( 1 ), pDoc );
+ }
+ else // (nur) auf englisches Zahlformat testen
+ {
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+ sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
+ double fVal;
+ if ( pFormatter->IsNumberFormat( rText, nEnglish, fVal ) )
+ {
+ pNewCell = new ScValueCell( fVal );
+ // return the format type from the English format, so a localized format can be created
+ if ( pRetFormatType )
+ *pRetFormatType = pFormatter->GetType( nEnglish );
+ }
+ else if ( rText.Len() )
+ pNewCell = ScBaseCell::CreateTextCell( rText, pDoc );
+
+ // das (englische) Zahlformat wird nicht gesetzt
+ //! passendes lokales Format suchen und setzen???
+ }
+
+ return pNewCell;
+}
+
+
+sal_Bool ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText,
+ sal_Bool bInterpret, sal_Bool bEnglish, sal_Bool bApi,
+ const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
+{
+ // SetCellText ruft PutCell oder SetNormalString
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScBaseCell* pNewCell = NULL;
+ if ( bInterpret )
+ {
+ if ( bEnglish )
+ {
+ ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard;
+ if (bApi)
+ pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc));
+
+ // code moved to own method InterpretEnglishString because it is also used in
+ // ScCellRangeObj::setFormulaArray
+
+ pNewCell = InterpretEnglishString( rPos, rText, rFormulaNmsp, eGrammar );
+ }
+ // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
+ }
+ else if ( rText.Len() )
+ {
+ OSL_ENSURE( rFormulaNmsp.Len() == 0, "ScDocFunc::SetCellText - formula namespace, but do not interpret?" );
+ pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); // immer Text
+ }
+
+ if (pNewCell)
+ return PutCell( rPos, pNewCell, bApi );
+ else
+ return SetNormalString( rPos, rText, bApi );
+}
+
+//------------------------------------------------------------------------
+
+bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow )
+{
+ ScDocument& rDoc = *rDocShell.GetDocument();
+ ScPostIt* pNote = rDoc.GetNote( rPos );
+ if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false;
+
+ // move the caption to internal or hidden layer and create undo action
+ pNote->ShowCaption( rPos, bShow );
+ if( rDoc.IsUndoEnabled() )
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) );
+
+ if (rDoc.IsStreamValid(rPos.Tab()))
+ rDoc.SetStreamValid(rPos.Tab(), false);
+
+ rDocShell.SetDocumentModified();
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+
+bool ScDocFunc::SetNoteText( const ScAddress& rPos, const String& rText, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ String aNewText = rText;
+ aNewText.ConvertLineEnd(); //! ist das noetig ???
+
+ if( ScPostIt* pNote = (aNewText.Len() > 0) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote( rPos ) )
+ pNote->SetText( rPos, aNewText );
+
+ //! Undo !!!
+
+ if (pDoc->IsStreamValid(rPos.Tab()))
+ pDoc->SetStreamValid(rPos.Tab(), false);
+
+ rDocShell.PostPaintCell( rPos );
+ aModificator.SetDocumentModified();
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+
+bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate, sal_Bool bApi )
+{
+ bool bDone = false;
+
+ ScDocShellModificator aModificator( rDocShell );
+ ScDocument& rDoc = *rDocShell.GetDocument();
+ ScEditableTester aTester( &rDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
+ if (aTester.IsEditable())
+ {
+ ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+ ::svl::IUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0;
+
+ ScNoteData aOldData;
+ ScPostIt* pOldNote = rDoc.ReleaseNote( rPos );
+ if( pOldNote )
+ {
+ // ensure existing caption object before draw undo tracking starts
+ pOldNote->GetOrCreateCaption( rPos );
+ // rescue note data for undo
+ aOldData = pOldNote->GetNoteData();
+ }
+
+ // collect drawing undo actions for deleting/inserting caption obejcts
+ if( pUndoMgr )
+ pDrawLayer->BeginCalcUndo();
+
+ // delete the note (creates drawing undo action for the caption object)
+ delete pOldNote;
+
+ // create new note (creates drawing undo action for the new caption object)
+ ScNoteData aNewData;
+ if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) )
+ {
+ if( pAuthor ) pNewNote->SetAuthor( *pAuthor );
+ if( pDate ) pNewNote->SetDate( *pDate );
+ // rescue note data for undo
+ aNewData = pNewNote->GetNoteData();
+ }
+
+ // create the undo action
+ if( pUndoMgr && (aOldData.mpCaption || aNewData.mpCaption) )
+ pUndoMgr->AddUndoAction( new ScUndoReplaceNote( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) );
+
+ // repaint cell (to make note marker visible)
+ rDocShell.PostPaintCell( rPos );
+
+ if (rDoc.IsStreamValid(rPos.Tab()))
+ rDoc.SetStreamValid(rPos.Tab(), false);
+
+ aModificator.SetDocumentModified();
+ bDone = true;
+ }
+ else if (!bApi)
+ {
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ }
+
+ return bDone;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
+ sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if ( bRecord && !pDoc->IsUndoEnabled() )
+ bRecord = false;
+
+ sal_Bool bImportingXML = pDoc->IsImportingXML();
+ // Cell formats can still be set if the range isn't editable only because of matrix formulas.
+ // #i62483# When loading XML, the check can be skipped altogether.
+ sal_Bool bOnlyNotBecauseOfMatrix;
+ if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
+ && !bOnlyNotBecauseOfMatrix )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR);
+ return false;
+ }
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ //! Umrandung
+
+ ScRange aMultiRange;
+ sal_Bool bMulti = rMark.IsMultiMarked();
+ if ( bMulti )
+ rMark.GetMultiMarkArea( aMultiRange );
+ else
+ rMark.GetMarkArea( aMultiRange );
+
+ if ( bRecord )
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() );
+ pDoc->CopyToDocument( aMultiRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoSelectionAttr(
+ &rDocShell, rMark,
+ aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(),
+ aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(),
+ pUndoDoc, bMulti, &rPattern ) );
+ }
+
+ // While loading XML it is not neccessary to ask HasAttrib. It needs too much time.
+ sal_uInt16 nExtFlags = 0;
+ if ( !bImportingXML )
+ rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content before the change
+ pDoc->ApplySelectionPattern( rPattern, rMark );
+ if ( !bImportingXML )
+ rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content after the change
+
+ if (!AdjustRowHeight( aMultiRange ))
+ rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
+ else if (nExtFlags & SC_PF_LINES)
+ lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
+
+ aModificator.SetDocumentModified();
+
+ return sal_True;
+}
+
+
+sal_Bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleName,
+ sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if ( bRecord && !pDoc->IsUndoEnabled() )
+ bRecord = false;
+
+ sal_Bool bImportingXML = pDoc->IsImportingXML();
+ // Cell formats can still be set if the range isn't editable only because of matrix formulas.
+ // #i62483# When loading XML, the check can be skipped altogether.
+ sal_Bool bOnlyNotBecauseOfMatrix;
+ if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
+ && !bOnlyNotBecauseOfMatrix )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR);
+ return false;
+ }
+
+ ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find(
+ rStyleName, SFX_STYLE_FAMILY_PARA );
+ if (!pStyleSheet)
+ return false;
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScRange aMultiRange;
+ sal_Bool bMulti = rMark.IsMultiMarked();
+ if ( bMulti )
+ rMark.GetMultiMarkArea( aMultiRange );
+ else
+ rMark.GetMarkArea( aMultiRange );
+
+ if ( bRecord )
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ SCTAB nStartTab = aMultiRange.aStart.Tab();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && rMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aMultiRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoSelectionStyle(
+ &rDocShell, rMark, aMultiRange, rStyleName, pUndoDoc ) );
+
+ }
+
+ pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark );
+
+ sal_uInt16 nExtFlags = 0;
+ if (!AdjustRowHeight( aMultiRange ))
+ rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
+ else if (nExtFlags & SC_PF_LINES)
+ lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
+
+ aModificator.SetDocumentModified();
+
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd,
+ sal_Bool bRecord, sal_Bool bApi, sal_Bool bPartOfPaste )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
+ {
+ OSL_FAIL("invalid row in InsertCells");
+ return false;
+ }
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCCOL nPaintStartX = nStartCol;
+ SCROW nPaintStartY = nStartRow;
+ SCCOL nPaintEndX = nEndCol;
+ SCROW nPaintEndY = nEndRow;
+ sal_uInt16 nPaintFlags = PAINT_GRID;
+ sal_Bool bSuccess;
+ SCTAB i;
+
+ ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); //preserve current cursor position
+ SCCOL nCursorCol = 0;
+ SCROW nCursorRow = 0;
+ if( pViewSh )
+ {
+ nCursorCol = pViewSh->GetViewData()->GetCurX();
+ nCursorRow = pViewSh->GetViewData()->GetCurY();
+ }
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ SCTAB nCount = 0;
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( !pDoc->IsScenario(i) )
+ {
+ nCount++;
+ if( nCount == nEndTab+1 )
+ {
+ aMark.SelectTable( i, sal_True );
+ break;
+ }
+ }
+ }
+ }
+
+ ScMarkData aFullMark( aMark ); // including scenario sheets
+ for( i=0; i<nTabCount; i++ )
+ if( aMark.GetTableSelect( i ) )
+ {
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ aFullMark.SelectTable( j, sal_True );
+ }
+
+ SCTAB nSelCount = aMark.GetSelectCount();
+
+ // zugehoerige Szenarien auch anpassen
+ // Test zusammengefasste
+
+ SCCOL nMergeTestStartX = nStartCol;
+ SCROW nMergeTestStartY = nStartRow;
+ SCCOL nMergeTestEndX = nEndCol;
+ SCROW nMergeTestEndY = nEndRow;
+
+ ScRange aExtendMergeRange( rRange );
+
+ if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
+ {
+ pDoc->ExtendMerge( aExtendMergeRange );
+ pDoc->ExtendOverlapped( aExtendMergeRange );
+ nMergeTestEndX = aExtendMergeRange.aEnd.Col();
+ nMergeTestEndY = aExtendMergeRange.aEnd.Row();
+ nPaintEndX = nMergeTestEndX;
+ nPaintEndY = nMergeTestEndY;
+ }
+
+ if ( eCmd == INS_INSROWS )
+ {
+ nMergeTestStartX = 0;
+ nMergeTestEndX = MAXCOL;
+ }
+ if ( eCmd == INS_INSCOLS )
+ {
+ nMergeTestStartY = 0;
+ nMergeTestEndY = MAXROW;
+ }
+ if ( eCmd == INS_CELLSDOWN )
+ nMergeTestEndY = MAXROW;
+ if ( eCmd == INS_CELLSRIGHT )
+ nMergeTestEndX = MAXCOL;
+
+ sal_Bool bNeedRefresh = false;
+
+ SCCOL nEditTestEndX = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndX;
+ SCROW nEditTestEndY = (eCmd==INS_INSROWS) ? MAXROW : nMergeTestEndY;
+ ScEditableTester aTester( pDoc, nMergeTestStartX, nMergeTestStartY, nEditTestEndX, nEditTestEndY, aMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
+
+ ScDocument* pRefUndoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ if ( bRecord )
+ {
+ pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
+
+ // pRefUndoDoc is filled in InsertCol / InsertRow
+
+ pUndoData = new ScRefUndoData( pDoc );
+
+ pDoc->BeginDrawUndo();
+ }
+
+ // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction
+ // the patch comes from mloiseleur and maoyg
+ sal_Bool bInsertMerge = false;
+ std::vector<ScRange> qIncreaseRange;
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS );
+ if (bRecord)
+ rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect(i) )
+ {
+ if( pDoc->HasAttrib( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
+ {
+ if (eCmd==INS_CELLSRIGHT)
+ bNeedRefresh = sal_True;
+
+ SCCOL nMergeStartX = nMergeTestStartX;
+ SCROW nMergeStartY = nMergeTestStartY;
+ SCCOL nMergeEndX = nMergeTestEndX;
+ SCROW nMergeEndY = nMergeTestEndY;
+
+ pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
+ pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
+
+ if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX )) ||
+ (eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY )) )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
+ rDocShell.GetUndoManager()->LeaveListAction();
+ return false;
+ }
+
+ SCCOL nTestCol = -1;
+ SCROW nTestRow1 = -1;
+ SCROW nTestRow2 = -1;
+
+ ScDocAttrIterator aTestIter( pDoc, i, nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY );
+ ScRange aExtendRange( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i );
+ const ScPatternAttr* pPattern = NULL;
+ const ScMergeAttr* pMergeFlag = NULL;
+ const ScMergeFlagAttr* pMergeFlagAttr = NULL;
+ while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
+ {
+ pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
+ pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
+ sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
+ if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
+ {
+ ScRange aRange( nTestCol, nTestRow1, i );
+ pDoc->ExtendOverlapped(aRange);
+ pDoc->ExtendMerge(aRange, sal_True, sal_True);
+
+ if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
+ {
+ for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
+ {
+ ScRange aTestRange( nTestCol, nTestRow, i );
+ pDoc->ExtendOverlapped( aTestRange );
+ pDoc->ExtendMerge( aTestRange, sal_True, sal_True);
+ ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
+ if( !aExtendRange.In( aMergeRange ) )
+ {
+ qIncreaseRange.push_back( aTestRange );
+ bInsertMerge = sal_True;
+ }
+ }
+ }
+ else
+ {
+ ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
+ if( !aExtendRange.In( aMergeRange ) )
+ {
+ qIncreaseRange.push_back( aRange );
+ }
+ bInsertMerge = sal_True;
+ }
+ }
+ }
+
+ if( bInsertMerge )
+ {
+ if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN )
+ {
+ nStartRow = aExtendMergeRange.aStart.Row();
+ nEndRow = aExtendMergeRange.aEnd.Row();
+
+ if( eCmd == INS_CELLSDOWN )
+ nEndCol = nMergeTestEndX;
+ else
+ {
+ nStartCol = 0;
+ nEndCol = MAXCOL;
+ }
+ }
+ else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS )
+ {
+
+ nStartCol = aExtendMergeRange.aStart.Col();
+ nEndCol = aExtendMergeRange.aEnd.Col();
+ if( eCmd == INS_CELLSRIGHT )
+ {
+ nEndRow = nMergeTestEndY;
+ }
+ else
+ {
+ nStartRow = 0;
+ nEndRow = MAXROW;
+ }
+ }
+
+ if( !qIncreaseRange.empty() )
+ {
+ for( ::std::vector<ScRange>::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); iIter++ )
+ {
+ ScRange aRange( *iIter );
+ if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
+ {
+ UnmergeCells( aRange, sal_True, sal_True );
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
+ rDocShell.GetUndoManager()->LeaveListAction();
+ return false;
+ }
+ }
+ }
+ }
+
+ switch (eCmd)
+ {
+ case INS_CELLSDOWN:
+ bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
+ nPaintEndY = MAXROW;
+ break;
+ case INS_INSROWS:
+ bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
+ nPaintStartX = 0;
+ nPaintEndX = MAXCOL;
+ nPaintEndY = MAXROW;
+ nPaintFlags |= PAINT_LEFT;
+ break;
+ case INS_CELLSRIGHT:
+ bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
+ nPaintEndX = MAXCOL;
+ break;
+ case INS_INSCOLS:
+ bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
+ nPaintStartY = 0;
+ nPaintEndY = MAXROW;
+ nPaintEndX = MAXCOL;
+ nPaintFlags |= PAINT_TOP;
+ break;
+ default:
+ OSL_FAIL("Falscher Code beim Einfuegen");
+ bSuccess = false;
+ break;
+ }
+
+ if ( bSuccess )
+ {
+ SCTAB* pTabs = NULL;
+ SCTAB* pScenarios = NULL;
+ SCTAB nUndoPos = 0;
+
+ if ( bRecord )
+ {
+ pTabs = new SCTAB[nSelCount];
+ pScenarios = new SCTAB[nSelCount];
+ nUndoPos = 0;
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ SCTAB nCount = 0;
+ for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nCount ++;
+
+ pScenarios[nUndoPos] = nCount;
+ pTabs[nUndoPos] = i;
+ nUndoPos ++;
+ }
+ }
+
+ if( !bInsertMerge )
+ {
+ rDocShell.GetUndoManager()->LeaveListAction();
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells(
+ &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),
+ nUndoPos, pTabs, pScenarios, eCmd, pRefUndoDoc, pUndoData, bPartOfPaste ) );
+ }
+
+ // #i8302 : we remerge growing ranges, with the new part inserted
+
+ while( !qIncreaseRange.empty() )
+ {
+ ScRange aRange = qIncreaseRange.back();
+ if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
+ {
+ switch (eCmd)
+ {
+ case INS_CELLSDOWN:
+ case INS_INSROWS:
+ aRange.aEnd.IncRow(static_cast<SCsCOL>(nEndRow-nStartRow+1));
+ break;
+ case INS_CELLSRIGHT:
+ case INS_INSCOLS:
+ aRange.aEnd.IncCol(static_cast<SCsCOL>(nEndCol-nStartCol+1));
+ break;
+ default:
+ break;
+ }
+ ScCellMergeOption aMergeOption(
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row() );
+ aMergeOption.maTabs.insert(aRange.aStart.Tab());
+ MergeCells(aMergeOption, false, true, true);
+ }
+ qIncreaseRange.pop_back();
+ }
+
+ if( bInsertMerge )
+ rDocShell.GetUndoManager()->LeaveListAction();
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ if (bNeedRefresh)
+ pDoc->ExtendMerge( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i, sal_True );
+ else
+ pDoc->RefreshAutoFilter( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i );
+
+ if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
+ pDoc->UpdatePageBreaks( i );
+
+ sal_uInt16 nExtFlags = 0;
+ rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
+
+ SCTAB nScenarioCount = 0;
+
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nScenarioCount ++;
+
+ sal_Bool bAdjusted = ( eCmd == INS_INSROWS ) ? AdjustRowHeight(ScRange(0, nStartRow, i, MAXCOL, nEndRow, i+nScenarioCount )) :
+ AdjustRowHeight(ScRange(0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount ));
+ if (bAdjusted)
+ {
+ // paint only what is not done by AdjustRowHeight
+ if (nPaintFlags & PAINT_TOP)
+ rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
+ }
+ else
+ rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags );
+ }
+ }
+ }
+ else
+ {
+ if( bInsertMerge )
+ {
+ while( !qIncreaseRange.empty() )
+ {
+ ScRange aRange = qIncreaseRange.back();
+ ScCellMergeOption aMergeOption(
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row() );
+ MergeCells(aMergeOption, false, true, true);
+ qIncreaseRange.pop_back();
+ }
+
+ if( pViewSh )
+ {
+ pViewSh->MarkRange( rRange, false );
+ pViewSh->SetCursor( nCursorCol, nCursorRow );
+ }
+ }
+
+ rDocShell.GetUndoManager()->LeaveListAction();
+ rDocShell.GetUndoManager()->RemoveLastUndoAction();
+
+ delete pRefUndoDoc;
+ delete pUndoData;
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_INSERT_FULL); // Spalte/Zeile voll
+ }
+
+ aModificator.SetDocumentModified();
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
+ return bSuccess;
+}
+
+sal_Bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd,
+ sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
+ {
+ OSL_FAIL("invalid row in DeleteCells");
+ return false;
+ }
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCCOL nPaintStartX = nStartCol;
+ SCROW nPaintStartY = nStartRow;
+ SCCOL nPaintEndX = nEndCol;
+ SCROW nPaintEndY = nEndRow;
+ sal_uInt16 nPaintFlags = PAINT_GRID;
+ SCTAB i;
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ SCTAB nCount = 0;
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( !pDoc->IsScenario(i) )
+ {
+ nCount++;
+ if( nCount == nEndTab+1 )
+ {
+ aMark.SelectTable( i, sal_True );
+ break;
+ }
+ }
+ }
+ }
+
+ ScMarkData aFullMark( aMark ); // including scenario sheets
+ for( i=0; i<nTabCount; i++ )
+ if( aMark.GetTableSelect( i ) )
+ {
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ aFullMark.SelectTable( j, sal_True );
+ }
+
+ SCTAB nSelCount = aMark.GetSelectCount();
+
+ SCCOL nUndoStartX = nStartCol;
+ SCROW nUndoStartY = nStartRow;
+ SCCOL nUndoEndX = nEndCol;
+ SCROW nUndoEndY = nEndRow;
+
+ ScRange aExtendMergeRange( rRange );
+
+ if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
+ {
+ pDoc->ExtendMerge( aExtendMergeRange );
+ pDoc->ExtendOverlapped( aExtendMergeRange );
+ nUndoEndX = aExtendMergeRange.aEnd.Col();
+ nUndoEndY = aExtendMergeRange.aEnd.Row();
+ nPaintEndX = nUndoEndX;
+ nPaintEndY = nUndoEndY;
+ }
+
+ if (eCmd==DEL_DELROWS)
+ {
+ nUndoStartX = 0;
+ nUndoEndX = MAXCOL;
+ }
+ if (eCmd==DEL_DELCOLS)
+ {
+ nUndoStartY = 0;
+ nUndoEndY = MAXROW;
+ }
+ // Test Zellschutz
+
+ SCCOL nEditTestEndX = nUndoEndX;
+ if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
+ nEditTestEndX = MAXCOL;
+ SCROW nEditTestEndY = nUndoEndY;
+ if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
+ nEditTestEndY = MAXROW;
+ ScEditableTester aTester( pDoc, nUndoStartX, nUndoStartY, nEditTestEndX, nEditTestEndY, aMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ // Test zusammengefasste
+
+ SCCOL nMergeTestEndX = (eCmd==DEL_CELLSLEFT) ? MAXCOL : nUndoEndX;
+ SCROW nMergeTestEndY = (eCmd==DEL_CELLSUP) ? MAXROW : nUndoEndY;
+ SCCOL nExtendStartCol = nUndoStartX;
+ SCROW nExtendStartRow = nUndoStartY;
+ sal_Bool bNeedRefresh = false;
+
+ //Issue 8302 want to be able to insert into the middle of merged cells
+ //the patch comes from maoyg
+ ::std::vector<ScRange> qDecreaseRange;
+ sal_Bool bDeletingMerge = false;
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_DELETECELLS );
+ if (bRecord)
+ rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect(i) )
+ {
+ if ( pDoc->HasAttrib( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ {
+ SCCOL nMergeStartX = nUndoStartX;
+ SCROW nMergeStartY = nUndoStartY;
+ SCCOL nMergeEndX = nMergeTestEndX;
+ SCROW nMergeEndY = nMergeTestEndY;
+
+ pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
+ pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
+ if( ( eCmd == DEL_CELLSUP && ( nMergeStartX != nUndoStartX || nMergeEndX != nMergeTestEndX))||
+ ( eCmd == DEL_CELLSLEFT && ( nMergeStartY != nUndoStartY || nMergeEndY != nMergeTestEndY)))
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
+ rDocShell.GetUndoManager()->LeaveListAction();
+ return false;
+ }
+
+ nExtendStartCol = nMergeStartX;
+ nExtendStartRow = nMergeStartY;
+ SCCOL nTestCol = -1;
+ SCROW nTestRow1 = -1;
+ SCROW nTestRow2 = -1;
+
+ ScDocAttrIterator aTestIter( pDoc, i, nUndoStartX, nUndoStartY, nMergeTestEndX, nMergeTestEndY );
+ ScRange aExtendRange( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i );
+ const ScPatternAttr* pPattern = NULL;
+ const ScMergeAttr* pMergeFlag = NULL;
+ const ScMergeFlagAttr* pMergeFlagAttr = NULL;
+ while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
+ {
+ pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
+ pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
+ sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
+ if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
+ {
+ ScRange aRange( nTestCol, nTestRow1, i );
+ pDoc->ExtendOverlapped( aRange );
+ pDoc->ExtendMerge( aRange, sal_True, sal_True );
+
+ if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
+ {
+ for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
+ {
+ ScRange aTestRange( nTestCol, nTestRow, i );
+ pDoc->ExtendOverlapped( aTestRange );
+ pDoc->ExtendMerge( aTestRange, sal_True, sal_True);
+ ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
+ if( !aExtendRange.In( aMergeRange ) )
+ {
+ qDecreaseRange.push_back( aTestRange );
+ bDeletingMerge = sal_True;
+ }
+ }
+ }
+ else
+ {
+ ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
+ if( !aExtendRange.In( aMergeRange ) )
+ {
+ qDecreaseRange.push_back( aRange );
+ }
+ bDeletingMerge = sal_True;
+ }
+ }
+ }
+
+ if( bDeletingMerge )
+ {
+
+ if( eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP )
+ {
+ nStartRow = aExtendMergeRange.aStart.Row();
+ nEndRow = aExtendMergeRange.aEnd.Row();
+ bNeedRefresh = sal_True;
+
+ if( eCmd == DEL_CELLSUP )
+ {
+ nEndCol = aExtendMergeRange.aEnd.Col();
+ }
+ else
+ {
+ nStartCol = 0;
+ nEndCol = MAXCOL;
+ }
+ }
+ else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
+ {
+
+ nStartCol = aExtendMergeRange.aStart.Col();
+ nEndCol = aExtendMergeRange.aEnd.Col();
+ if( eCmd == DEL_CELLSLEFT )
+ {
+ nEndRow = aExtendMergeRange.aEnd.Row();
+ bNeedRefresh = sal_True;
+ }
+ else
+ {
+ nStartRow = 0;
+ nEndRow = MAXROW;
+ }
+ }
+
+ if( !qDecreaseRange.empty() )
+ {
+ for( ::std::vector<ScRange>::const_iterator iIter( qDecreaseRange.begin()); iIter != qDecreaseRange.end(); iIter++ )
+ {
+ ScRange aRange( *iIter );
+ if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
+ {
+ UnmergeCells( aRange, sal_True, sal_True );
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
+ rDocShell.GetUndoManager()->LeaveListAction();
+ return false;
+ }
+ }
+ }
+ }
+
+ //
+ // ausfuehren
+ //
+
+ WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
+
+ ScDocument* pUndoDoc = NULL;
+ ScDocument* pRefUndoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ if ( bRecord )
+ {
+ // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position,
+ // so it's no longer necessary to copy more than the deleted range into pUndoDoc.
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, 0, nTabCount-1, (eCmd==DEL_DELCOLS), (eCmd==DEL_DELROWS) );
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ SCTAB nScenarioCount = 0;
+
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nScenarioCount ++;
+
+ pDoc->CopyToDocument( nUndoStartX, nUndoStartY, i, nUndoEndX, nUndoEndY, i+nScenarioCount,
+ IDF_ALL | IDF_NOCAPTIONS, false, pUndoDoc );
+ }
+ }
+
+ pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
+
+ pUndoData = new ScRefUndoData( pDoc );
+
+ pDoc->BeginDrawUndo();
+ }
+
+ sal_uInt16 nExtFlags = 0;
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, i, nEndCol, nEndRow, i );
+ }
+
+ sal_Bool bUndoOutline = false;
+ switch (eCmd)
+ {
+ case DEL_CELLSUP:
+ pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark );
+ nPaintEndY = MAXROW;
+ break;
+ case DEL_DELROWS:
+ pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
+ nPaintStartX = 0;
+ nPaintEndX = MAXCOL;
+ nPaintEndY = MAXROW;
+ nPaintFlags |= PAINT_LEFT;
+ break;
+ case DEL_CELLSLEFT:
+ pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark );
+ nPaintEndX = MAXCOL;
+ break;
+ case DEL_DELCOLS:
+ pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
+ nPaintStartY = 0;
+ nPaintEndY = MAXROW;
+ nPaintEndX = MAXCOL;
+ nPaintFlags |= PAINT_TOP;
+ break;
+ default:
+ OSL_FAIL("Falscher Code beim Loeschen");
+ break;
+ }
+
+ //! Test, ob Outline in Groesse geaendert
+
+ if ( bRecord )
+ {
+ for( i=0; i<nTabCount; i++ )
+ if( aFullMark.GetTableSelect( i ) )
+ pRefUndoDoc->DeleteAreaTab(nUndoStartX,nUndoStartY,nUndoEndX,nUndoEndY, i, IDF_ALL);
+
+ // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
+ pUndoDoc->AddUndoTab( 0, nTabCount-1, false, false );
+
+ // kopieren mit bColRowFlags=sal_False (#54194#)
+ pRefUndoDoc->CopyToDocument(0,0,0,MAXCOL,MAXROW,MAXTAB,IDF_FORMULA,false,pUndoDoc,NULL,false);
+ delete pRefUndoDoc;
+
+ SCTAB* pTabs = new SCTAB[nSelCount];
+ SCTAB* pScenarios = new SCTAB[nSelCount];
+ SCTAB nUndoPos = 0;
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ SCTAB nCount = 0;
+ for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nCount ++;
+
+ pScenarios[nUndoPos] = nCount;
+ pTabs[nUndoPos] = i;
+ nUndoPos ++;
+ }
+ }
+
+ if( !bDeletingMerge )
+ {
+ rDocShell.GetUndoManager()->LeaveListAction();
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
+ &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios,
+ eCmd, pUndoDoc, pUndoData ) );
+ }
+
+ // #i8302 want to be able to insert into the middle of merged cells
+ // the patch comes from maoyg
+
+ while( !qDecreaseRange.empty() )
+ {
+ ScRange aRange = qDecreaseRange.back();
+
+ long nDecreaseRowCount = 0;
+ long nDecreaseColCount = 0;
+ if( eCmd == DEL_CELLSUP || eCmd == DEL_DELROWS )
+ {
+ if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
+ nDecreaseRowCount = nEndRow-nStartRow+1;
+ else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() )
+ nDecreaseRowCount = aRange.aEnd.Row()-nStartRow+1;
+ else if( nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
+ nDecreaseRowCount = aRange.aEnd.Row()-nEndRow+1;
+ }
+ else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
+ {
+ if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
+ nDecreaseColCount = nEndCol-nStartCol+1;
+ else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() )
+ nDecreaseColCount = aRange.aEnd.Col()-nStartCol+1;
+ else if( nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
+ nDecreaseColCount = aRange.aEnd.Col()-nEndCol+1;
+ }
+
+ switch (eCmd)
+ {
+ case DEL_CELLSUP:
+ case DEL_DELROWS:
+ aRange.aEnd.SetRow(static_cast<SCsCOL>( aRange.aEnd.Row()-nDecreaseRowCount));
+ break;
+ case DEL_CELLSLEFT:
+ case DEL_DELCOLS:
+ aRange.aEnd.SetCol(static_cast<SCsCOL>( aRange.aEnd.Col()-nDecreaseColCount));
+ break;
+ default:
+ break;
+ }
+
+ if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
+ {
+ ScCellMergeOption aMergeOption(aRange);
+ MergeCells( aMergeOption, false, true, true );
+ }
+ qDecreaseRange.pop_back();
+ }
+
+ if( bDeletingMerge )
+ rDocShell.GetUndoManager()->LeaveListAction();
+
+ if ( bNeedRefresh )
+ {
+ // #i51445# old merge flag attributes must be deleted also for single cells,
+ // not only for whole columns/rows
+
+ if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
+ nMergeTestEndX = MAXCOL;
+ if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
+ nMergeTestEndY = MAXROW;
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetItemSet().Put( ScMergeFlagAttr() );
+
+ pDoc->ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndX, nMergeTestEndY, aMark, aPattern );
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ SCTAB nScenarioCount = 0;
+
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nScenarioCount ++;
+
+ ScRange aMergedRange( nExtendStartCol, nExtendStartRow, i, nMergeTestEndX, nMergeTestEndY, i+nScenarioCount );
+ pDoc->ExtendMerge( aMergedRange, sal_True );
+ }
+ }
+ }
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ if ( eCmd == DEL_DELCOLS || eCmd == DEL_DELROWS )
+ pDoc->UpdatePageBreaks( i );
+
+ rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
+
+ SCTAB nScenarioCount = 0;
+
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nScenarioCount ++;
+
+ // ganze Zeilen loeschen: nichts anpassen
+ if ( eCmd == DEL_DELROWS || !AdjustRowHeight(ScRange( 0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount )) )
+ rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags );
+ else
+ {
+ // paint only what is not done by AdjustRowHeight
+ if (nExtFlags & SC_PF_LINES)
+ lcl_PaintAbove( rDocShell, ScRange( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount) );
+ if (nPaintFlags & PAINT_TOP)
+ rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
+ }
+ }
+ }
+ aModificator.SetDocumentModified();
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
+
+ return sal_True;
+}
+
+sal_Bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
+ sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nStartCol = rSource.aStart.Col();
+ SCROW nStartRow = rSource.aStart.Row();
+ SCTAB nStartTab = rSource.aStart.Tab();
+ SCCOL nEndCol = rSource.aEnd.Col();
+ SCROW nEndRow = rSource.aEnd.Row();
+ SCTAB nEndTab = rSource.aEnd.Tab();
+ SCCOL nDestCol = rDestPos.Col();
+ SCROW nDestRow = rDestPos.Row();
+ SCTAB nDestTab = rDestPos.Tab();
+
+ if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) || !ValidRow(nDestRow) )
+ {
+ OSL_FAIL("invalid row in MoveBlock");
+ return false;
+ }
+
+ // zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird!
+ sal_Bool bScenariosAdded = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ if ( nDestTab == nStartTab && !pDoc->IsScenario(nEndTab) )
+ while ( nEndTab+1 < nTabCount && pDoc->IsScenario(nEndTab+1) )
+ {
+ ++nEndTab;
+ bScenariosAdded = sal_True;
+ }
+
+ SCTAB nSrcTabCount = nEndTab-nStartTab+1;
+ SCTAB nDestEndTab = nDestTab+nSrcTabCount-1;
+ SCTAB nTab;
+
+ ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
+
+ ScMarkData aSourceMark;
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aSourceMark.SelectTable( nTab, sal_True ); // Source selektieren
+ aSourceMark.SetMarkArea( rSource );
+
+ ScDocShellRef aDragShellRef;
+ if ( pDoc->HasOLEObjectsInArea( rSource ) )
+ {
+ aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately
+ aDragShellRef->DoInitNew(NULL);
+ }
+ ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
+
+ ScClipParam aClipParam(ScRange(nStartCol, nStartRow, 0, nEndCol, nEndRow, 0), bCut);
+ pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true);
+
+ ScDrawLayer::SetGlobalDrawPersist(NULL);
+
+ SCCOL nOldEndCol = nEndCol;
+ SCROW nOldEndRow = nEndRow;
+ sal_Bool bClipOver = false;
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ {
+ SCCOL nTmpEndCol = nOldEndCol;
+ SCROW nTmpEndRow = nOldEndRow;
+ if (pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab ))
+ bClipOver = sal_True;
+ if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol;
+ if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow;
+ }
+
+ SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol );
+ SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow );
+
+ SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol ); // erweitert im Zielblock
+ SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow );
+
+ sal_Bool bIncludeFiltered = bCut;
+ if ( !bIncludeFiltered )
+ {
+ // adjust sizes to include only non-filtered rows
+
+ SCCOL nClipX;
+ SCROW nClipY;
+ pClipDoc->GetClipArea( nClipX, nClipY, false );
+ SCROW nUndoAdd = nUndoEndRow - nDestEndRow;
+ nDestEndRow = nDestRow + nClipY;
+ nUndoEndRow = nDestEndRow + nUndoAdd;
+ }
+
+ if (!ValidCol(nUndoEndCol) || !ValidRow(nUndoEndRow))
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PASTE_FULL);
+ delete pClipDoc;
+ return false;
+ }
+
+ // Test auf Zellschutz
+
+ ScEditableTester aTester;
+ for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
+ aTester.TestBlock( pDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow );
+ if (bCut)
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aTester.TestBlock( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
+
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ delete pClipDoc;
+ return false;
+ }
+
+ // Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen
+
+ if (bClipOver && !bCut)
+ if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ { // "Zusammenfassen nicht verschachteln !"
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
+ delete pClipDoc;
+ return false;
+ }
+
+ // Are there borders in the cells? (for painting)
+
+ sal_uInt16 nSourceExt = 0;
+ rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab );
+ sal_uInt16 nDestExt = 0;
+ rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab );
+
+ //
+ // ausfuehren
+ //
+
+ ScDocument* pUndoDoc = NULL;
+ ScDocument* pRefUndoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ if (bRecord)
+ {
+ sal_Bool bWholeCols = ( nStartRow == 0 && nEndRow == MAXROW );
+ sal_Bool bWholeRows = ( nStartCol == 0 && nEndCol == MAXCOL );
+ sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bWholeCols, bWholeRows );
+
+ if (bCut)
+ {
+ pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
+ nUndoFlags, false, pUndoDoc );
+ pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
+ }
+
+ if ( nDestTab != nStartTab )
+ pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows );
+ pDoc->CopyToDocument( nDestCol, nDestRow, nDestTab,
+ nDestEndCol, nDestEndRow, nDestEndTab,
+ nUndoFlags, false, pUndoDoc );
+
+ pUndoData = new ScRefUndoData( pDoc );
+
+ pDoc->BeginDrawUndo();
+ }
+
+ sal_Bool bSourceHeight = false; // Hoehen angepasst?
+ if (bCut)
+ {
+ ScMarkData aDelMark; // only for tables
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ {
+ pDoc->DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, IDF_ALL );
+ aDelMark.SelectTable( nTab, sal_True );
+ }
+ pDoc->DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark );
+
+ // Test auf zusammengefasste
+
+ if (bClipOver)
+ if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab,
+ nUndoEndCol,nUndoEndRow,nDestEndTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ {
+ pDoc->CopyFromClip( rSource, aSourceMark, IDF_ALL, pRefUndoDoc, pClipDoc );
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ {
+ SCCOL nTmpEndCol = nEndCol;
+ SCROW nTmpEndRow = nEndRow;
+ pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, sal_True );
+ }
+
+ // Fehlermeldung erst nach dem Wiederherstellen des Inhalts
+ if (!bApi) // "Zusammenfassen nicht verschachteln !"
+ rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
+
+ delete pUndoDoc;
+ delete pRefUndoDoc;
+ delete pUndoData;
+ delete pClipDoc;
+ return false;
+ }
+
+ bSourceHeight = AdjustRowHeight( rSource, false );
+ }
+
+ ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab );
+
+ ScMarkData aDestMark;
+ for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
+ aDestMark.SelectTable( nTab, sal_True ); // Destination selektieren
+ aDestMark.SetMarkArea( aPasteDest );
+
+ /* Do not copy cell notes and drawing objects here. While pasting, the
+ function ScDocument::UpdateReference() is called which calls
+ ScDrawLayer::MoveCells() which may move away inserted objects to wrong
+ positions (e.g. if source and destination range overlaps). Cell notes
+ and drawing objects are pasted below after doing all adjusting. */
+ pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_ALL & ~(IDF_NOTE | IDF_OBJECTS),
+ pRefUndoDoc, pClipDoc, sal_True, false, bIncludeFiltered );
+
+ // skipped rows and merged cells don't mix
+ if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
+ UnmergeCells( aPasteDest, false, sal_True );
+
+ VirtualDevice aVirtDev;
+ sal_Bool bDestHeight = AdjustRowHeight(
+ ScRange( 0,nDestRow,nDestTab, MAXCOL,nDestEndRow,nDestEndTab ),
+ false );
+
+ /* Paste cell notes and drawing objects after adjusting formula references
+ and row heights. There are no cell notes or drawing objects, if the
+ clipdoc does not contain a drawing layer.
+ #i102056# Passing IDF_NOTE only would overwrite cell contents with
+ empty note cells, therefore the special modifier IDF_ADDNOTES is passed
+ here too which changes the behaviour of ScColumn::CopyFromClip() to not
+ touch existing cells. */
+ if ( pClipDoc->GetDrawLayer() )
+ pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_NOTE | IDF_ADDNOTES | IDF_OBJECTS,
+ pRefUndoDoc, pClipDoc, sal_True, false, bIncludeFiltered );
+
+ if (bRecord)
+ {
+ if (pRefUndoDoc)
+ {
+ // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
+ pUndoDoc->AddUndoTab( 0, nTabCount-1, false, false );
+
+ pRefUndoDoc->DeleteArea( nDestCol, nDestRow, nDestEndCol, nDestEndRow, aSourceMark, IDF_ALL );
+ // kopieren mit bColRowFlags=sal_False (#54194#)
+ pRefUndoDoc->CopyToDocument( 0, 0, 0, MAXCOL, MAXROW, MAXTAB,
+ IDF_FORMULA, false, pUndoDoc, NULL, false );
+ delete pRefUndoDoc;
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDragDrop( &rDocShell, ScRange(
+ nStartCol, nStartRow, nStartTab,
+ nOldEndCol, nOldEndRow, nEndTab ),
+ ScAddress( nDestCol, nDestRow, nDestTab ),
+ bCut, pUndoDoc, pUndoData, bScenariosAdded ) );
+ }
+
+ SCCOL nDestPaintEndCol = nDestEndCol;
+ SCROW nDestPaintEndRow = nDestEndRow;
+ for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
+ {
+ SCCOL nTmpEndCol = nDestEndCol;
+ SCROW nTmpEndRow = nDestEndRow;
+ pDoc->ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, sal_True );
+ if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol;
+ if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow;
+ }
+
+ if (bCut)
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ pDoc->RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
+
+ if (bPaint)
+ {
+ // Zielbereich:
+
+ SCCOL nPaintStartX = nDestCol;
+ SCROW nPaintStartY = nDestRow;
+ SCCOL nPaintEndX = nDestPaintEndCol;
+ SCROW nPaintEndY = nDestPaintEndRow;
+ sal_uInt16 nFlags = PAINT_GRID;
+
+ if ( nStartRow==0 && nEndRow==MAXROW ) // Breiten mitkopiert?
+ {
+ nPaintEndX = MAXCOL;
+ nPaintStartY = 0;
+ nPaintEndY = MAXROW;
+ nFlags |= PAINT_TOP;
+ }
+ if ( bDestHeight || ( nStartCol == 0 && nEndCol == MAXCOL ) )
+ {
+ nPaintEndY = MAXROW;
+ nPaintStartX = 0;
+ nPaintEndX = MAXCOL;
+ nFlags |= PAINT_LEFT;
+ }
+ if ( bScenariosAdded )
+ {
+ nPaintStartX = 0;
+ nPaintStartY = 0;
+ nPaintEndX = MAXCOL;
+ nPaintEndY = MAXROW;
+ }
+
+ rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab,
+ nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt );
+
+ if ( bCut )
+ {
+ // Quellbereich:
+
+ nPaintStartX = nStartCol;
+ nPaintStartY = nStartRow;
+ nPaintEndX = nEndCol;
+ nPaintEndY = nEndRow;
+ nFlags = PAINT_GRID;
+
+ if ( bSourceHeight )
+ {
+ nPaintEndY = MAXROW;
+ nPaintStartX = 0;
+ nPaintEndX = MAXCOL;
+ nFlags |= PAINT_LEFT;
+ }
+ if ( bScenariosAdded )
+ {
+ nPaintStartX = 0;
+ nPaintStartY = 0;
+ nPaintEndX = MAXCOL;
+ nPaintEndY = MAXROW;
+ }
+
+ rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab,
+ nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt );
+ }
+ }
+
+ aModificator.SetDocumentModified();
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
+
+ delete pClipDoc;
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+uno::Reference< uno::XInterface > GetDocModuleObject( SfxObjectShell& rDocSh, String& sCodeName )
+{
+ uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY);
+ uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess;
+ uno::Reference< uno::XInterface > xDocModuleApiObject;
+ if ( xSF.is() )
+ {
+ xVBACodeNamedObjectAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), uno::UNO_QUERY );
+ xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY );
+ }
+ return xDocModuleApiObject;
+
+}
+
+script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, String& sModule )
+{
+ script::ModuleInfo sModuleInfo;
+ sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
+ sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule );
+ return sModuleInfo;
+}
+
+void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, String& sModuleName, String& sSource )
+{
+ SfxObjectShell& rDocSh = *rDoc.GetDocumentShell();
+ uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
+ DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" );
+
+ uno::Reference< container::XNameContainer > xLib;
+ if( xLibContainer.is() )
+ {
+ String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
+ if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() )
+ aLibName = rDocSh.GetBasicManager()->GetName();
+ uno::Any aLibAny = xLibContainer->getByName( aLibName );
+ aLibAny >>= xLib;
+ }
+ if( xLib.is() )
+ {
+ // if the Module with codename exists then find a new name
+ sal_Int32 nNum = 0;
+ String genModuleName;
+ if ( sModuleName.Len() )
+ genModuleName = sModuleName;
+ else
+ {
+ genModuleName = String::CreateFromAscii( "Sheet1" );
+ nNum = 1;
+ }
+ while( xLib->hasByName( genModuleName ) )
+ genModuleName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Sheet")) + rtl::OUString::valueOf( ++nNum );
+
+ uno::Any aSourceAny;
+ rtl::OUString sTmpSource = sSource;
+ if ( sTmpSource.getLength() == 0 )
+ sTmpSource = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n" ));
+ aSourceAny <<= sTmpSource;
+ uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
+ if ( xVBAModuleInfo.is() )
+ {
+ rDoc.SetCodeName( nTab, genModuleName );
+ script::ModuleInfo sModuleInfo = lcl_InitModuleInfo( rDocSh, genModuleName );
+ xVBAModuleInfo->insertModuleInfo( genModuleName, sModuleInfo );
+ xLib->insertByName( genModuleName, aSourceAny );
+ }
+
+ }
+}
+
+void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName )
+{
+ uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
+ DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" );
+
+ uno::Reference< container::XNameContainer > xLib;
+ if( xLibContainer.is() )
+ {
+ String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
+ if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() )
+ aLibName = rDocSh.GetBasicManager()->GetName();
+ uno::Any aLibAny = xLibContainer->getByName( aLibName );
+ aLibAny >>= xLib;
+ }
+ if( xLib.is() )
+ {
+ uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
+ if( xLib->hasByName( sModuleName ) )
+ xLib->removeByName( sModuleName );
+ if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo(sModuleName) )
+ xVBAModuleInfo->removeModuleInfo( sModuleName );
+
+ }
+}
+
+
+sal_Bool ScDocFunc::InsertTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi )
+{
+ sal_Bool bSuccess = false;
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+
+ // Strange loop, also basic is loaded too early ( InsertTable )
+ // is called via the xml import for sheets in described in odf
+ sal_Bool bInsertDocModule = false;
+
+ if( !rDocShell.GetDocument()->IsImportingXML() )
+ {
+ bInsertDocModule = pDoc ? pDoc->IsInVBAMode() : false;
+ }
+ if ( bInsertDocModule || ( bRecord && !pDoc->IsUndoEnabled() ) )
+ bRecord = false;
+
+ if (bRecord)
+ pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ sal_Bool bAppend = ( nTab >= nTabCount );
+ if ( bAppend )
+ nTab = nTabCount; // wichtig fuer Undo
+
+ if (pDoc->InsertTab( nTab, rName ))
+ {
+ String sCodeName;
+ if (bRecord)
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName));
+ // Views updaten:
+ // Only insert vba modules if vba mode ( and not currently importing XML )
+ if( bInsertDocModule )
+ {
+ String sSource;
+ VBA_InsertModule( *pDoc, nTab, sCodeName, sSource );
+ }
+ rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) );
+
+ rDocShell.PostPaintExtras();
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ bSuccess = sal_True;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(STR_TABINSERT_ERROR);
+
+ return bSuccess;
+}
+
+sal_Bool ScDocFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord, sal_Bool /* bApi */ )
+{
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ sal_Bool bSuccess = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ sal_Bool bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : false;
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+ if ( bVbaEnabled )
+ bRecord = false;
+ sal_Bool bWasLinked = pDoc->IsLinked(nTab);
+ ScDocument* pUndoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ if (bRecord)
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ SCTAB nCount = pDoc->GetTableCount();
+
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); // nur nTab mit Flags
+ pUndoDoc->AddUndoTab( 0, nCount-1 ); // alle Tabs fuer Referenzen
+
+ pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,false, pUndoDoc );
+ String aOldName;
+ pDoc->GetName( nTab, aOldName );
+ pUndoDoc->RenameTab( nTab, aOldName, false );
+ if (bWasLinked)
+ pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
+ pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
+ pDoc->GetLinkTab(nTab),
+ pDoc->GetLinkRefreshDelay(nTab) );
+
+ if ( pDoc->IsScenario(nTab) )
+ {
+ pUndoDoc->SetScenario( nTab, sal_True );
+ String aComment;
+ Color aColor;
+ sal_uInt16 nScenFlags;
+ pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
+ pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
+ sal_Bool bActive = pDoc->IsActiveScenario( nTab );
+ pUndoDoc->SetActiveScenario( nTab, bActive );
+ }
+ pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
+ pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) );
+ pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) );
+
+ // Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
+ pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage
+
+ pUndoData = new ScRefUndoData( pDoc );
+ }
+
+ String sCodeName;
+ sal_Bool bHasCodeName = pDoc->GetCodeName( nTab, sCodeName );
+ if (pDoc->DeleteTab( nTab, pUndoDoc ))
+ {
+ if (bRecord)
+ {
+ vector<SCTAB> theTabs;
+ theTabs.push_back(nTab);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData ));
+ }
+ // Views updaten:
+ if( bVbaEnabled )
+ {
+ if( bHasCodeName )
+ {
+ VBA_DeleteModule( rDocShell, sCodeName );
+ }
+ }
+ rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) );
+
+ if (bWasLinked)
+ {
+ rDocShell.UpdateLinks(); // Link-Manager updaten
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate(SID_LINKS);
+ }
+
+ rDocShell.PostPaintExtras();
+ aModificator.SetDocumentModified();
+
+ 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 ) );
+
+ bSuccess = sal_True;
+ }
+ else
+ {
+ delete pUndoDoc;
+ delete pUndoData;
+ }
+ return bSuccess;
+}
+
+sal_Bool ScDocFunc::SetTableVisible( SCTAB nTab, sal_Bool bVisible, sal_Bool bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ sal_Bool bUndo(pDoc->IsUndoEnabled());
+ if ( pDoc->IsVisible( nTab ) == bVisible )
+ return sal_True; // nichts zu tun - ok
+
+ if ( !pDoc->IsDocEditable() )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR);
+ return false;
+ }
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ if ( !bVisible && !pDoc->IsImportingXML() ) // #i57869# allow hiding in any order for loading
+ {
+ // nicht alle Tabellen ausblenden
+
+ sal_uInt16 nVisCount = 0;
+ SCTAB nCount = pDoc->GetTableCount();
+ for (SCTAB i=0; i<nCount; i++)
+ if (pDoc->IsVisible(i))
+ ++nVisCount;
+
+ if (nVisCount <= 1)
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
+ return false;
+ }
+ }
+
+ pDoc->SetVisible( nTab, bVisible );
+ if (bUndo)
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell, nTab, bVisible ) );
+
+ // Views updaten:
+ if (!bVisible)
+ rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
+ aModificator.SetDocumentModified();
+
+ return sal_True;
+}
+
+sal_Bool ScDocFunc::SetLayoutRTL( SCTAB nTab, sal_Bool bRTL, sal_Bool /* bApi */ )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ sal_Bool bUndo(pDoc->IsUndoEnabled());
+ if ( pDoc->IsLayoutRTL( nTab ) == bRTL )
+ return sal_True; // nothing to do - ok
+
+ //! protection (sheet or document?)
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ pDoc->SetLayoutRTL( nTab, bRTL );
+
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell, nTab, bRTL ) );
+ }
+
+ rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_TAB_RTL );
+ pBindings->Invalidate( SID_ATTR_SIZE );
+ }
+
+ return sal_True;
+}
+
+sal_Bool ScDocFunc::RenameTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+ if ( !pDoc->IsDocEditable() )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR);
+ return false;
+ }
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ sal_Bool bSuccess = false;
+ String sOldName;
+ pDoc->GetName(nTab, sOldName);
+ if (pDoc->RenameTab( nTab, rName ))
+ {
+ if (bRecord)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRenameTab( &rDocShell, nTab, sOldName, rName));
+ }
+ rDocShell.PostPaintExtras();
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+
+ bSuccess = sal_True;
+ }
+ return bSuccess;
+}
+
+bool ScDocFunc::SetTabBgColor( SCTAB nTab, const Color& rColor, bool bRecord, bool bApi )
+{
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+ if ( !pDoc->IsDocEditable() || pDoc->IsTabProtected(nTab) )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Check to see what this string is...
+ return false;
+ }
+
+ Color aOldTabBgColor;
+ aOldTabBgColor = pDoc->GetTabBgColor(nTab);
+
+ bool bSuccess = false;
+ pDoc->SetTabBgColor(nTab, rColor);
+ if ( pDoc->GetTabBgColor(nTab) == rColor)
+ bSuccess = true;
+ if (bSuccess)
+ {
+ if (bRecord)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabColor( &rDocShell, nTab, aOldTabBgColor, rColor));
+ }
+ rDocShell.PostPaintExtras();
+ ScDocShellModificator aModificator( rDocShell );
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+
+ bSuccess = true;
+ }
+ return bSuccess;
+}
+
+bool ScDocFunc::SetTabBgColor(
+ ScUndoTabColorInfo::List& rUndoTabColorList, bool bRecord, bool bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ if ( !pDoc->IsDocEditable() )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
+ return false;
+ }
+
+ sal_uInt16 nTab;
+ Color aNewTabBgColor;
+ bool bSuccess = true;
+ size_t nTabProtectCount = 0;
+ size_t nTabListCount = rUndoTabColorList.size();
+ for ( size_t i = 0; i < nTabListCount; ++i )
+ {
+ ScUndoTabColorInfo& rInfo = rUndoTabColorList[i];
+ nTab = rInfo.mnTabId;
+ if ( !pDoc->IsTabProtected(nTab) )
+ {
+ aNewTabBgColor = rInfo.maNewTabBgColor;
+ rInfo.maOldTabBgColor = pDoc->GetTabBgColor(nTab);
+ pDoc->SetTabBgColor(nTab, aNewTabBgColor);
+ if ( pDoc->GetTabBgColor(nTab) != aNewTabBgColor)
+ {
+ bSuccess = false;
+ break;
+ }
+ }
+ else
+ {
+ nTabProtectCount++;
+ }
+ }
+
+ if ( nTabProtectCount == nTabListCount )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
+ return false;
+ }
+
+ if (bSuccess)
+ {
+ if (bRecord)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabColor( &rDocShell, rUndoTabColorList));
+ }
+ rDocShell.PostPaintExtras();
+ ScDocShellModificator aModificator( rDocShell );
+ aModificator.SetDocumentModified();
+ }
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+
+//! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!!
+//! Probleme:
+//! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm
+//! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen
+
+sal_uInt16 lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab, sal_Bool bFormula )
+{
+ sal_uInt16 nTwips = 0;
+
+ ScSizeDeviceProvider aProv(&rDocShell);
+ OutputDevice* pDev = aProv.GetDevice(); // has pixel MapMode
+ double nPPTX = aProv.GetPPTX();
+ double nPPTY = aProv.GetPPTY();
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ Fraction aOne(1,1);
+ nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne,
+ bFormula, NULL );
+
+ return nTwips;
+}
+
+sal_Bool ScDocFunc::SetWidthOrHeight( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, SCTAB nTab,
+ ScSizeMode eMode, sal_uInt16 nSizeTwips,
+ sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ if (!nRangeCnt)
+ return sal_True;
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if ( bRecord && !pDoc->IsUndoEnabled() )
+ bRecord = false;
+
+ // import into read-only document is possible
+ if ( !pDoc->IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
+ return false;
+ }
+
+ sal_Bool bSuccess = false;
+ SCCOLROW nStart = pRanges[0];
+ SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
+
+ sal_Bool bFormula = false;
+ if ( eMode == SC_SIZE_OPTIMAL )
+ {
+ //! Option "Formeln anzeigen" - woher nehmen?
+ }
+
+ ScDocument* pUndoDoc = NULL;
+ ScOutlineTable* pUndoTab = NULL;
+ SCCOLROW* pUndoRanges = NULL;
+
+ if ( bRecord )
+ {
+ pDoc->BeginDrawUndo(); // Drawing Updates
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ if (bWidth)
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, false );
+ pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, false, pUndoDoc );
+ }
+ else
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
+ pDoc->CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, MAXCOL, static_cast<SCROW>(nEnd), nTab, IDF_NONE, false, pUndoDoc );
+ }
+
+ pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
+ memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
+
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+ if (pTable)
+ pUndoTab = new ScOutlineTable( *pTable );
+ }
+
+ sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
+ sal_Bool bOutline = false;
+
+ pDoc->InitializeNoteCaptions(nTab);
+ for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
+ {
+ SCCOLROW nStartNo = *(pRanges++);
+ SCCOLROW nEndNo = *(pRanges++);
+
+ if ( !bWidth ) // Hoehen immer blockweise
+ {
+ if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
+ {
+ sal_Bool bAll = ( eMode==SC_SIZE_OPTIMAL );
+ if (!bAll)
+ {
+ // fuer alle eingeblendeten CR_MANUALSIZE loeschen,
+ // dann SetOptimalHeight mit bShrink = FALSE
+ for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++)
+ {
+ sal_uInt8 nOld = pDoc->GetRowFlags(nRow,nTab);
+ SCROW nLastRow = -1;
+ bool bHidden = pDoc->RowHidden(nRow, nTab, NULL, &nLastRow);
+ if ( !bHidden && ( nOld & CR_MANUALSIZE ) )
+ pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE );
+ }
+ }
+
+ ScSizeDeviceProvider aProv( &rDocShell );
+ Fraction aOne(1,1);
+ pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(),
+ aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, bAll );
+
+ if (bAll)
+ pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
+
+ // Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt
+ // (an bei Extra-Height, sonst aus).
+ }
+ else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL )
+ {
+ if (nSizeTwips)
+ {
+ pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
+ pDoc->SetManualHeight( nStartNo, nEndNo, nTab, sal_True ); // height was set manually
+ }
+ if ( eMode != SC_SIZE_ORIGINAL )
+ pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
+ }
+ else if ( eMode==SC_SIZE_SHOW )
+ {
+ pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
+ }
+ }
+ else // Spaltenbreiten
+ {
+ for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
+ {
+ if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) )
+ {
+ sal_uInt16 nThisSize = nSizeTwips;
+
+ if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
+ nThisSize = nSizeTwips +
+ lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula );
+ if ( nThisSize )
+ pDoc->SetColWidth( nCol, nTab, nThisSize );
+
+ if ( eMode != SC_SIZE_ORIGINAL )
+ pDoc->ShowCol( nCol, nTab, bShow );
+ }
+ }
+ }
+
+ // adjust outlines
+
+ if ( eMode != SC_SIZE_ORIGINAL )
+ {
+ if (bWidth)
+ bOutline = bOutline || pDoc->UpdateOutlineCol(
+ static_cast<SCCOL>(nStartNo),
+ static_cast<SCCOL>(nEndNo), nTab, bShow );
+ else
+ bOutline = bOutline || pDoc->UpdateOutlineRow(
+ static_cast<SCROW>(nStartNo),
+ static_cast<SCROW>(nEndNo), nTab, bShow );
+ }
+ }
+ pDoc->SetDrawPageSize(nTab);
+
+ if (!bOutline)
+ DELETEZ(pUndoTab);
+
+ if (bRecord)
+ {
+ ScMarkData aMark;
+ aMark.SelectOneTable( nTab );
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoWidthOrHeight( &rDocShell, aMark,
+ nStart, nTab, nEnd, nTab,
+ pUndoDoc, nRangeCnt, pUndoRanges,
+ pUndoTab, eMode, nSizeTwips, bWidth ) );
+ }
+
+ pDoc->UpdatePageBreaks( nTab );
+
+ rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL);
+ aModificator.SetDocumentModified();
+
+ return bSuccess;
+}
+
+
+sal_Bool ScDocFunc::InsertPageBreak( sal_Bool bColumn, const ScAddress& rPos,
+ sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+ SCTAB nTab = rPos.Tab();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+
+ SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
+ static_cast<SCCOLROW>(rPos.Row());
+ if (nPos == 0)
+ return false; // erste Spalte / Zeile
+
+ ScBreakType nBreak = bColumn ?
+ pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab) :
+ pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
+ if (nBreak & BREAK_MANUAL)
+ return true;
+
+ if (bRecord)
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_True ) );
+
+ if (bColumn)
+ pDoc->SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
+ else
+ pDoc->SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
+
+ pDoc->InvalidatePageBreaks(nTab);
+ pDoc->UpdatePageBreaks( nTab );
+
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, false);
+
+ if (bColumn)
+ {
+ rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_INS_COLBRK );
+ pBindings->Invalidate( FID_DEL_COLBRK );
+ }
+ }
+ else
+ {
+ rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_INS_ROWBRK );
+ pBindings->Invalidate( FID_DEL_ROWBRK );
+ }
+ }
+ if (pBindings)
+ pBindings->Invalidate( FID_DEL_MANUALBREAKS );
+
+ if (bSetModified)
+ aModificator.SetDocumentModified();
+
+ return sal_True;
+}
+
+sal_Bool ScDocFunc::RemovePageBreak( sal_Bool bColumn, const ScAddress& rPos,
+ sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+ SCTAB nTab = rPos.Tab();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+
+ SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
+ static_cast<SCCOLROW>(rPos.Row());
+
+ ScBreakType nBreak;
+ if (bColumn)
+ nBreak = pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab);
+ else
+ nBreak = pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
+ if ((nBreak & BREAK_MANUAL) == 0)
+ // There is no manual break.
+ return false;
+
+ if (bRecord)
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, false ) );
+
+ if (bColumn)
+ pDoc->RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
+ else
+ pDoc->RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
+
+ pDoc->UpdatePageBreaks( nTab );
+
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, false);
+
+ if (bColumn)
+ {
+ rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_INS_COLBRK );
+ pBindings->Invalidate( FID_DEL_COLBRK );
+ }
+ }
+ else
+ {
+ rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_INS_ROWBRK );
+ pBindings->Invalidate( FID_DEL_ROWBRK );
+ }
+ }
+ if (pBindings)
+ pBindings->Invalidate( FID_DEL_MANUALBREAKS );
+
+ if (bSetModified)
+ aModificator.SetDocumentModified();
+
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+
+void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ pDoc->SetTabProtection(nTab, &rProtect);
+ if (pDoc->IsUndoEnabled())
+ {
+ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
+ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
+ if (pProtect)
+ {
+ ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
+ p->setProtected(true); // just in case ...
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabProtect(&rDocShell, nTab, p) );
+
+ // ownership of auto_ptr now transferred to ScUndoTabProtect.
+ }
+ }
+
+ rDocShell.PostPaintGridAll();
+ ScDocShellModificator aModificator(rDocShell);
+ aModificator.SetDocumentModified();
+}
+
+sal_Bool ScDocFunc::Protect( SCTAB nTab, const String& rPassword, sal_Bool /*bApi*/ )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (nTab == TABLEID_DOC)
+ {
+ // document protection
+ ScDocProtection aProtection;
+ aProtection.setProtected(true);
+ aProtection.setPassword(rPassword);
+ pDoc->SetDocProtection(&aProtection);
+ if (pDoc->IsUndoEnabled())
+ {
+ ScDocProtection* pProtect = pDoc->GetDocProtection();
+ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
+ if (pProtect)
+ {
+ ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect));
+ p->setProtected(true); // just in case ...
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDocProtect(&rDocShell, p) );
+ // ownership of auto_ptr is transferred to ScUndoDocProtect.
+ }
+ }
+ }
+ else
+ {
+ // sheet protection
+
+ ScTableProtection aProtection;
+ aProtection.setProtected(true);
+ aProtection.setPassword(rPassword);
+ pDoc->SetTabProtection(nTab, &aProtection);
+ if (pDoc->IsUndoEnabled())
+ {
+ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
+ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
+ if (pProtect)
+ {
+ ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
+ p->setProtected(true); // just in case ...
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabProtect(&rDocShell, nTab, p) );
+ // ownership of auto_ptr now transferred to ScUndoTabProtect.
+ }
+ }
+ }
+
+ rDocShell.PostPaintGridAll();
+ ScDocShellModificator aModificator( rDocShell );
+ aModificator.SetDocumentModified();
+
+ return true;
+}
+
+sal_Bool ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, sal_Bool bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (nTab == TABLEID_DOC)
+ {
+ // document protection
+
+ ScDocProtection* pDocProtect = pDoc->GetDocProtection();
+ if (!pDocProtect || !pDocProtect->isProtected())
+ // already unprotected (should not happen)!
+ return true;
+
+ // save the protection state before unprotect (for undo).
+ ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect));
+
+ if (!pDocProtect->verifyPassword(rPassword))
+ {
+ if (!bApi)
+ {
+ InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
+ aBox.Execute();
+ }
+ return false;
+ }
+
+ pDoc->SetDocProtection(NULL);
+ if (pDoc->IsUndoEnabled())
+ {
+ pProtectCopy->setProtected(false);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDocProtect(&rDocShell, pProtectCopy) );
+ // ownership of auto_ptr now transferred to ScUndoDocProtect.
+ }
+ }
+ else
+ {
+ // sheet protection
+
+ ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
+ if (!pTabProtect || !pTabProtect->isProtected())
+ // already unprotected (should not happen)!
+ return true;
+
+ // save the protection state before unprotect (for undo).
+ ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect));
+ if (!pTabProtect->verifyPassword(rPassword))
+ {
+ if (!bApi)
+ {
+ InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
+ aBox.Execute();
+ }
+ return false;
+ }
+
+ pDoc->SetTabProtection(nTab, NULL);
+ if (pDoc->IsUndoEnabled())
+ {
+ pProtectCopy->setProtected(false);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) );
+ // ownership of auto_ptr now transferred to ScUndoTabProtect.
+ }
+ }
+
+ rDocShell.PostPaintGridAll();
+ ScDocShellModificator aModificator( rDocShell );
+ aModificator.SetDocumentModified();
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ sal_Bool bUndo (pDoc->IsUndoEnabled());
+ ScEditableTester aTester( pDoc, rMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached
+ // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems
+ // here.
+
+ ScRange aMarkRange;
+ ScMarkData aMultiMark = rMark;
+ aMultiMark.SetMarking(false); // for MarkToMulti
+ aMultiMark.MarkToMulti();
+ aMultiMark.GetMultiMarkArea( aMarkRange );
+
+ if (bUndo)
+ {
+ SCTAB nStartTab = aMarkRange.aStart.Tab();
+ SCTAB nEndTab = aMarkRange.aEnd.Tab();
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
+ pDoc->CopyToDocument( aMarkRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&aMultiMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoClearItems( &rDocShell, aMultiMark, pUndoDoc, pWhich ) );
+ }
+
+ pDoc->ClearSelectionItems( pWhich, aMultiMark );
+
+ rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
+ aModificator.SetDocumentModified();
+
+ //! Bindings-Invalidate etc.?
+
+ return sal_True;
+}
+
+sal_Bool ScDocFunc::ChangeIndent( const ScMarkData& rMark, sal_Bool bIncrement, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ sal_Bool bUndo(pDoc->IsUndoEnabled());
+ ScEditableTester aTester( pDoc, rMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ ScRange aMarkRange;
+ rMark.GetMultiMarkArea( aMarkRange );
+
+ if (bUndo)
+ {
+ SCTAB nStartTab = aMarkRange.aStart.Tab();
+ SCTAB nTabCount = pDoc->GetTableCount();
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && rMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aMarkRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&rMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoIndent( &rDocShell, rMark, pUndoDoc, bIncrement ) );
+ }
+
+ pDoc->ChangeSelectionIndent( bIncrement, rMark );
+
+ rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( SID_ALIGNLEFT ); // ChangeIndent setzt auf links
+ pBindings->Invalidate( SID_ALIGNRIGHT );
+ pBindings->Invalidate( SID_ALIGNBLOCK );
+ pBindings->Invalidate( SID_ALIGNCENTERHOR );
+ // pseudo slots for Format menu
+ pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT );
+ pBindings->Invalidate( SID_ALIGN_ANY_LEFT );
+ pBindings->Invalidate( SID_ALIGN_ANY_HCENTER );
+ pBindings->Invalidate( SID_ALIGN_ANY_RIGHT );
+ pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED );
+ }
+
+ return sal_True;
+}
+
+sal_Bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
+ sal_uInt16 nFormatNo, sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ sal_Bool bSuccess = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, sal_True );
+ }
+
+ ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( pAutoFormat && nFormatNo < pAutoFormat->GetCount() && aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ sal_Bool bSize = (*pAutoFormat)[nFormatNo]->GetIncludeWidthHeight();
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ ScDocument* pUndoDoc = NULL;
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && aMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i, bSize, bSize );
+
+ ScRange aCopyRange = rRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aStart.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, false, pUndoDoc, &aMark );
+ if (bSize)
+ {
+ pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1,
+ IDF_NONE, false, pUndoDoc, &aMark );
+ pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1,
+ IDF_NONE, false, pUndoDoc, &aMark );
+ }
+ pDoc->BeginDrawUndo();
+ }
+
+ pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark );
+
+ if (bSize)
+ {
+ SCCOLROW nCols[2] = { nStartCol, nEndCol };
+ SCCOLROW nRows[2] = { nStartRow, nEndRow };
+
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (aMark.GetTableSelect(nTab))
+ {
+ SetWidthOrHeight( sal_True, 1,nCols, nTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, false, sal_True);
+ SetWidthOrHeight( false,1,nRows, nTab, SC_SIZE_VISOPT, 0, false, false);
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
+ PAINT_GRID | PAINT_LEFT | PAINT_TOP );
+ }
+ }
+ else
+ {
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (aMark.GetTableSelect(nTab))
+ {
+ sal_Bool bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, nTab,
+ nEndCol, nEndRow, nTab), false );
+ if (bAdj)
+ rDocShell.PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab,
+ PAINT_GRID | PAINT_LEFT );
+ else
+ rDocShell.PostPaint( nStartCol, nStartRow, nTab,
+ nEndCol, nEndRow, nTab, PAINT_GRID );
+ }
+ }
+
+ if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) );
+ }
+
+ aModificator.SetDocumentModified();
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
+ const ScTokenArray* pTokenArray, const String& rString, sal_Bool bApi, sal_Bool bEnglish,
+ const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ sal_Bool bSuccess = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ sal_Bool bUndo(pDoc->IsUndoEnabled());
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, sal_True );
+ }
+
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScDocument* pUndoDoc = NULL;
+
+ if (bUndo)
+ {
+ //! auch bei Undo selektierte Tabellen beruecksichtigen
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
+ pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, false, pUndoDoc );
+ }
+
+ // use TokenArray if given, string (and flags) otherwise
+ if ( pTokenArray )
+ {
+ pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
+ aMark, EMPTY_STRING, pTokenArray, eGrammar);
+ }
+ else if ( pDoc->IsImportingXML() )
+ {
+ ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar );
+ pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
+ aMark, EMPTY_STRING, pCode, eGrammar);
+ delete pCode;
+ pDoc->IncXMLImportedFormulaCount( rString.Len() );
+ }
+ else if (bEnglish)
+ {
+ ScCompiler aComp( pDoc, rRange.aStart);
+ aComp.SetGrammar(eGrammar);
+ ScTokenArray* pCode = aComp.CompileString( rString );
+ pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
+ aMark, EMPTY_STRING, pCode, eGrammar);
+ delete pCode;
+ }
+ else
+ pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
+ aMark, rString, NULL, eGrammar);
+
+ if (bUndo)
+ {
+ //! auch bei Undo selektierte Tabellen beruecksichtigen
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) );
+ }
+
+ // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen
+ rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID );
+ aModificator.SetDocumentModified();
+
+ bSuccess = sal_True;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
+ const ScTabOpParam& rParam, sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ sal_Bool bSuccess = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, sal_True );
+ }
+
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+ pDoc->SetDirty( rRange );
+ if ( bRecord )
+ {
+ //! auch bei Undo selektierte Tabellen beruecksichtigen
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
+ pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, false, pUndoDoc );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabOp( &rDocShell,
+ nStartCol, nStartRow, nStartTab,
+ nEndCol, nEndRow, nEndTab, pUndoDoc,
+ rParam.aRefFormulaCell,
+ rParam.aRefFormulaEnd,
+ rParam.aRefRowCell,
+ rParam.aRefColCell,
+ rParam.nMode) );
+ }
+ pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark);
+ rDocShell.PostPaintGridAll();
+ aModificator.SetDocumentModified();
+ bSuccess = sal_True;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+
+inline ScDirection DirFromFillDir( FillDir eDir )
+{
+ if (eDir==FILL_TO_BOTTOM)
+ return DIR_BOTTOM;
+ else if (eDir==FILL_TO_RIGHT)
+ return DIR_RIGHT;
+ else if (eDir==FILL_TO_TOP)
+ return DIR_TOP;
+ else // if (eDir==FILL_TO_LEFT)
+ return DIR_LEFT;
+}
+
+sal_Bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
+ FillDir eDir, sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ sal_Bool bSuccess = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, sal_True );
+ }
+
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScRange aSourceArea = rRange;
+ ScRange aDestArea = rRange;
+
+ SCCOLROW nCount = 0;
+ switch (eDir)
+ {
+ case FILL_TO_BOTTOM:
+ nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
+ aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() );
+ break;
+ case FILL_TO_RIGHT:
+ nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
+ aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() );
+ break;
+ case FILL_TO_TOP:
+ nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
+ aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() );
+ break;
+ case FILL_TO_LEFT:
+ nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
+ aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() );
+ break;
+ }
+
+ ScDocument* pUndoDoc = NULL;
+ if ( bRecord )
+ {
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCTAB nDestStartTab = aDestArea.aStart.Tab();
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nDestStartTab && aMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aDestArea;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, false, pUndoDoc, &aMark );
+ }
+
+ pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
+ aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
+ nCount, eDir, FILL_SIMPLE );
+ AdjustRowHeight(rRange);
+
+ if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
+ eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307) );
+ }
+
+ rDocShell.PostPaintGridAll();
+ aModificator.SetDocumentModified();
+
+ bSuccess = sal_True;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
+ FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
+ double fStart, double fStep, double fMax,
+ sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ sal_Bool bSuccess = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, sal_True );
+ }
+
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScRange aSourceArea = rRange;
+ ScRange aDestArea = rRange;
+
+ SCSIZE nCount = pDoc->GetEmptyLinesInBlock(
+ aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(),
+ aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(),
+ DirFromFillDir(eDir) );
+
+ // mindestens eine Zeile/Spalte als Quellbereich behalten:
+ SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ?
+ static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) :
+ static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 );
+ if ( nCount >= nTotLines )
+ nCount = nTotLines - 1;
+
+ switch (eDir)
+ {
+ case FILL_TO_BOTTOM:
+ aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) );
+ break;
+ case FILL_TO_RIGHT:
+ aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) );
+ break;
+ case FILL_TO_TOP:
+ aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) );
+ break;
+ case FILL_TO_LEFT:
+ aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) );
+ break;
+ }
+
+ ScDocument* pUndoDoc = NULL;
+ if ( bRecord )
+ {
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCTAB nDestStartTab = aDestArea.aStart.Tab();
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nDestStartTab && aMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ pDoc->CopyToDocument(
+ aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
+ aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
+ IDF_AUTOFILL, false, pUndoDoc, &aMark );
+ }
+
+ if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() &&
+ aDestArea.aStart.Row() <= aDestArea.aEnd.Row())
+ {
+ if ( fStart != MAXDOUBLE )
+ {
+ SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col();
+ SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row();
+ SCTAB nTab = aDestArea.aStart.Tab();
+ pDoc->SetValue( nValX, nValY, nTab, fStart );
+ }
+ pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
+ aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
+ nCount, eDir, eCmd, eDateCmd, fStep, fMax );
+ AdjustRowHeight(rRange);
+
+ rDocShell.PostPaintGridAll();
+ aModificator.SetDocumentModified();
+ }
+
+ if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
+ eDir, eCmd, eDateCmd, fStart, fStep, fMax) );
+ }
+
+ bSuccess = sal_True;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
+ FillDir eDir, sal_uLong nCount, sal_Bool bRecord, sal_Bool bApi )
+{
+ double fStep = 1.0;
+ double fMax = MAXDOUBLE;
+ return FillAuto( rRange, pTabMark, eDir, FILL_AUTO, FILL_DAY, nCount, fStep, fMax, bRecord, bApi );
+}
+
+sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, sal_uLong nCount, double fStep, double fMax, sal_Bool bRecord, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, sal_True );
+ }
+
+ ScRange aSourceArea = rRange;
+ ScRange aDestArea = rRange;
+
+
+ switch (eDir)
+ {
+ case FILL_TO_BOTTOM:
+ aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) );
+ break;
+ case FILL_TO_TOP:
+ if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Row() ))
+ {
+ OSL_FAIL("FillAuto: Row < 0");
+ nCount = aSourceArea.aStart.Row();
+ }
+ aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) );
+ break;
+ case FILL_TO_RIGHT:
+ aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) );
+ break;
+ case FILL_TO_LEFT:
+ if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Col() ))
+ {
+ OSL_FAIL("FillAuto: Col < 0");
+ nCount = aSourceArea.aStart.Col();
+ }
+ aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) );
+ break;
+ default:
+ OSL_FAIL("Falsche Richtung bei FillAuto");
+ break;
+ }
+
+ // Zellschutz testen
+ //! Quellbereich darf geschuetzt sein !!!
+ //! aber kein Matrixfragment enthalten !!!
+
+ ScEditableTester aTester( pDoc, aDestArea );
+ if ( !aTester.IsEditable() )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow,
+ nEndCol, nEndRow, aMark ) )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR);
+ return false;
+ }
+
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScDocument* pUndoDoc = NULL;
+ if ( bRecord )
+ {
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCTAB nDestStartTab = aDestArea.aStart.Tab();
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nDestStartTab && aMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ // do not clone note captions in undo document
+ pDoc->CopyToDocument(
+ aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
+ aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
+ IDF_AUTOFILL, false, pUndoDoc, &aMark );
+ }
+
+ pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
+ aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
+ nCount, eDir, eCmd, eDateCmd, fStep, fMax );
+
+ AdjustRowHeight(aDestArea);
+
+ if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
+ eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax) );
+ }
+
+ rDocShell.PostPaintGridAll();
+ aModificator.SetDocumentModified();
+
+ rRange = aDestArea; // Zielbereich zurueckgeben (zum Markieren)
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::MergeCells( const ScCellMergeOption& rOption, sal_Bool bContents, sal_Bool bRecord, sal_Bool bApi )
+{
+ using ::std::set;
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nStartCol = rOption.mnStartCol;
+ SCROW nStartRow = rOption.mnStartRow;
+ SCCOL nEndCol = rOption.mnEndCol;
+ SCROW nEndRow = rOption.mnEndRow;
+ if ((nStartCol == nEndCol && nStartRow == nEndRow) || rOption.maTabs.empty())
+ {
+ // Nothing to do. Bail out quick.
+ return true;
+ }
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ set<SCTAB>::const_iterator itrBeg = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
+ SCTAB nTab1 = *itrBeg, nTab2 = *rOption.maTabs.rbegin();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ ScEditableTester aTester( pDoc, *itr, nStartCol, nStartRow, nEndCol, nEndRow );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ if ( pDoc->HasAttrib( nStartCol, nStartRow, *itr, nEndCol, nEndRow, *itr,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ) )
+ {
+ // "Zusammenfassen nicht verschachteln !"
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0);
+ return false;
+ }
+ }
+
+ ScDocument* pUndoDoc = NULL;
+ bool bNeedContentsUndo = false;
+ for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ SCTAB nTab = *itr;
+ bool bNeedContents = bContents &&
+ ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
+ !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) );
+
+ if (bRecord)
+ {
+ // test if the range contains other notes which also implies that we need an undo document
+ bool bHasNotes = false;
+ for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() )
+ for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
+ bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0);
+
+ if (!pUndoDoc)
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo(pDoc, nTab1, nTab2);
+ }
+ // note captions are collected by drawing undo
+ pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
+ IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
+ if( bHasNotes )
+ pDoc->BeginDrawUndo();
+ }
+
+ if (bNeedContents)
+ pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
+ pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
+
+ if (rOption.mbCenter)
+ {
+ pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) );
+ pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY ) );
+ }
+
+ if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
+ rDocShell.PostPaint( nStartCol, nStartRow, nTab,
+ nEndCol, nEndRow, nTab, PAINT_GRID );
+ if (bNeedContents || rOption.mbCenter)
+ {
+ ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab);
+ pDoc->SetDirty(aRange);
+ }
+
+ bNeedContentsUndo |= bNeedContents;
+ }
+
+ if (pUndoDoc)
+ {
+ SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : NULL;
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoMerge(&rDocShell, rOption, bNeedContentsUndo, pUndoDoc, pDrawUndo) );
+ }
+
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_MERGE_ON );
+ pBindings->Invalidate( FID_MERGE_OFF );
+ pBindings->Invalidate( FID_MERGE_TOGGLE );
+ }
+
+ return sal_True;
+}
+
+sal_Bool ScDocFunc::UnmergeCells( const ScRange& rRange, sal_Bool bRecord, sal_Bool bApi )
+{
+ ScCellMergeOption aOption(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
+ SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
+ for (SCTAB i = nTab1; i <= nTab2; ++i)
+ aOption.maTabs.insert(i);
+
+ return UnmergeCells(aOption, bRecord, bApi);
+}
+
+bool ScDocFunc::UnmergeCells( const ScCellMergeOption& rOption, sal_Bool bRecord, sal_Bool bApi )
+{
+ using ::std::set;
+
+ if (rOption.maTabs.empty())
+ // Nothing to unmerge.
+ return true;
+
+ ScDocShellModificator aModificator( rDocShell );
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = false;
+
+ ScDocument* pUndoDoc = NULL;
+ bool bBeep = false;
+ for (set<SCTAB>::const_iterator itr = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
+ itr != itrEnd; ++itr)
+ {
+ SCTAB nTab = *itr;
+ ScRange aRange = rOption.getSingleRange(nTab);
+ if ( !pDoc->HasAttrib(aRange, HASATTR_MERGED) )
+ {
+ bBeep = true;
+ continue;
+ }
+
+ ScRange aExtended = aRange;
+ pDoc->ExtendMerge(aExtended);
+ ScRange aRefresh = aExtended;
+ pDoc->ExtendOverlapped(aRefresh);
+
+ if (bRecord)
+ {
+ if (!pUndoDoc)
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo(pDoc, *rOption.maTabs.begin(), *rOption.maTabs.rbegin());
+ }
+ pDoc->CopyToDocument(aExtended, IDF_ATTRIB, false, pUndoDoc);
+ }
+
+ const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetItemSet().Put( rDefAttr );
+ pDoc->ApplyPatternAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(), nTab,
+ aPattern );
+
+ pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
+ aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
+ SC_MF_HOR | SC_MF_VER );
+
+ pDoc->ExtendMerge( aRefresh, sal_True, false );
+
+ if ( !AdjustRowHeight( aExtended ) )
+ rDocShell.PostPaint( aExtended, PAINT_GRID );
+ }
+ if (bBeep && !bApi)
+ Sound::Beep();
+
+ if (bRecord)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRemoveMerge( &rDocShell, rOption, pUndoDoc ) );
+ }
+ aModificator.SetDocumentModified();
+
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+
+bool ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges )
+{
+ return SetNewRangeNames( new ScRangeName(rNewRanges) );
+}
+
+void ScDocFunc::ModifyAllRangeNames( const ScRangeName* pGlobal, const ScRangeName::TabNameCopyMap& rTabs )
+{
+ ScDocShellModificator aModificator(rDocShell);
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (pDoc->IsUndoEnabled())
+ {
+ ScRangeName* pOldGlobal = pDoc->GetRangeName();
+ ScRangeName::TabNameCopyMap aOldLocals;
+ pDoc->GetAllTabRangeNames(aOldLocals);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAllRangeNames(&rDocShell, pOldGlobal, pGlobal, aOldLocals, rTabs));
+ }
+
+ pDoc->CompileNameFormula(true);
+
+ // global names
+ pDoc->SetRangeName(new ScRangeName(*pGlobal));
+
+ // sheet-local names
+ pDoc->SetAllTabRangeNames(rTabs);
+
+ pDoc->CompileNameFormula(false);
+
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
+}
+
+bool ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, bool bModifyDoc ) // takes ownership of pNewRanges
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ DBG_ASSERT( pNewRanges, "pNewRanges is 0" );
+ ScDocument* pDoc = rDocShell.GetDocument();
+ sal_Bool bUndo(pDoc->IsUndoEnabled());
+
+ if (bUndo)
+ {
+ ScRangeName* pOld = pDoc->GetRangeName();
+ ScRangeName* pUndoRanges = new ScRangeName(*pOld);
+ ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges ) );
+ }
+
+ // #i55926# While loading XML, formula cells only have a single string token,
+ // so CompileNameFormula would never find any name (index) tokens, and would
+ // unnecessarily loop through all cells.
+ sal_Bool bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 );
+
+ if ( bCompile )
+ pDoc->CompileNameFormula( sal_True ); // CreateFormulaString
+ pDoc->SetRangeName( pNewRanges ); // takes ownership
+ if ( bCompile )
+ pDoc->CompileNameFormula( false ); // CompileFormulaString
+
+ if (bModifyDoc)
+ {
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint(SC_HINT_AREAS_CHANGED) );
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+
+void ScDocFunc::CreateOneName( ScRangeName& rList,
+ SCCOL nPosX, SCROW nPosY, SCTAB nTab,
+ SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
+ sal_Bool& rCancel, sal_Bool bApi )
+{
+ if (rCancel)
+ return;
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (!pDoc->HasValueData( nPosX, nPosY, nTab ))
+ {
+ String aName;
+ pDoc->GetString( nPosX, nPosY, nTab, aName );
+ ScRangeData::MakeValidName(aName);
+ if (aName.Len())
+ {
+ String aContent;
+ ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format( aContent, SCR_ABS_3D, pDoc );
+
+ bool bInsert = false;
+ ScRangeData* pOld = rList.findByName(aName);
+ if (pOld)
+ {
+ String aOldStr;
+ pOld->GetSymbol( aOldStr );
+ if (aOldStr != aContent)
+ {
+ if (bApi)
+ bInsert = sal_True; // per API nicht nachfragen
+ else
+ {
+ String aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE );
+
+ String aMessage = aTemplate.GetToken( 0, '#' );
+ aMessage += aName;
+ aMessage += aTemplate.GetToken( 1, '#' );
+
+ short nResult = QueryBox( rDocShell.GetActiveDialogParent(),
+ WinBits(WB_YES_NO_CANCEL | WB_DEF_YES),
+ aMessage ).Execute();
+ if ( nResult == RET_YES )
+ {
+ rList.erase(*pOld);
+ bInsert = true;
+ }
+ else if ( nResult == RET_CANCEL )
+ rCancel = sal_True;
+ }
+ }
+ }
+ else
+ bInsert = true;
+
+ if (bInsert)
+ {
+ ScRangeData* pData = new ScRangeData( pDoc, aName, aContent,
+ ScAddress( nPosX, nPosY, nTab));
+ if (!rList.insert(pData))
+ {
+ OSL_FAIL("nanu?");
+ delete pData;
+ }
+ }
+ }
+ }
+}
+
+sal_Bool ScDocFunc::CreateNames( const ScRange& rRange, sal_uInt16 nFlags, sal_Bool bApi )
+{
+ if (!nFlags)
+ return false; // war nix
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ sal_Bool bDone = false;
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+ DBG_ASSERT(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht");
+
+ sal_Bool bValid = sal_True;
+ if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) )
+ if ( nStartRow == nEndRow )
+ bValid = false;
+ if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) )
+ if ( nStartCol == nEndCol )
+ bValid = false;
+
+ if (bValid)
+ {
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScRangeName* pNames = pDoc->GetRangeName();
+ if (!pNames)
+ return false; // soll nicht sein
+ ScRangeName aNewRanges( *pNames );
+
+ sal_Bool bTop = ( ( nFlags & NAME_TOP ) != 0 );
+ sal_Bool bLeft = ( ( nFlags & NAME_LEFT ) != 0 );
+ sal_Bool bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 );
+ sal_Bool bRight = ( ( nFlags & NAME_RIGHT ) != 0 );
+
+ SCCOL nContX1 = nStartCol;
+ SCROW nContY1 = nStartRow;
+ SCCOL nContX2 = nEndCol;
+ SCROW nContY2 = nEndRow;
+
+ if ( bTop )
+ ++nContY1;
+ if ( bLeft )
+ ++nContX1;
+ if ( bBottom )
+ --nContY2;
+ if ( bRight )
+ --nContX2;
+
+ sal_Bool bCancel = false;
+ SCCOL i;
+ SCROW j;
+
+ if ( bTop )
+ for (i=nContX1; i<=nContX2; i++)
+ CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
+ if ( bLeft )
+ for (j=nContY1; j<=nContY2; j++)
+ CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
+ if ( bBottom )
+ for (i=nContX1; i<=nContX2; i++)
+ CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
+ if ( bRight )
+ for (j=nContY1; j<=nContY2; j++)
+ CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
+
+ if ( bTop && bLeft )
+ CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
+ if ( bTop && bRight )
+ CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
+ if ( bBottom && bLeft )
+ CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
+ if ( bBottom && bRight )
+ CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
+
+ bDone = ModifyRangeNames( aNewRanges );
+
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
+ }
+
+ return bDone;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+
+ sal_Bool bDone = false;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ const sal_Bool bRecord = pDoc->IsUndoEnabled();
+ SCTAB nTab = rStartPos.Tab();
+ ScDocument* pUndoDoc = NULL;
+
+ ScRangeName* pList = pDoc->GetRangeName();
+ sal_uInt16 nValidCount = 0;
+ ScRangeName::iterator itrBeg = pList->begin(), itrEnd = pList->end();
+ for (ScRangeName::iterator itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ const ScRangeData& r = *itr;
+ if (!r.HasType(RT_DATABASE) && !r.HasType(RT_SHARED))
+ ++nValidCount;
+ }
+
+ if (nValidCount)
+ {
+ SCCOL nStartCol = rStartPos.Col();
+ SCROW nStartRow = rStartPos.Row();
+ SCCOL nEndCol = nStartCol + 1;
+ SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1;
+
+ ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
+ if (aTester.IsEditable())
+ {
+ if (bRecord)
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab );
+ pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
+ IDF_ALL, false, pUndoDoc );
+
+ pDoc->BeginDrawUndo(); // wegen Hoehenanpassung
+ }
+
+ ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ];
+ sal_uInt16 j = 0;
+ for (ScRangeName::iterator itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ ScRangeData& r = *itr;
+ if (!r.HasType(RT_DATABASE) && !r.HasType(RT_SHARED))
+ ppSortArray[j++] = &r;
+ }
+#ifndef ICC
+ qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
+ &ScRangeData_QsortNameCompare );
+#else
+ qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
+ ICCQsortNameCompare );
+#endif
+ String aName;
+ rtl::OUStringBuffer aContent;
+ String aFormula;
+ SCROW nOutRow = nStartRow;
+ for (j=0; j<nValidCount; j++)
+ {
+ ScRangeData* pData = ppSortArray[j];
+ pData->GetName(aName);
+ // relative Referenzen Excel-konform auf die linke Spalte anpassen:
+ pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab ));
+ aFormula = '=';
+ aFormula += aContent;
+ pDoc->PutCell( nStartCol,nOutRow,nTab, new ScStringCell( aName ) );
+ pDoc->PutCell( nEndCol ,nOutRow,nTab, new ScStringCell( aFormula ) );
+ ++nOutRow;
+ }
+
+ delete [] ppSortArray;
+
+ if (bRecord)
+ {
+ ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRedoDoc->InitUndo( pDoc, nTab, nTab );
+ pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
+ IDF_ALL, false, pRedoDoc );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoListNames( &rDocShell,
+ ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ),
+ pUndoDoc, pRedoDoc ) );
+ }
+
+ if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab)))
+ rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID );
+
+ aModificator.SetDocumentModified();
+ bDone = sal_True;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ }
+ return bDone;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, sal_Bool bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rOldRange.aStart.Col();
+ SCROW nStartRow = rOldRange.aStart.Row();
+ SCTAB nTab = rOldRange.aStart.Tab();
+
+ sal_Bool bUndo(pDoc->IsUndoEnabled());
+
+ sal_Bool bRet = false;
+
+ String aFormula;
+ pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula );
+ if ( aFormula.GetChar(0) == '{' && aFormula.GetChar(aFormula.Len()-1) == '}' )
+ {
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX );
+ if (bUndo)
+ rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
+
+ aFormula.Erase(0,1);
+ aFormula.Erase(aFormula.Len()-1,1);
+
+ ScMarkData aMark;
+ aMark.SetMarkArea( rOldRange );
+ aMark.SelectTable( nTab, sal_True );
+ ScRange aNewRange( rOldRange.aStart, rNewEnd );
+
+ if ( DeleteContents( aMark, IDF_CONTENTS, sal_True, bApi ) )
+ {
+ // GRAM_PODF_A1 for API compatibility.
+ bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, false, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
+ if (!bRet)
+ {
+ // versuchen, alten Zustand wiederherzustellen
+ EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, false, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
+ }
+ }
+
+ if (bUndo)
+ rDocShell.GetUndoManager()->LeaveListAction();
+ }
+
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+sal_Bool ScDocFunc::InsertAreaLink( const String& rFile, const String& rFilter,
+ const String& rOptions, const String& rSource,
+ const ScRange& rDestRange, sal_uLong nRefresh,
+ sal_Bool bFitBlock, sal_Bool bApi )
+{
+ //! auch fuer ScViewFunc::InsertAreaLink benutzen!
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ sal_Bool bUndo (pDoc->IsUndoEnabled());
+
+ sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
+
+ // #i52120# if other area links exist at the same start position,
+ // remove them first (file format specifies only one link definition
+ // for a cell)
+
+ sal_uInt16 nLinkCount = pLinkManager->GetLinks().Count();
+ sal_uInt16 nRemoved = 0;
+ sal_uInt16 nLinkPos = 0;
+ while (nLinkPos<nLinkCount)
+ {
+ ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
+ if ( pBase->ISA(ScAreaLink) &&
+ static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart )
+ {
+ if ( bUndo )
+ {
+ if ( !nRemoved )
+ {
+ // group all remove and the insert action
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK );
+ rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
+ }
+
+ ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRemoveAreaLink( &rDocShell,
+ pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(),
+ pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) );
+ }
+ pLinkManager->Remove( pBase );
+ nLinkCount = pLinkManager->GetLinks().Count();
+ ++nRemoved;
+ }
+ else
+ ++nLinkPos;
+ }
+
+ String aFilterName = rFilter;
+ String aNewOptions = rOptions;
+ if (!aFilterName.Len())
+ ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, sal_True, !bApi );
+
+ // remove application prefix from filter name here, so the filter options
+ // aren't reset when the filter name is changed in ScAreaLink::DataChanged
+ ScDocumentLoader::RemoveAppPrefix( aFilterName );
+
+ ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName,
+ aNewOptions, rSource, rDestRange, nRefresh );
+ pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aFilterName, &rSource );
+
+ // Undo fuer den leeren Link
+
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell,
+ rFile, aFilterName, aNewOptions,
+ rSource, rDestRange, nRefresh ) );
+ if ( nRemoved )
+ rDocShell.GetUndoManager()->LeaveListAction(); // undo for link update is still separate
+ }
+
+ // Update hat sein eigenes Undo
+ if (pDoc->IsExecuteLinkEnabled())
+ {
+ pLink->SetDoInsert(bFitBlock); // beim ersten Update ggf. nichts einfuegen
+ pLink->Update(); // kein SetInCreate -> Update ausfuehren
+ }
+ pLink->SetDoInsert(sal_True); // Default = sal_True
+
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_LINKS );
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator
+
+ return sal_True;
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */