summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver Bolte <obo@openoffice.org>2009-09-09 07:31:32 +0000
committerOliver Bolte <obo@openoffice.org>2009-09-09 07:31:32 +0000
commitc24ab8def12f8a7a305e35d39c91976e345dd3b0 (patch)
tree019d5541f524e4f5691328f1d8b5f9f24e5a01a0
parentfbb3c82a81750cf7744e25af48a3372b8aafbd53 (diff)
CWS-TOOLING: integrate CWS koheimultirangecopy
2009-08-29 08:19:57 +0200 kohei r275558 : A bit of cleanup & comments. 2009-08-29 08:10:31 +0200 kohei r275557 : removed duplicated code block. 2009-08-29 07:30:33 +0200 kohei r275556 : #i104551# fixed it. 2009-08-28 17:23:28 +0200 kohei r275541 : #i104553# fixed a crash on pasting over existing data. This also fixes notes being destroyed as originally reported in the IZ entry. 2009-08-27 23:36:17 +0200 kohei r275510 : #i104550# fixed. All I had to do was to call MarkToSimple() before examining the geometry of the marked ranges. 2009-08-27 18:04:11 +0200 kohei r275501 : CWS-TOOLING: rebase CWS koheimultirangecopy to trunk@275331 (milestone: DEV300:m56) 2009-08-21 11:37:20 +0200 dr r275228 : #i10000# another wntmsci12 warning 2009-08-21 09:33:32 +0200 dr r275218 : #i10000# sunncc warnings 2009-08-20 20:01:15 +0200 kohei r275196 : Let's not initialize a variable with itself, which is not yet initialized. This was obviously a silly human error. 2009-08-05 23:24:16 +0200 kohei r274702 : correct error message on matrix fragment. 2009-08-05 20:00:12 +0200 kohei r274699 : removed header includes for indexmap.hxx. 2009-08-05 19:54:24 +0200 kohei r274698 : removed ScIndexMap entirely - we don't need this any more. 2009-08-05 19:53:01 +0200 kohei r274697 : Removed duplicated methods that use ScIndexMap. We should now use ScRangeData::IndexMap across the board. 2009-08-05 18:45:17 +0200 kohei r274695 : Refactored code to remove redundant ScDocument::CopyToClip method. 2009-07-21 18:03:54 +0200 kohei r274209 : #i25855# initial commit of the patch from ooo-build. It's buildable.
-rw-r--r--sc/inc/cell.hxx5
-rw-r--r--sc/inc/clipparam.hxx91
-rw-r--r--sc/inc/column.hxx5
-rw-r--r--sc/inc/document.hxx48
-rw-r--r--sc/inc/indexmap.hxx59
-rw-r--r--sc/inc/rangenam.hxx7
-rw-r--r--sc/inc/table.hxx5
-rw-r--r--sc/source/core/data/cell2.cxx8
-rw-r--r--sc/source/core/data/clipparam.cxx203
-rw-r--r--sc/source/core/data/column.cxx3
-rw-r--r--sc/source/core/data/documen2.cxx38
-rw-r--r--sc/source/core/data/documen3.cxx8
-rw-r--r--sc/source/core/data/documen8.cxx14
-rw-r--r--sc/source/core/data/document.cxx656
-rw-r--r--sc/source/core/data/makefile.mk2
-rw-r--r--sc/source/core/data/table1.cxx2
-rw-r--r--sc/source/core/data/table2.cxx10
-rw-r--r--sc/source/core/tool/indexmap.cxx80
-rw-r--r--sc/source/core/tool/makefile.mk1
-rw-r--r--sc/source/core/tool/rangenam.cxx13
-rw-r--r--sc/source/ui/docshell/arealink.cxx6
-rw-r--r--sc/source/ui/docshell/docfunc.cxx5
-rw-r--r--sc/source/ui/inc/cellsh.hxx3
-rw-r--r--sc/source/ui/inc/viewfunc.hxx5
-rw-r--r--sc/source/ui/navipi/content.cxx6
-rw-r--r--sc/source/ui/undo/undoblk.cxx6
-rw-r--r--sc/source/ui/unoobj/funcuno.cxx6
-rw-r--r--sc/source/ui/view/cellsh.cxx1
-rw-r--r--sc/source/ui/view/cellsh1.cxx84
-rw-r--r--sc/source/ui/view/tabcont.cxx4
-rw-r--r--sc/source/ui/view/tabvwsh4.cxx2
-rw-r--r--sc/source/ui/view/viewfun3.cxx382
-rw-r--r--sc/source/ui/view/viewfun5.cxx9
33 files changed, 1272 insertions, 505 deletions
diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx
index 1e9a8618800e..1f2bff35ce98 100644
--- a/sc/inc/cell.hxx
+++ b/sc/inc/cell.hxx
@@ -37,6 +37,7 @@
#include <tools/mempool.hxx>
#include <svtools/listener.hxx>
#include "global.hxx"
+#include "rangenam.hxx"
#include "formula/grammar.hxx"
#include "tokenarray.hxx"
#include "formularesult.hxx"
@@ -289,8 +290,6 @@ enum ScMatrixMode {
MM_FAKE = 3 // Interpret "as-if" matrix formula (legacy)
};
-class ScIndexMap;
-
class SC_DLLPUBLIC ScFormulaCell : public ScBaseCell, public SvtListener
{
private:
@@ -413,7 +412,7 @@ public:
void UpdateCompile( BOOL bForceIfNameInUse = FALSE );
BOOL IsRangeNameInUse(USHORT nIndex) const;
void FindRangeNamesInUse(std::set<USHORT>& rIndexes) const;
- void ReplaceRangeNamesInUse( const ScIndexMap& rMap );
+ void ReplaceRangeNamesInUse( const ScRangeData::IndexMap& rMap );
BOOL IsSubTotal() const { return bSubTotal; }
BOOL IsChanged() const { return bChanged; }
void ResetChanged() { bChanged = FALSE; }
diff --git a/sc/inc/clipparam.hxx b/sc/inc/clipparam.hxx
new file mode 100644
index 000000000000..896117bdef69
--- /dev/null
+++ b/sc/inc/clipparam.hxx
@@ -0,0 +1,91 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: document.hxx,v $
+ * $Revision: 1.115.36.9 $
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef SC_CLIPPARAM_HXX
+#define SC_CLIPPARAM_HXX
+
+#include "rangelst.hxx"
+#include "rangenam.hxx"
+
+#include <vector>
+
+/**
+ * This struct stores general clipboard parameters associated with a
+ * ScDocument instance created in clipboard mode.
+ */
+struct ScClipParam
+{
+ enum Direction { Unspecified, Column, Row };
+
+ ScRangeList maRanges;
+ Direction meDirection;
+ bool mbCutMode;
+
+ ScClipParam();
+ ScClipParam(const ScRange& rRange, bool bCutMode);
+ explicit ScClipParam(const ScClipParam& r);
+
+ bool isMultiRange() const;
+
+ /**
+ * Get the column size of a pasted range. Note that when the range is
+ * non-contiguous, we first compress all individual ranges into a single
+ * range, and the size of that compressed range is returned.
+ */
+ SCCOL getPasteColSize();
+
+ /**
+ * Same as the above method, but returns the row size of the compressed
+ * range.
+ */
+ SCROW getPasteRowSize();
+
+ /**
+ * Return a single range that encompasses all individual ranges.
+ */
+ ScRange getWholeRange() const;
+
+ void transpose();
+};
+
+// ============================================================================
+
+struct ScClipRangeNameData
+{
+ ScRangeData::IndexMap maRangeMap;
+ ::std::vector<ScRangeData*> mpRangeNames;
+ bool mbReplace;
+
+ ScClipRangeNameData();
+ ~ScClipRangeNameData();
+ void insert(sal_uInt16 nOldIndex, sal_uInt16 nNewIndex);
+};
+
+#endif
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 816a8ade4628..3f1fbfc1c88f 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -35,6 +35,7 @@
#include "global.hxx"
#include "compressedarray.hxx"
#include "address.hxx"
+#include "rangenam.hxx"
#include <tools/solar.h>
#include <set>
@@ -97,8 +98,6 @@ struct ColEntry
};
-class ScIndexMap;
-
class ScColumn
{
private:
@@ -297,7 +296,7 @@ public:
void SetTabNo(SCTAB nNewTab);
BOOL IsRangeNameInUse(SCROW nRow1, SCROW nRow2, USHORT nIndex) const;
void FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<USHORT>& rIndexes) const;
- void ReplaceRangeNamesInUse( SCROW nRow1, SCROW nRow2, const ScIndexMap& rMap );
+ void ReplaceRangeNamesInUse( SCROW nRow1, SCROW nRow2, const ScRangeData::IndexMap& rMap );
const SfxPoolItem* GetAttr( SCROW nRow, USHORT nWhich ) const;
const ScPatternAttr* GetPattern( SCROW nRow ) const;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 6711a2c974ad..67d36861d10a 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -136,6 +136,8 @@ class ScLookupCache;
struct ScLookupCacheMapImpl;
class SfxUndoManager;
class ScFormulaParserPool;
+struct ScClipParam;
+struct ScClipRangeNameData;
namespace com { namespace sun { namespace star {
namespace lang {
@@ -280,6 +282,7 @@ private:
ScFieldEditEngine* pCacheFieldEditEngine;
::std::auto_ptr<ScDocProtection> pDocProtection;
+ ::std::auto_ptr<ScClipParam> mpClipParam;
::std::auto_ptr<ScExternalRefManager> pExternalRefMgr;
@@ -306,7 +309,6 @@ private:
sal_uInt32 nRangeOverflowType; // used in (xml) loading for overflow warnings
- ScRange aClipRange;
ScRange aEmbedRange;
ScAddress aCurTextWidthCalcPos;
ScAddress aOnlineSpellPos; // within whole document
@@ -356,7 +358,6 @@ private:
BOOL bForcedFormulaPending;
BOOL bCalculatingFormulaTree;
BOOL bIsClip;
- BOOL bCutMode;
BOOL bIsUndo;
BOOL bIsVisible; // set from view ctor
@@ -962,12 +963,11 @@ public:
void DeleteAreaTab(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
SCTAB nTab, USHORT nDelFlag);
void DeleteAreaTab(const ScRange& rRange, USHORT nDelFlag);
- void CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
- BOOL bCut, ScDocument* pClipDoc, BOOL bAllTabs,
- const ScMarkData* pMarks = NULL,
- BOOL bKeepScenarioFlags = FALSE,
- BOOL bIncludeObjects = FALSE,
- BOOL bCloneNoteCaptions = TRUE);
+
+ void CopyToClip(const ScClipParam& rClipParam, ScDocument* pClipDoc,
+ const ScMarkData* pMarks = NULL, bool bAllTabs = false, bool bKeepScenarioFlags = false,
+ bool bIncludeObjects = false, bool bCloneNoteCaptions = true);
+
void CopyTabToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
SCTAB nTab, ScDocument* pClipDoc = NULL);
void CopyBlockFromClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
@@ -995,6 +995,12 @@ public:
BOOL bSkipAttrForEmpty = FALSE,
const ScRangeList * pDestRanges = NULL );
+ void CopyMultiRangeFromClip(const ScAddress& rDestPos, const ScMarkData& rMark,
+ sal_uInt16 nInsFlag, ScDocument* pClipDoc,
+ bool bResetCut = true, bool bAsLink = false,
+ bool bIncludeFiltered = true,
+ bool bSkipAttrForEmpty = false);
+
void GetClipArea(SCCOL& nClipX, SCROW& nClipY, BOOL bIncludeFiltered);
void GetClipStart(SCCOL& nClipX, SCROW& nClipY);
@@ -1004,6 +1010,9 @@ public:
SC_DLLPUBLIC void TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsLink );
+ ScClipParam& GetClipParam();
+ void SetClipParam(const ScClipParam& rParam);
+
void MixDocument( const ScRange& rRange, USHORT nFunction, BOOL bSkipEmpty,
ScDocument* pSrcDoc );
@@ -1701,6 +1710,23 @@ public:
SfxUndoManager* GetUndoManager();
private: // CLOOK-Impl-Methoden
+ /**
+ * Use this class as a locale variable to merge number formatter from
+ * another document, and set NULL pointer to pFormatExchangeList when
+ * done.
+ */
+ class NumFmtMergeHandler
+ {
+ public:
+ explicit NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc);
+ ~NumFmtMergeHandler();
+
+ private:
+ ScDocument* mpDoc;
+ };
+
+ void MergeNumberFormatter(ScDocument* pSrcDoc);
+
void ImplCreateOptions(); // bei Gelegenheit auf on-demand umstellen?
void ImplDeleteOptions();
@@ -1722,6 +1748,12 @@ private: // CLOOK-Impl-Methoden
void UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode,
const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
+ void CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs);
+ void CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames);
+ void UpdateRangeNamesInFormulas(
+ ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
+ SCCOL nXw, SCROW nYw);
+
BOOL HasPartOfMerged( const ScRange& rRange );
std::map< SCTAB, ScSortParam > mSheetSortParams;
diff --git a/sc/inc/indexmap.hxx b/sc/inc/indexmap.hxx
deleted file mode 100644
index 4db5deb78d4e..000000000000
--- a/sc/inc/indexmap.hxx
+++ /dev/null
@@ -1,59 +0,0 @@
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2008 by Sun Microsystems, Inc.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * $RCSfile: indexmap.hxx,v $
- * $Revision: 1.3 $
- *
- * 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.
- *
- ************************************************************************/
-
-#ifndef _SC_INDEXMAP_HXX
-#define _SC_INDEXMAP_HXX
-
-
-#include <tools/solar.h>
-
-
-class ScIndexMap
-{
- // not implemented
- ScIndexMap( const ScIndexMap& );
- ScIndexMap& operator=( const ScIndexMap& );
-
-private:
- USHORT* pMap;
- USHORT nCount;
-
-public:
- ScIndexMap( USHORT nEntries );
- ~ScIndexMap();
-
- void SetPair( USHORT nEntry, USHORT nIndex1, USHORT nIndex2 );
- /// returns nIndex2 if found, else nIndex1
- USHORT Find( USHORT nIndex1 ) const;
-};
-
-
-#endif // _SC_INDEXMAP_HXX
-
diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx
index 2c6f706ff403..9963cf65c895 100644
--- a/sc/inc/rangenam.hxx
+++ b/sc/inc/rangenam.hxx
@@ -37,6 +37,8 @@
#include "formula/grammar.hxx"
#include "scdllapi.h"
+#include <map>
+
//------------------------------------------------------------------------
class ScDocument;
@@ -65,7 +67,6 @@ typedef USHORT RangeType;
//------------------------------------------------------------------------
class ScTokenArray;
-class ScIndexMap;
class ScRangeData : public ScDataObject
{
@@ -87,6 +88,8 @@ private:
friend class ScRangeName;
ScRangeData( USHORT nIndex );
public:
+ typedef ::std::map<sal_uInt16, sal_uInt16> IndexMap;
+
SC_DLLPUBLIC ScRangeData( ScDocument* pDoc,
const String& rName,
const String& rSymbol,
@@ -152,7 +155,7 @@ public:
void ValidateTabRefs();
- void ReplaceRangeNamesInUse( const ScIndexMap& rMap );
+ void ReplaceRangeNamesInUse( const IndexMap& rMap );
static void MakeValidName( String& rName );
SC_DLLPUBLIC static BOOL IsNameValid( const String& rName, ScDocument* pDoc );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 1deaa8f334a6..9fda5d522fdc 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -71,7 +71,6 @@ class ScStyleSheet;
class ScTableLink;
class ScTableProtection;
class ScUserListData;
-class ScIndexMap;
struct RowInfo;
struct ScFunctionData;
struct ScLineFlags;
@@ -322,6 +321,8 @@ public:
void DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, USHORT nDelFlag);
void CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pTable,
BOOL bKeepScenarioFlags, BOOL bCloneNoteCaptions);
+ void CopyToClip(const ScRangeList& rRanges, ScTable* pTable,
+ bool bKeepScenarioFlags, bool bCloneNoteCaptions);
void CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCsCOL nDx, SCsROW nDy,
USHORT nInsFlag, BOOL bAsLink, BOOL bSkipAttrForEmpty, ScTable* pTable);
void StartListeningInArea( SCCOL nCol1, SCROW nRow1,
@@ -439,7 +440,7 @@ public:
void FindRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
std::set<USHORT>& rIndexes) const;
void ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
- const ScIndexMap& rMap );
+ const ScRangeData::IndexMap& rMap );
void Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
double nStepValue, double nMaxValue);
diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx
index a0e776458ca2..0b2a5a551ccb 100644
--- a/sc/source/core/data/cell2.cxx
+++ b/sc/source/core/data/cell2.cxx
@@ -53,7 +53,6 @@
#include "scmatrix.hxx"
#include "editutil.hxx"
#include "chgtrack.hxx"
-#include "indexmap.hxx"
#include "externalrefmgr.hxx"
using namespace formula;
@@ -1480,14 +1479,15 @@ void ScFormulaCell::FindRangeNamesInUse(std::set<USHORT>& rIndexes) const
lcl_FindRangeNamesInUse( rIndexes, pCode, pDocument->GetRangeName() );
}
-void ScFormulaCell::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
+void ScFormulaCell::ReplaceRangeNamesInUse( const ScRangeData::IndexMap& rMap )
{
for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
{
if( p->GetOpCode() == ocName )
{
- USHORT nIndex = p->GetIndex();
- USHORT nNewIndex = rMap.Find( nIndex );
+ sal_uInt16 nIndex = p->GetIndex();
+ ScRangeData::IndexMap::const_iterator itr = rMap.find(nIndex);
+ sal_uInt16 nNewIndex = itr == rMap.end() ? nIndex : itr->second;
if ( nIndex != nNewIndex )
{
p->SetIndex( nNewIndex );
diff --git a/sc/source/core/data/clipparam.cxx b/sc/source/core/data/clipparam.cxx
new file mode 100644
index 000000000000..b2ec555a0d5c
--- /dev/null
+++ b/sc/source/core/data/clipparam.cxx
@@ -0,0 +1,203 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: document.cxx,v $
+ * $Revision: 1.90.36.8 $
+ *
+ * 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 "clipparam.hxx"
+
+using ::std::vector;
+
+ScClipParam::ScClipParam() :
+ meDirection(Unspecified),
+ mbCutMode(false)
+{
+}
+
+ScClipParam::ScClipParam(const ScRange& rRange, bool bCutMode) :
+ meDirection(Unspecified),
+ mbCutMode(bCutMode)
+{
+ maRanges.Append(rRange);
+}
+
+ScClipParam::ScClipParam(const ScClipParam& r) :
+ maRanges(r.maRanges),
+ meDirection(r.meDirection),
+ mbCutMode(r.mbCutMode)
+{
+}
+
+bool ScClipParam::isMultiRange() const
+{
+ return maRanges.Count() > 1;
+}
+
+SCCOL ScClipParam::getPasteColSize()
+{
+ if (!maRanges.Count())
+ return 0;
+
+ switch (meDirection)
+ {
+ case ScClipParam::Column:
+ {
+ SCCOL nColSize = 0;
+ for (ScRangePtr p = maRanges.First(); p; p = maRanges.Next())
+ nColSize += p->aEnd.Col() - p->aStart.Col() + 1;
+ return nColSize;
+ }
+ case ScClipParam::Row:
+ {
+ // We assume that all ranges have identical column size.
+ const ScRange& rRange = *maRanges.First();
+ return rRange.aEnd.Col() - rRange.aStart.Col() + 1;
+ }
+ case ScClipParam::Unspecified:
+ default:
+ ;
+ }
+ return 0;
+}
+
+SCROW ScClipParam::getPasteRowSize()
+{
+ if (!maRanges.Count())
+ return 0;
+
+ switch (meDirection)
+ {
+ case ScClipParam::Column:
+ {
+ // We assume that all ranges have identical row size.
+ const ScRange& rRange = *maRanges.First();
+ return rRange.aEnd.Row() - rRange.aStart.Row() + 1;
+ }
+ case ScClipParam::Row:
+ {
+ SCROW nRowSize = 0;
+ for (ScRangePtr p = maRanges.First(); p; p = maRanges.Next())
+ nRowSize += p->aEnd.Row() - p->aStart.Row() + 1;
+ return nRowSize;
+ }
+ case ScClipParam::Unspecified:
+ default:
+ ;
+ }
+ return 0;
+}
+
+ScRange ScClipParam::getWholeRange() const
+{
+ ScRange aWhole;
+ bool bFirst = true;
+ ScRangeList aRanges = maRanges;
+ for (ScRange* p = aRanges.First(); p; p = aRanges.Next())
+ {
+ if (bFirst)
+ {
+ aWhole = *p;
+ bFirst = false;
+ continue;
+ }
+
+ if (aWhole.aStart.Col() > p->aStart.Col())
+ aWhole.aStart.SetCol(p->aStart.Col());
+
+ if (aWhole.aStart.Row() > p->aStart.Row())
+ aWhole.aStart.SetRow(p->aStart.Row());
+
+ if (aWhole.aEnd.Col() < p->aEnd.Col())
+ aWhole.aEnd.SetCol(p->aEnd.Col());
+
+ if (aWhole.aEnd.Row() < p->aEnd.Row())
+ aWhole.aEnd.SetRow(p->aEnd.Row());
+ }
+ return aWhole;
+}
+
+void ScClipParam::transpose()
+{
+ switch (meDirection)
+ {
+ case Column:
+ meDirection = ScClipParam::Row;
+ break;
+ case Row:
+ meDirection = ScClipParam::Column;
+ break;
+ case Unspecified:
+ default:
+ ;
+ }
+
+ ScRangeList aNewRanges;
+ if (maRanges.Count())
+ {
+ ScRange* p = maRanges.First();
+ SCCOL nColOrigin = p->aStart.Col();
+ SCROW nRowOrigin = p->aStart.Row();
+ for (; p; p = maRanges.Next())
+ {
+ SCCOL nColDelta = p->aStart.Col() - nColOrigin;
+ SCROW nRowDelta = p->aStart.Row() - nRowOrigin;
+ SCCOL nCol1 = 0;
+ SCCOL nCol2 = static_cast<SCCOL>(p->aEnd.Row() - p->aStart.Row());
+ SCROW nRow1 = 0;
+ SCROW nRow2 = static_cast<SCROW>(p->aEnd.Col() - p->aStart.Col());
+ nCol1 += static_cast<SCCOL>(nRowDelta);
+ nCol2 += static_cast<SCCOL>(nRowDelta);
+ nRow1 += static_cast<SCROW>(nColDelta);
+ nRow2 += static_cast<SCROW>(nColDelta);
+ ScRange aNew(nCol1, nRow1, p->aStart.Tab(), nCol2, nRow2, p->aStart.Tab());
+ aNewRanges.Append(aNew);
+ }
+ }
+ maRanges = aNewRanges;
+}
+
+// ============================================================================
+
+ScClipRangeNameData::ScClipRangeNameData() :
+ mbReplace(false)
+{
+}
+
+ScClipRangeNameData::~ScClipRangeNameData()
+{
+}
+
+void ScClipRangeNameData::insert(sal_uInt16 nOldIndex, sal_uInt16 nNewIndex)
+{
+ maRangeMap.insert(
+ ScRangeData::IndexMap::value_type(nOldIndex, nNewIndex));
+}
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 33b3404faec6..0afc4fb1347c 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -1874,7 +1874,7 @@ void ScColumn::FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<USHORT>& r
}
void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
- const ScIndexMap& rMap )
+ const ScRangeData::IndexMap& rMap )
{
if (pItems)
for (SCSIZE i = 0; i < nCount; i++)
@@ -1891,7 +1891,6 @@ void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
}
}
-
void ScColumn::SetDirtyVar()
{
for (SCSIZE i=0; i<nCount; i++)
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 4949254b7ab8..3404866446fe 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -86,7 +86,6 @@
#include "editutil.hxx"
#include "hints.hxx"
#include "dpobject.hxx"
-#include "indexmap.hxx"
#include "scrdata.hxx"
#include "poolhelp.hxx"
#include "unoreflist.hxx"
@@ -96,6 +95,7 @@
#include "externalrefmgr.hxx"
#include "tabprotection.hxx"
#include "formulaparserpool.hxx"
+#include "clipparam.hxx"
// pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
// dtor plus helpers are convenient.
@@ -155,6 +155,8 @@ ScDocument::ScDocument( ScDocumentMode eMode,
pScriptTypeData( NULL ),
pCacheFieldEditEngine( NULL ),
pDocProtection( NULL ),
+ mpClipParam( NULL),
+ pExternalRefMgr( NULL ),
pViewOptions( NULL ),
pDocOptions( NULL ),
pExtDocOptions( NULL ),
@@ -182,7 +184,6 @@ ScDocument::ScDocument( ScDocumentMode eMode,
bForcedFormulaPending( FALSE ),
bCalculatingFormulaTree( FALSE ),
bIsClip( eMode == SCDOCMODE_CLIP ),
- bCutMode( FALSE ),
bIsUndo( eMode == SCDOCMODE_UNDO ),
bIsVisible( FALSE ),
bIsEmbedded( FALSE ),
@@ -972,23 +973,18 @@ ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
bOldAutoCalcSrc = pSrcDoc->GetAutoCalc();
pSrcDoc->SetAutoCalc( TRUE ); // falls was berechnet werden muss
}
- SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
- SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
- if (pOtherFormatter && pOtherFormatter != pThisFormatter)
+
{
- SvNumberFormatterIndexTable* pExchangeList =
- pThisFormatter->MergeFormatter(*(pOtherFormatter));
- if (pExchangeList->Count() > 0)
- pFormatExchangeList = pExchangeList;
- }
- nDestPos = Min(nDestPos, (SCTAB)(GetTableCount() - 1));
- { // scope for bulk broadcast
- ScBulkBroadcast aBulkBroadcast( pBASM);
- pSrcDoc->pTab[nSrcPos]->CopyToTable(0, 0, MAXCOL, MAXROW,
- ( bResultsOnly ? IDF_ALL & ~IDF_FORMULA : IDF_ALL),
- FALSE, pTab[nDestPos] );
+ NumFmtMergeHandler aNumFmtMergeHdl(this, pSrcDoc);
+
+ nDestPos = Min(nDestPos, (SCTAB)(GetTableCount() - 1));
+ { // scope for bulk broadcast
+ ScBulkBroadcast aBulkBroadcast( pBASM);
+ pSrcDoc->pTab[nSrcPos]->CopyToTable(0, 0, MAXCOL, MAXROW,
+ ( bResultsOnly ? IDF_ALL & ~IDF_FORMULA : IDF_ALL),
+ FALSE, pTab[nDestPos] );
+ }
}
- pFormatExchangeList = NULL;
pTab[nDestPos]->SetTabNo(nDestPos);
if ( !bResultsOnly )
@@ -998,7 +994,7 @@ ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
// array containing range names which might need update of indices
ScRangeData** pSrcRangeNames = nSrcRangeNames ? new ScRangeData* [nSrcRangeNames] : NULL;
// the index mapping thereof
- ScIndexMap aSrcRangeMap( nSrcRangeNames );
+ ScRangeData::IndexMap aSrcRangeMap;
BOOL bRangeNameReplace = FALSE;
// find named ranges that are used in the source sheet
@@ -1023,7 +1019,8 @@ ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
USHORT nExistingIndex = pExistingData->GetIndex();
pSrcRangeNames[i] = NULL; // don't modify the named range
- aSrcRangeMap.SetPair( i, nOldIndex, nExistingIndex );
+ aSrcRangeMap.insert(
+ ScRangeData::IndexMap::value_type(nOldIndex, nExistingIndex));
bRangeNameReplace = TRUE;
bNamesLost = TRUE;
}
@@ -1043,7 +1040,8 @@ ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
pData->TransferTabRef( nSrcPos, nDestPos );
pSrcRangeNames[i] = pData;
USHORT nNewIndex = pData->GetIndex();
- aSrcRangeMap.SetPair( i, nOldIndex, nNewIndex );
+ aSrcRangeMap.insert(
+ ScRangeData::IndexMap::value_type(nOldIndex, nNewIndex));
if ( !bRangeNameReplace )
bRangeNameReplace = ( nOldIndex != nNewIndex );
}
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 7355fb5241ce..4ba4a225c21f 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -80,6 +80,7 @@
#include "listenercalls.hxx"
#include "tabprotection.hxx"
#include "formulaparserpool.hxx"
+#include "clipparam.hxx"
#include <memory>
@@ -854,7 +855,7 @@ void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode,
{
ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
if (pClipDoc)
- pClipDoc->bCutMode = FALSE;
+ pClipDoc->GetClipParam().mbCutMode = false;
}
}
}
@@ -864,7 +865,10 @@ void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDo
{
DBG_ASSERT(pClipDoc->bIsClip, "UpdateTranspose: kein Clip");
- ScRange aSource = pClipDoc->aClipRange; // Tab wird noch angepasst
+ ScRange aSource;
+ ScClipParam& rClipParam = GetClipParam();
+ if (rClipParam.maRanges.Count())
+ aSource = *rClipParam.maRanges.First();
ScAddress aDest = rDestPos;
SCTAB nClipTab = 0;
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index 620a8a6a3e13..64433a30297a 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -324,20 +324,8 @@ void ScDocument::ModifyStyleSheet( SfxStyleSheetBase& rStyleSheet,
void ScDocument::CopyStdStylesFrom( ScDocument* pSrcDoc )
{
// #b5017505# number format exchange list has to be handled here, too
-
- SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
- SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
- if (pOtherFormatter && pOtherFormatter != pThisFormatter)
- {
- SvNumberFormatterIndexTable* pExchangeList =
- pThisFormatter->MergeFormatter(*(pOtherFormatter));
- if (pExchangeList->Count() > 0)
- pFormatExchangeList = pExchangeList;
- }
-
+ NumFmtMergeHandler aNumFmtMergeHdl(this, pSrcDoc);
xPoolHelper->GetStylePool()->CopyStdStylesFrom( pSrcDoc->xPoolHelper->GetStylePool() );
-
- pFormatExchangeList = NULL;
}
//------------------------------------------------------------------------
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 0150593fa6ef..c74d804de352 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -84,7 +84,6 @@
#include "detdata.hxx"
#include "cell.hxx"
#include "dpobject.hxx"
-#include "indexmap.hxx"
#include "detfunc.hxx" // for UpdateAllComments
#include "scmod.hxx"
#include "dociter.hxx"
@@ -94,6 +93,9 @@
#include "postit.hxx"
#include "externalrefmgr.hxx"
#include "tabprotection.hxx"
+#include "clipparam.hxx"
+
+#include <map>
namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
@@ -1367,7 +1369,7 @@ void ScDocument::AddUndoTab( SCTAB nTab1, SCTAB nTab2, BOOL bColInfo, BOOL bRowI
void ScDocument::SetCutMode( BOOL bVal )
{
if (bIsClip)
- bCutMode = bVal;
+ GetClipParam().mbCutMode = bVal;
else
{
DBG_ERROR("SetCutMode without bIsClip");
@@ -1378,7 +1380,7 @@ void ScDocument::SetCutMode( BOOL bVal )
BOOL ScDocument::IsCutMode()
{
if (bIsClip)
- return bCutMode;
+ return GetClipParam().mbCutMode;
else
{
DBG_ERROR("IsCutMode ohne bIsClip");
@@ -1490,70 +1492,50 @@ void ScDocument::UndoToDocument(const ScRange& rRange,
pDestDoc->SetAutoCalc( bOldAutoCalc );
}
-
-void ScDocument::CopyToClip(SCCOL nCol1, SCROW nRow1,
- SCCOL nCol2, SCROW nRow2,
- BOOL bCut, ScDocument* pClipDoc,
- BOOL bAllTabs, const ScMarkData* pMarks,
- BOOL bKeepScenarioFlags, BOOL bIncludeObjects, BOOL bCloneNoteCaptions)
+void ScDocument::CopyToClip(const ScClipParam& rClipParam,
+ ScDocument* pClipDoc, const ScMarkData* pMarks,
+ bool bAllTabs, bool bKeepScenarioFlags, bool bIncludeObjects, bool bCloneNoteCaptions)
{
DBG_ASSERT( bAllTabs || pMarks, "CopyToClip: ScMarkData fehlt" );
- if (!bIsClip)
+ if (bIsClip)
+ return;
+
+ if (!pClipDoc)
{
- PutInOrder( nCol1, nCol2 );
- PutInOrder( nRow1, nRow2 );
- if (!pClipDoc)
- {
- DBG_ERROR("CopyToClip: no ClipDoc");
- pClipDoc = SC_MOD()->GetClipDoc();
- }
+ DBG_ERROR("CopyToClip: no ClipDoc");
+ pClipDoc = SC_MOD()->GetClipDoc();
+ }
- pClipDoc->aDocName = aDocName;
- pClipDoc->aClipRange = ScRange( nCol1,nRow1,0, nCol2,nRow2,0 );
- pClipDoc->ResetClip( this, pMarks );
- USHORT i;
- SCTAB j;
-
- std::set<USHORT> aUsedNames; // indexes of named ranges that are used in the copied cells
- for (j = 0; j <= MAXTAB; j++)
- if (pTab[j] && pClipDoc->pTab[j])
- if ( bAllTabs || !pMarks || pMarks->GetTableSelect(j) )
- pTab[j]->FindRangeNamesInUse( nCol1, nRow1, nCol2, nRow2, aUsedNames );
-
- pClipDoc->pRangeName->FreeAll();
- for (i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
- {
- USHORT nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
- bool bInUse = ( aUsedNames.find(nIndex) != aUsedNames.end() );
- if (bInUse)
- {
- ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
- if (!pClipDoc->pRangeName->Insert(pData))
- delete pData;
- else
- pData->SetIndex(nIndex);
- }
- }
- for (j = 0; j <= MAXTAB; j++)
- if (pTab[j] && pClipDoc->pTab[j])
- if ( bAllTabs || !pMarks || pMarks->GetTableSelect(j) )
- {
- pTab[j]->CopyToClip(nCol1, nRow1, nCol2, nRow2, pClipDoc->pTab[j], bKeepScenarioFlags, bCloneNoteCaptions);
+ pClipDoc->aDocName = aDocName;
+ pClipDoc->SetClipParam(rClipParam);
+ pClipDoc->ResetClip(this, pMarks);
- if ( pDrawLayer && bIncludeObjects )
- {
- // also copy drawing objects
+ ScRange aClipRange = rClipParam.getWholeRange();
+ CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, bAllTabs);
- Rectangle aObjRect = GetMMRect( nCol1, nRow1, nCol2, nRow2, j );
- pDrawLayer->CopyToClip( pClipDoc, j, aObjRect );
- }
- }
+ for (SCTAB i = 0; i <= MAXTAB; ++i)
+ {
+ if (!pTab[i] || !pClipDoc->pTab[i])
+ continue;
+
+ if (pMarks && !pMarks->GetTableSelect(i))
+ continue;
+
+ pTab[i]->CopyToClip(rClipParam.maRanges, pClipDoc->pTab[i], bKeepScenarioFlags, bCloneNoteCaptions);
- pClipDoc->bCutMode = bCut;
+ if (pDrawLayer && bIncludeObjects)
+ {
+ // also copy drawing objects
+ Rectangle aObjRect = GetMMRect(
+ aClipRange.aStart.Col(), aClipRange.aStart.Row(), aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i);
+ pDrawLayer->CopyToClip(pClipDoc, i, aObjRect);
+ }
}
-}
+ // Make sure to mark overlapped cells.
+ pClipDoc->ExtendMerge(aClipRange, true);
+}
void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
SCCOL nCol2, SCROW nRow2,
@@ -1569,14 +1551,16 @@ void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
pClipDoc = SC_MOD()->GetClipDoc();
}
+ ScClipParam& rClipParam = pClipDoc->GetClipParam();
pClipDoc->aDocName = aDocName;
- pClipDoc->aClipRange = ScRange( nCol1,nRow1,0, nCol2,nRow2,0 );
+ rClipParam.maRanges.RemoveAll();
+ rClipParam.maRanges.Append(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
pClipDoc->ResetClip( this, nTab );
if (pTab[nTab] && pClipDoc->pTab[nTab])
pTab[nTab]->CopyToClip(nCol1, nRow1, nCol2, nRow2, pClipDoc->pTab[nTab], FALSE, TRUE);
- pClipDoc->bCutMode = FALSE;
+ pClipDoc->GetClipParam().mbCutMode = false;
}
}
@@ -1606,6 +1590,7 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsL
// Daten
+ ScRange aClipRange = GetClipParam().getWholeRange();
if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) )
{
for (SCTAB i=0; i<=MAXTAB; i++)
@@ -1634,10 +1619,8 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsL
}
}
- pTransClip->aClipRange = ScRange( 0, 0, aClipRange.aStart.Tab(),
- static_cast<SCCOL>(aClipRange.aEnd.Row() - aClipRange.aStart.Row()),
- static_cast<SCROW>(aClipRange.aEnd.Col() - aClipRange.aStart.Col()),
- aClipRange.aEnd.Tab() );
+ pTransClip->SetClipParam(GetClipParam());
+ pTransClip->GetClipParam().transpose();
}
else
{
@@ -1646,9 +1629,184 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsL
// Dies passiert erst beim Einfuegen...
- bCutMode = FALSE;
+ GetClipParam().mbCutMode = false;
+}
+
+void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs)
+{
+ std::set<USHORT> aUsedNames; // indexes of named ranges that are used in the copied cells
+ for (SCTAB i = 0; i <= MAXTAB; ++i)
+ if (pTab[i] && pClipDoc->pTab[i])
+ if ( bAllTabs || !pMarks || pMarks->GetTableSelect(i) )
+ pTab[i]->FindRangeNamesInUse(
+ rClipRange.aStart.Col(), rClipRange.aStart.Row(),
+ rClipRange.aEnd.Col(), rClipRange.aEnd.Row(), aUsedNames);
+
+ pClipDoc->pRangeName->FreeAll();
+ for (USHORT i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
+ {
+ USHORT nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
+ bool bInUse = ( aUsedNames.find(nIndex) != aUsedNames.end() );
+ if (bInUse)
+ {
+ ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
+ if (!pClipDoc->pRangeName->Insert(pData))
+ delete pData;
+ else
+ pData->SetIndex(nIndex);
+ }
+ }
+}
+
+ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc) :
+ mpDoc(pDoc)
+{
+ mpDoc->MergeNumberFormatter(pSrcDoc);
+}
+
+ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
+{
+ mpDoc->pFormatExchangeList = NULL;
+}
+
+void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc)
+{
+ SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
+ SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
+ if (pOtherFormatter && pOtherFormatter != pThisFormatter)
+ {
+ SvNumberFormatterIndexTable* pExchangeList =
+ pThisFormatter->MergeFormatter(*(pOtherFormatter));
+ if (pExchangeList->Count() > 0)
+ pFormatExchangeList = pExchangeList;
+ }
+}
+
+void ScDocument::CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames)
+{
+ sal_uInt16 nClipRangeNameCount = pClipDoc->pRangeName->GetCount();
+ ScClipRangeNameData aClipRangeNames;
+
+ // array containing range names which might need update of indices
+ aClipRangeNames.mpRangeNames.resize(nClipRangeNameCount, NULL);
+
+ for (sal_uInt16 i = 0; i < nClipRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch
+ {
+ /* Copy only if the name doesn't exist in this document.
+ If it exists we use the already existing name instead,
+ another possibility could be to create new names if
+ documents differ.
+ A proper solution would ask the user how to proceed.
+ The adjustment of the indices in the formulas is done later.
+ */
+ ScRangeData* pClipRangeData = (*pClipDoc->pRangeName)[i];
+ USHORT k;
+ if ( pRangeName->SearchName( pClipRangeData->GetName(), k ) )
+ {
+ aClipRangeNames.mpRangeNames[i] = NULL; // range name not inserted
+ USHORT nOldIndex = pClipRangeData->GetIndex();
+ USHORT nNewIndex = ((*pRangeName)[k])->GetIndex();
+ aClipRangeNames.insert(nOldIndex, nNewIndex);
+ if ( !aClipRangeNames.mbReplace )
+ aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
+ }
+ else
+ {
+ ScRangeData* pData = new ScRangeData( *pClipRangeData );
+ pData->SetDocument(this);
+ if ( pRangeName->FindIndex( pData->GetIndex() ) )
+ pData->SetIndex(0); // need new index, done in Insert
+ if ( pRangeName->Insert( pData ) )
+ {
+ aClipRangeNames.mpRangeNames[i] = pData;
+ USHORT nOldIndex = pClipRangeData->GetIndex();
+ USHORT nNewIndex = pData->GetIndex();
+ aClipRangeNames.insert(nOldIndex, nNewIndex);
+ if ( !aClipRangeNames.mbReplace )
+ aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
+ }
+ else
+ { // must be an overflow
+ delete pData;
+ aClipRangeNames.mpRangeNames[i] = NULL;
+ aClipRangeNames.insert(pClipRangeData->GetIndex(), 0);
+ aClipRangeNames.mbReplace = true;
+ }
+ }
+ }
+ rRangeNames = aClipRangeNames;
+}
+
+void ScDocument::UpdateRangeNamesInFormulas(
+ ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
+ SCCOL nXw, SCROW nYw)
+{
+ // nXw and nYw are the extra width and height of the destination range
+ // extended due to presence of merged cell(s).
+
+ if (!rRangeNames.mbReplace)
+ return;
+
+ // first update all inserted named formulas if they contain other
+ // range names and used indices changed
+ size_t nRangeNameCount = rRangeNames.mpRangeNames.size();
+ for (size_t i = 0; i < nRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch
+ {
+ if ( rRangeNames.mpRangeNames[i] )
+ rRangeNames.mpRangeNames[i]->ReplaceRangeNamesInUse(rRangeNames.maRangeMap);
+ }
+ // then update the formulas, they might need just the updated range names
+ for (ULONG nRange = 0; nRange < rDestRanges.Count(); ++nRange)
+ {
+ const ScRange* pRange = rDestRanges.GetObject( nRange);
+ SCCOL nCol1 = pRange->aStart.Col();
+ SCROW nRow1 = pRange->aStart.Row();
+ SCCOL nCol2 = pRange->aEnd.Col();
+ SCROW nRow2 = pRange->aEnd.Row();
+
+ SCCOL nC1 = nCol1;
+ SCROW nR1 = nRow1;
+ SCCOL nC2 = nC1 + nXw;
+ if (nC2 > nCol2)
+ nC2 = nCol2;
+ SCROW nR2 = nR1 + nYw;
+ if (nR2 > nRow2)
+ nR2 = nRow2;
+ do
+ {
+ do
+ {
+ for (SCTAB k = 0; k <= MAXTAB; k++)
+ {
+ if ( pTab[k] && rMark.GetTableSelect(k) )
+ pTab[k]->ReplaceRangeNamesInUse(nC1, nR1,
+ nC2, nR2, rRangeNames.maRangeMap);
+ }
+ nC1 = nC2 + 1;
+ nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
+ } while (nC1 <= nCol2);
+ nC1 = nCol1;
+ nC2 = nC1 + nXw;
+ if (nC2 > nCol2)
+ nC2 = nCol2;
+ nR1 = nR2 + 1;
+ nR2 = Min((SCROW)(nR1 + nYw), nRow2);
+ } while (nR1 <= nRow2);
+ }
}
+ScClipParam& ScDocument::GetClipParam()
+{
+ if (!mpClipParam.get())
+ mpClipParam.reset(new ScClipParam);
+
+ return *mpClipParam;
+}
+
+void ScDocument::SetClipParam(const ScClipParam& rParam)
+{
+ mpClipParam.reset(new ScClipParam(rParam));
+}
BOOL ScDocument::IsClipboardSource() const
{
@@ -1748,7 +1906,7 @@ void ScDocument::CopyBlockFromClip( SCCOL nCol1, SCROW nRow1,
&& ppClipTab[nClipTab + nFollow + 1] )
++nFollow;
- if ( pCBFCP->pClipDoc->bCutMode )
+ if ( pCBFCP->pClipDoc->GetClipParam().mbCutMode )
{
BOOL bOldInserting = IsInsertingFromOtherDoc();
SetInsertingFromOtherDoc( TRUE);
@@ -1790,7 +1948,9 @@ void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1, SCROW nRow1,
pCBFCP->pClipDoc->GetRowFlagsArray( nFlagTab);
SCROW nSourceRow = rClipStartRow;
- SCROW nSourceEnd = pCBFCP->pClipDoc->aClipRange.aEnd.Row();
+ SCROW nSourceEnd = 0;
+ if (pCBFCP->pClipDoc->GetClipParam().maRanges.Count())
+ nSourceEnd = pCBFCP->pClipDoc->GetClipParam().maRanges.First()->aEnd.Row();
SCROW nDestRow = nRow1;
while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 )
@@ -1836,67 +1996,11 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
BOOL bOldAutoCalc = GetAutoCalc();
SetAutoCalc( FALSE ); // avoid multiple recalculations
- SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
- SvNumberFormatter* pOtherFormatter = pClipDoc->xPoolHelper->GetFormTable();
- if (pOtherFormatter && pOtherFormatter != pThisFormatter)
- {
- SvNumberFormatterIndexTable* pExchangeList =
- pThisFormatter->MergeFormatter(*(pOtherFormatter));
- if (pExchangeList->Count() > 0)
- pFormatExchangeList = pExchangeList;
- }
+ NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
- USHORT nClipRangeNames = pClipDoc->pRangeName->GetCount();
- // array containing range names which might need update of indices
- ScRangeData** pClipRangeNames = nClipRangeNames ? new ScRangeData* [nClipRangeNames] : NULL;
- // the index mapping thereof
- ScIndexMap aClipRangeMap( nClipRangeNames );
- BOOL bRangeNameReplace = FALSE;
+ ScClipRangeNameData aClipRangeNames;
+ CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
- for (USHORT i = 0; i < nClipRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
- {
- /* Copy only if the name doesn't exist in this document.
- If it exists we use the already existing name instead,
- another possibility could be to create new names if
- documents differ.
- A proper solution would ask the user how to proceed.
- The adjustment of the indices in the formulas is done later.
- */
- ScRangeData* pClipRangeData = (*pClipDoc->pRangeName)[i];
- USHORT k;
- if ( pRangeName->SearchName( pClipRangeData->GetName(), k ) )
- {
- pClipRangeNames[i] = NULL; // range name not inserted
- USHORT nOldIndex = pClipRangeData->GetIndex();
- USHORT nNewIndex = ((*pRangeName)[k])->GetIndex();
- aClipRangeMap.SetPair( i, nOldIndex, nNewIndex );
- if ( !bRangeNameReplace )
- bRangeNameReplace = ( nOldIndex != nNewIndex );
- }
- else
- {
- ScRangeData* pData = new ScRangeData( *pClipRangeData );
- pData->SetDocument(this);
- if ( pRangeName->FindIndex( pData->GetIndex() ) )
- pData->SetIndex(0); // need new index, done in Insert
- if ( pRangeName->Insert( pData ) )
- {
- pClipRangeNames[i] = pData;
- USHORT nOldIndex = pClipRangeData->GetIndex();
- USHORT nNewIndex = pData->GetIndex();
- aClipRangeMap.SetPair( i, nOldIndex, nNewIndex );
- if ( !bRangeNameReplace )
- bRangeNameReplace = ( nOldIndex != nNewIndex );
- }
- else
- { // must be an overflow
- delete pData;
- pClipRangeNames[i] = NULL;
- aClipRangeMap.SetPair( i, pClipRangeData->GetIndex(), 0 );
- bRangeNameReplace = TRUE;
- }
- }
- }
SCCOL nAllCol1 = rDestRange.aStart.Col();
SCROW nAllRow1 = rDestRange.aStart.Row();
SCCOL nAllCol2 = rDestRange.aEnd.Col();
@@ -1904,17 +2008,18 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
SCCOL nXw = 0;
SCROW nYw = 0;
+ ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) // find largest merge overlap
if (pClipDoc->pTab[nTab]) // all sheets of the clipboard content
{
- SCCOL nThisEndX = pClipDoc->aClipRange.aEnd.Col();
- SCROW nThisEndY = pClipDoc->aClipRange.aEnd.Row();
- pClipDoc->ExtendMerge( pClipDoc->aClipRange.aStart.Col(),
- pClipDoc->aClipRange.aStart.Row(),
+ SCCOL nThisEndX = aClipRange.aEnd.Col();
+ SCROW nThisEndY = aClipRange.aEnd.Row();
+ pClipDoc->ExtendMerge( aClipRange.aStart.Col(),
+ aClipRange.aStart.Row(),
nThisEndX, nThisEndY, nTab );
// only extra value from ExtendMerge
- nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - pClipDoc->aClipRange.aEnd.Col() );
- nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - pClipDoc->aClipRange.aEnd.Row() );
+ nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() );
+ nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() );
if ( nThisEndX > nXw )
nXw = nThisEndX;
if ( nThisEndY > nYw )
@@ -1981,10 +2086,10 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
if (bDoDouble)
ScColumn::bDoubleAlloc = TRUE;
- SCCOL nClipStartCol = pClipDoc->aClipRange.aStart.Col();
- SCROW nClipStartRow = pClipDoc->aClipRange.aStart.Row();
+ SCCOL nClipStartCol = aClipRange.aStart.Col();
+ SCROW nClipStartRow = aClipRange.aStart.Row();
// WaE: commented because unused: SCCOL nClipEndCol = pClipDoc->aClipRange.aEnd.Col();
- SCROW nClipEndRow = pClipDoc->aClipRange.aEnd.Row();
+ SCROW nClipEndRow = aClipRange.aEnd.Row();
for (ULONG nRange = 0; nRange < pDestRanges->Count(); ++nRange)
{
const ScRange* pRange = pDestRanges->GetObject( nRange);
@@ -2035,7 +2140,7 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
} while (nC1 <= nCol2);
if (nClipStartRow > nClipEndRow)
- nClipStartRow = pClipDoc->aClipRange.aStart.Row();
+ nClipStartRow = aClipRange.aStart.Row();
nC1 = nCol1;
nC2 = nC1 + nXw;
if (nC2 > nCol2)
@@ -2052,75 +2157,168 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
pTab[k]->DecRecalcLevel();
bInsertingFromOtherDoc = FALSE;
- pFormatExchangeList = NULL;
- if ( bRangeNameReplace )
- {
- // first update all inserted named formulas if they contain other
- // range names and used indices changed
- for (USHORT i = 0; i < nClipRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
- {
- if ( pClipRangeNames[i] )
- pClipRangeNames[i]->ReplaceRangeNamesInUse( aClipRangeMap );
- }
- // then update the formulas, they might need the just updated range names
- for (ULONG nRange = 0; nRange < pDestRanges->Count(); ++nRange)
- {
- const ScRange* pRange = pDestRanges->GetObject( nRange);
- SCCOL nCol1 = pRange->aStart.Col();
- SCROW nRow1 = pRange->aStart.Row();
- SCCOL nCol2 = pRange->aEnd.Col();
- SCROW nRow2 = pRange->aEnd.Row();
-
- SCCOL nC1 = nCol1;
- SCROW nR1 = nRow1;
- SCCOL nC2 = nC1 + nXw;
- if (nC2 > nCol2)
- nC2 = nCol2;
- SCROW nR2 = nR1 + nYw;
- if (nR2 > nRow2)
- nR2 = nRow2;
- do
- {
- do
- {
- for (SCTAB k = 0; k <= MAXTAB; k++)
- {
- if ( pTab[k] && rMark.GetTableSelect(k) )
- pTab[k]->ReplaceRangeNamesInUse(nC1, nR1,
- nC2, nR2, aClipRangeMap );
- }
- nC1 = nC2 + 1;
- nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
- } while (nC1 <= nCol2);
- nC1 = nCol1;
- nC2 = nC1 + nXw;
- if (nC2 > nCol2)
- nC2 = nCol2;
- nR1 = nR2 + 1;
- nR2 = Min((SCROW)(nR1 + nYw), nRow2);
- } while (nR1 <= nRow2);
- }
- }
- if ( pClipRangeNames )
- delete [] pClipRangeNames;
+
+ UpdateRangeNamesInFormulas(aClipRangeNames, *pDestRanges, rMark, nXw, nYw);
+
// Listener aufbauen nachdem alles inserted wurde
StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
// nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
if (bResetCut)
- pClipDoc->bCutMode = FALSE;
+ pClipDoc->GetClipParam().mbCutMode = false;
SetAutoCalc( bOldAutoCalc );
}
}
}
+static SCROW lcl_getLastNonFilteredRow(
+ const ScBitMaskCompressedArray<SCROW, BYTE>& rFlags, SCROW nBegRow, SCROW nEndRow,
+ SCROW nRowCount)
+{
+ SCROW nFilteredRow = rFlags.GetFirstForCondition(
+ nBegRow, nEndRow, CR_FILTERED, CR_FILTERED);
+
+ SCROW nRow = nFilteredRow - 1;
+ if (nRow - nBegRow + 1 > nRowCount)
+ // make sure the row range stays within the data size.
+ nRow = nBegRow + nRowCount - 1;
+
+ return nRow;
+}
+
+void ScDocument::CopyMultiRangeFromClip(
+ const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc,
+ bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty)
+{
+ if (bIsClip)
+ return;
+
+ if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
+ // There is nothing in the clip doc to copy.
+ return;
+
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // avoid multiple recalculations
+
+ NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
+
+ ScClipRangeNameData aClipRangeNames;
+ CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
+
+ SCCOL nCol1 = rDestPos.Col();
+ SCROW nRow1 = rDestPos.Row();
+ ScClipParam& rClipParam = pClipDoc->GetClipParam();
+
+ ScCopyBlockFromClipParams aCBFCP;
+ aCBFCP.pRefUndoDoc = NULL;
+ aCBFCP.pClipDoc = pClipDoc;
+ aCBFCP.nInsFlag = nInsFlag;
+ aCBFCP.bAsLink = bAsLink;
+ aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty;
+ aCBFCP.nTabStart = MAXTAB;
+ aCBFCP.nTabEnd = 0;
+
+ for (SCTAB j = 0; j <= MAXTAB; ++j)
+ {
+ if (pTab[j] && rMark.GetTableSelect(j))
+ {
+ if ( j < aCBFCP.nTabStart )
+ aCBFCP.nTabStart = j;
+ aCBFCP.nTabEnd = j;
+ pTab[j]->IncRecalcLevel();
+ }
+ }
+
+ ScRange aDestRange;
+ rMark.GetMarkArea(aDestRange);
+ SCROW nLastMarkedRow = aDestRange.aEnd.Row();
+
+ bInsertingFromOtherDoc = TRUE; // kein Broadcast/Listener aufbauen bei Insert
+
+ SCROW nBegRow = nRow1;
+ sal_uInt16 nDelFlag = IDF_CONTENTS;
+ const ScBitMaskCompressedArray<SCROW, BYTE>& rFlags = GetRowFlagsArray(aCBFCP.nTabStart);
+
+ for (ScRange* p = rClipParam.maRanges.First(); p; p = rClipParam.maRanges.Next())
+ {
+ // The begin row must not be filtered.
+
+ SCROW nRowCount = p->aEnd.Row() - p->aStart.Row() + 1;
+
+ SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col());
+ SCsROW nDy = static_cast<SCsROW>(nBegRow - p->aStart.Row());
+ SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col();
+
+ SCROW nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
+
+ if (!bSkipAttrForEmpty)
+ DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
+
+ CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP);
+ nRowCount -= nEndRow - nBegRow + 1;
+
+ while (nRowCount > 0)
+ {
+ // Get the first non-filtered row.
+ SCROW nNonFilteredRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
+ if (nNonFilteredRow > nLastMarkedRow)
+ return;
+
+ SCROW nRowsSkipped = nNonFilteredRow - nEndRow - 1;
+ nDy += nRowsSkipped;
+
+ nBegRow = nNonFilteredRow;
+ nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
+
+ if (!bSkipAttrForEmpty)
+ DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
+
+ CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP);
+ nRowCount -= nEndRow - nBegRow + 1;
+ }
+
+ if (rClipParam.meDirection == ScClipParam::Row)
+ // Begin row for the next range being pasted.
+ nBegRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
+ else
+ nBegRow = nRow1;
+
+ if (rClipParam.meDirection == ScClipParam::Column)
+ nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
+ }
+
+ for (SCTAB i = 0; i <= MAXTAB; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ pTab[i]->DecRecalcLevel();
+
+ bInsertingFromOtherDoc = FALSE;
+
+ ScRangeList aRanges;
+ aRanges.Append(aDestRange);
+ SCCOL nCols = aDestRange.aEnd.Col() - aDestRange.aStart.Col() + 1;
+ SCROW nRows = aDestRange.aEnd.Row() - aDestRange.aStart.Row() + 1;
+ UpdateRangeNamesInFormulas(aClipRangeNames, aRanges, rMark, nCols-1, nRows-1);
+
+ // Listener aufbauen nachdem alles inserted wurde
+ StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
+ aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
+ // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
+ BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
+ aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
+
+ if (bResetCut)
+ pClipDoc->GetClipParam().mbCutMode = false;
+ SetAutoCalc( bOldAutoCalc );
+}
void ScDocument::SetClipArea( const ScRange& rArea, BOOL bCut )
{
if (bIsClip)
{
- aClipRange = rArea;
- bCutMode = bCut;
+ ScClipParam& rClipParam = GetClipParam();
+ rClipParam.maRanges.RemoveAll();
+ rClipParam.maRanges.Append(rArea);
+ rClipParam.mbCutMode = bCut;
}
else
{
@@ -2131,33 +2329,53 @@ void ScDocument::SetClipArea( const ScRange& rArea, BOOL bCut )
void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, BOOL bIncludeFiltered)
{
- if (bIsClip)
+ if (!bIsClip)
{
- nClipX = aClipRange.aEnd.Col() - aClipRange.aStart.Col();
+ DBG_ERROR("GetClipArea: kein Clip");
+ return;
+ }
- if ( bIncludeFiltered )
- nClipY = aClipRange.aEnd.Row() - aClipRange.aStart.Row();
- else
- {
- // count non-filtered rows
- // count on first used table in clipboard
- SCTAB nCountTab = 0;
- while ( nCountTab < MAXTAB && !pTab[nCountTab] )
- ++nCountTab;
-
- SCROW nResult = GetRowFlagsArray( nCountTab).CountForCondition(
- aClipRange.aStart.Row(), aClipRange.aEnd.Row(),
- CR_FILTERED, 0);
-
- if ( nResult > 0 )
- nClipY = nResult - 1;
- else
- nClipY = 0; // always return at least 1 row
- }
+ ScRangeList& rClipRanges = GetClipParam().maRanges;
+ if (!rClipRanges.Count())
+ // No clip range. Bail out.
+ return;
+
+ ScRangePtr p = rClipRanges.First();
+ SCCOL nStartCol = p->aStart.Col();
+ SCCOL nEndCol = p->aEnd.Col();
+ SCROW nStartRow = p->aStart.Row();
+ SCROW nEndRow = p->aEnd.Row();
+ for (p = rClipRanges.Next(); p; p = rClipRanges.Next())
+ {
+ if (p->aStart.Col() < nStartCol)
+ nStartCol = p->aStart.Col();
+ if (p->aStart.Row() < nStartRow)
+ nStartRow = p->aStart.Row();
+ if (p->aEnd.Col() > nEndCol)
+ nEndCol = p->aEnd.Col();
+ if (p->aEnd.Row() < nEndRow)
+ nEndRow = p->aEnd.Row();
}
+
+ nClipX = nEndCol - nStartCol;
+
+ if ( bIncludeFiltered )
+ nClipY = nEndRow - nStartRow;
else
{
- DBG_ERROR("GetClipArea: kein Clip");
+ // count non-filtered rows
+ // count on first used table in clipboard
+ SCTAB nCountTab = 0;
+ while ( nCountTab < MAXTAB && !pTab[nCountTab] )
+ ++nCountTab;
+
+ SCROW nResult = GetRowFlagsArray( nCountTab).CountForCondition(
+ nStartRow, nEndRow, CR_FILTERED, 0);
+
+ if ( nResult > 0 )
+ nClipY = nResult - 1;
+ else
+ nClipY = 0; // always return at least 1 row
}
}
@@ -2166,8 +2384,12 @@ void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY)
{
if (bIsClip)
{
- nClipX = aClipRange.aStart.Col();
- nClipY = aClipRange.aStart.Row();
+ ScRangeList& rClipRanges = GetClipParam().maRanges;
+ if (rClipRanges.Count())
+ {
+ nClipX = rClipRanges.First()->aStart.Col();
+ nClipY = rClipRanges.First()->aStart.Row();
+ }
}
else
{
@@ -2183,8 +2405,12 @@ BOOL ScDocument::HasClipFilteredRows()
while ( nCountTab < MAXTAB && !pTab[nCountTab] )
++nCountTab;
- return GetRowFlagsArray( nCountTab).HasCondition( aClipRange.aStart.Row(),
- aClipRange.aEnd.Row(), CR_FILTERED, CR_FILTERED);
+ ScRangeList& rClipRanges = GetClipParam().maRanges;
+ if (!rClipRanges.Count())
+ return false;
+
+ return GetRowFlagsArray( nCountTab).HasCondition( rClipRanges.First()->aStart.Row(),
+ rClipRanges.First()->aEnd.Row(), CR_FILTERED, CR_FILTERED);
}
diff --git a/sc/source/core/data/makefile.mk b/sc/source/core/data/makefile.mk
index 29618da6630b..d2c700c5f95d 100644
--- a/sc/source/core/data/makefile.mk
+++ b/sc/source/core/data/makefile.mk
@@ -56,6 +56,7 @@ SLOFILES = \
$(SLO)$/bcaslot.obj \
$(SLO)$/cell.obj \
$(SLO)$/cell2.obj \
+ $(SLO)$/clipparam.obj \
$(SLO)$/column.obj \
$(SLO)$/column2.obj \
$(SLO)$/column3.obj \
@@ -117,6 +118,7 @@ EXCEPTIONSFILES= \
$(SLO)$/autonamecache.obj \
$(SLO)$/bcaslot.obj \
$(SLO)$/cell2.obj \
+ $(SLO)$/clipparam.obj \
$(SLO)$/column.obj \
$(SLO)$/column3.obj \
$(SLO)$/documen2.obj \
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 1f1d82023f45..10197e3a9ad5 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -1327,7 +1327,7 @@ void ScTable::FindRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW n
void ScTable::ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1,
SCCOL nCol2, SCROW nRow2,
- const ScIndexMap& rMap )
+ const ScRangeData::IndexMap& rMap )
{
for (SCCOL i = nCol1; i <= nCol2 && (ValidCol(i)); i++)
{
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 104fb46b4495..c8a25fbe0ec1 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -371,6 +371,16 @@ void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
}
}
+void ScTable::CopyToClip(const ScRangeList& rRanges, ScTable* pTable,
+ bool bKeepScenarioFlags, bool bCloneNoteCaptions)
+{
+ ScRangeList aRanges(rRanges);
+ for (ScRangePtr p = aRanges.First(); p; p = aRanges.Next())
+ {
+ CopyToClip(p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(),
+ pTable, bKeepScenarioFlags, bCloneNoteCaptions);
+ }
+}
void ScTable::CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
SCsCOL nDx, SCsROW nDy, USHORT nInsFlag,
diff --git a/sc/source/core/tool/indexmap.cxx b/sc/source/core/tool/indexmap.cxx
deleted file mode 100644
index 50d0347a0aa9..000000000000
--- a/sc/source/core/tool/indexmap.cxx
+++ /dev/null
@@ -1,80 +0,0 @@
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2008 by Sun Microsystems, Inc.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * $RCSfile: indexmap.cxx,v $
- * $Revision: 1.4 $
- *
- * 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 <memory.h>
-
-#include "indexmap.hxx"
-
-
-ScIndexMap::ScIndexMap( USHORT nEntries )
-{
- nCount = nEntries;
- ULONG nC = nEntries ? ((ULONG) nEntries * 2) : 2;
- pMap = new USHORT [ nC ];
- memset( pMap, 0, nC * sizeof(USHORT) );
-}
-
-
-ScIndexMap::~ScIndexMap()
-{
- delete [] pMap;
-}
-
-
-void ScIndexMap::SetPair( USHORT nEntry, USHORT nIndex1, USHORT nIndex2 )
-{
- if ( nEntry < nCount )
- {
- ULONG nOff = (ULONG) nEntry * 2;
- pMap[nOff] = nIndex1;
- pMap[nOff+1] = nIndex2;
- }
-}
-
-
-USHORT ScIndexMap::Find( USHORT nIndex1 ) const
-{
- USHORT* pStop = pMap + (ULONG) nCount * 2;
- for ( USHORT* pOff = pMap; pOff < pStop; pOff += 2 )
- {
- if ( *pOff == nIndex1 )
- return *(pOff+1);
- }
- return nIndex1;
-}
-
-
diff --git a/sc/source/core/tool/makefile.mk b/sc/source/core/tool/makefile.mk
index ac0aa23fc044..52d9bad7c18c 100644
--- a/sc/source/core/tool/makefile.mk
+++ b/sc/source/core/tool/makefile.mk
@@ -80,7 +80,6 @@ SLOFILES = \
$(SLO)$/filtopt.obj \
$(SLO)$/formulaparserpool.obj \
$(SLO)$/hints.obj \
- $(SLO)$/indexmap.obj \
$(SLO)$/inputopt.obj \
$(SLO)$/interpr1.obj \
$(SLO)$/interpr2.obj \
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
index 0f2475bc2f65..3f0cadbadb7f 100644
--- a/sc/source/core/tool/rangenam.cxx
+++ b/sc/source/core/tool/rangenam.cxx
@@ -49,7 +49,6 @@
#include "rechead.hxx"
#include "refupdat.hxx"
#include "document.hxx"
-#include "indexmap.hxx"
using namespace formula;
@@ -588,20 +587,20 @@ void ScRangeData::TransferTabRef( SCTAB nOldTab, SCTAB nNewTab )
}
}
-
-void ScRangeData::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
+void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap )
{
- BOOL bCompile = FALSE;
+ bool bCompile = false;
for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
{
if ( p->GetOpCode() == ocName )
{
- const USHORT nOldIndex = p->GetIndex();
- const USHORT nNewIndex = rMap.Find( nOldIndex );
+ const sal_uInt16 nOldIndex = p->GetIndex();
+ IndexMap::const_iterator itr = rMap.find(nOldIndex);
+ const sal_uInt16 nNewIndex = itr == rMap.end() ? nOldIndex : itr->second;
if ( nOldIndex != nNewIndex )
{
p->SetIndex( nNewIndex );
- bCompile = TRUE;
+ bCompile = true;
}
}
}
diff --git a/sc/source/ui/docshell/arealink.cxx b/sc/source/ui/docshell/arealink.cxx
index a290a81d9078..a9e5f7ce8218 100644
--- a/sc/source/ui/docshell/arealink.cxx
+++ b/sc/source/ui/docshell/arealink.cxx
@@ -63,6 +63,7 @@
#include "sc.hrc" //CHINA001
#include "scabstdlg.hxx" //CHINA001
+#include "clipparam.hxx"
struct AreaLink_Impl
{
@@ -389,9 +390,8 @@ BOOL ScAreaLink::Refresh( const String& rNewFile, const String& rNewFilter,
aSourceMark.SelectOneTable( nSrcTab ); // selektieren fuer CopyToClip
aSourceMark.SetMarkArea( aTokenRange );
- pSrcDoc->CopyToClip( aTokenRange.aStart.Col(), aTokenRange.aStart.Row(),
- aTokenRange.aEnd.Col(), aTokenRange.aEnd.Row(),
- FALSE, &aClipDoc, FALSE, &aSourceMark );
+ ScClipParam aClipParam(aTokenRange, false);
+ pSrcDoc->CopyToClip(aClipParam, &aClipDoc, &aSourceMark);
if ( aClipDoc.HasAttrib( 0,0,nSrcTab, MAXCOL,MAXROW,nSrcTab,
HASATTR_MERGED | HASATTR_OVERLAPPED ) )
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 424e4731a324..608c1c688ea9 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -94,6 +94,7 @@
#include "compiler.hxx"
#include "scui_def.hxx" //CHINA001
#include "tabprotection.hxx"
+#include "clipparam.hxx"
#include <memory>
@@ -2276,8 +2277,8 @@ BOOL ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
}
ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
- pDoc->CopyToClip( nStartCol, nStartRow, nEndCol, nEndRow, bCut, pClipDoc,
- FALSE, &aSourceMark, bScenariosAdded, TRUE );
+ ScClipParam aClipParam(ScRange(nStartCol, nStartRow, 0, nEndCol, nEndRow, 0), false);
+ pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true);
ScDrawLayer::SetGlobalDrawPersist(NULL);
diff --git a/sc/source/ui/inc/cellsh.hxx b/sc/source/ui/inc/cellsh.hxx
index 8e09b7350bb1..90adbe40d2d2 100644
--- a/sc/source/ui/inc/cellsh.hxx
+++ b/sc/source/ui/inc/cellsh.hxx
@@ -42,6 +42,7 @@ class SvxClipboardFmtItem;
class TransferableDataHelper;
class TransferableClipboardListener;
class AbstractScLinkedAreaDlg;
+class ScTabViewShell;
struct CellShell_Impl
{
@@ -101,6 +102,8 @@ public:
void ExecutePageSel( SfxRequest& rReq );
void ExecuteMove( SfxRequest& rReq );
void GetStateCursor( SfxItemSet& rSet );
+
+ static void PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTabViewShell, bool bShowDialog );
};
#endif
diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index 228c4b4c1489..066aadca817a 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -348,6 +348,11 @@ private:
void PasteRTF( SCCOL nCol, SCROW nStartRow,
const ::com::sun::star::uno::Reference<
::com::sun::star::datatransfer::XTransferable >& rxTransferable );
+ bool PasteMultiRangesFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
+ bool bSkipEmpty, bool bTranspos, bool bAsLink, bool bAllowDialogs,
+ InsCellCmd eMoveMode, sal_uInt16 nCondFlags, sal_uInt16 nUndoFlags );
+ void PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark);
+
USHORT GetOptimalColWidth( SCCOL nCol, SCTAB nTab, BOOL bFormula );
void StartFormatArea();
diff --git a/sc/source/ui/navipi/content.cxx b/sc/source/ui/navipi/content.cxx
index a2db7e4e48f0..af3b5f0dee5e 100644
--- a/sc/source/ui/navipi/content.cxx
+++ b/sc/source/ui/navipi/content.cxx
@@ -71,6 +71,7 @@
#include "navicfg.hxx"
#include "navsett.hxx"
#include "postit.hxx"
+#include "clipparam.hxx"
using namespace com::sun::star;
@@ -1103,9 +1104,8 @@ void lcl_DoDragCells( ScDocShell* pSrcShell, const ScRange& rRange, USHORT nFlag
aMark ) )
{
ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
- pSrcDoc->CopyToClip( rRange.aStart.Col(), rRange.aStart.Row(),
- rRange.aEnd.Col(), rRange.aEnd.Row(),
- FALSE, pClipDoc, FALSE, &aMark );
+ ScClipParam aClipParam(rRange, false);
+ pSrcDoc->CopyToClip(aClipParam, pClipDoc, &aMark);
// pClipDoc->ExtendMerge( rRange, TRUE );
TransferableObjectDescriptor aObjDesc;
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index e44f5e7a6478..3df8e99348c0 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -64,6 +64,7 @@
#include "transobj.hxx"
#include "refundo.hxx"
#include "undoolk.hxx"
+#include "clipparam.hxx"
#include "sc.hrc"
@@ -1316,9 +1317,8 @@ void __EXPORT ScUndoDragDrop::Redo()
aSourceMark.SelectTable( nTab, TRUE );
// do not clone objects and note captions into clipdoc (see above)
- pDoc->CopyToClip( aSrcRange.aStart.Col(), aSrcRange.aStart.Row(),
- aSrcRange.aEnd.Col(), aSrcRange.aEnd.Row(),
- bCut, pClipDoc, FALSE, &aSourceMark, bKeepScenarioFlags, FALSE, FALSE );
+ ScClipParam aClipParam(aSrcRange, bCut);
+ pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bKeepScenarioFlags, false, false);
if (bCut)
{
diff --git a/sc/source/ui/unoobj/funcuno.cxx b/sc/source/ui/unoobj/funcuno.cxx
index 1d9f3a1d9213..a50b4003b0ac 100644
--- a/sc/source/ui/unoobj/funcuno.cxx
+++ b/sc/source/ui/unoobj/funcuno.cxx
@@ -57,6 +57,7 @@
#include "patattr.hxx"
#include "docpool.hxx"
#include "attrib.hxx"
+#include "clipparam.hxx"
using namespace com::sun::star;
@@ -175,9 +176,8 @@ BOOL lcl_CopyData( ScDocument* pSrcDoc, const ScRange& rSrcRange,
ScMarkData aSourceMark;
aSourceMark.SelectOneTable( nSrcTab ); // for CopyToClip
aSourceMark.SetMarkArea( rSrcRange );
- pSrcDoc->CopyToClip( rSrcRange.aStart.Col(),rSrcRange.aStart.Row(),
- rSrcRange.aEnd.Col(),rSrcRange.aEnd.Row(),
- FALSE, pClipDoc, FALSE, &aSourceMark );
+ ScClipParam aClipParam(rSrcRange, false);
+ pSrcDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false);
if ( pClipDoc->HasAttrib( 0,0,nSrcTab, MAXCOL,MAXROW,nSrcTab,
HASATTR_MERGED | HASATTR_OVERLAPPED ) )
diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index 54c8ff12e189..722885363346 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -206,7 +206,6 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
break;
case SID_COPY: // Kopieren
- bDisable = (!bSimpleArea && eMarkType != SC_MARK_SIMPLE_FILTERED);
// nur wegen Matrix nicht editierbar? Matrix nicht zerreissen
//! schlaegt nicht zu, wenn geschuetzt UND Matrix, aber damit
//! muss man leben.. wird in Copy-Routine abgefangen, sonst
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index e5bb702402d8..7f632f62c2ba 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -104,6 +104,7 @@
#include "dpgroup.hxx" // for ScDPNumGroupInfo
#include "spellparam.hxx"
#include "postit.hxx"
+#include "clipparam.hxx"
#include "globstr.hrc"
#include "scui_def.hxx" //CHINA001
@@ -1182,41 +1183,9 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
case SID_PASTE:
{
- Window* pWin = GetViewData()->GetActiveWin();
- ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
- ScDocument* pThisDoc = GetViewData()->GetDocument();
- ScDPObject* pDPObj = pThisDoc->GetDPAtCursor( GetViewData()->GetCurX(),
- GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
- if ( pOwnClip && pDPObj )
- {
- // paste from Calc into DataPilot table: sort (similar to drag & drop)
-
- ScDocument* pClipDoc = pOwnClip->GetDocument();
- SCTAB nSourceTab = pOwnClip->GetVisibleTab();
-
- SCCOL nClipStartX;
- SCROW nClipStartY;
- SCCOL nClipEndX;
- SCROW nClipEndY;
- pClipDoc->GetClipStart( nClipStartX, nClipStartY );
- pClipDoc->GetClipArea( nClipEndX, nClipEndY, TRUE );
- nClipEndX = nClipEndX + nClipStartX;
- nClipEndY = nClipEndY + nClipStartY; // GetClipArea returns the difference
-
- ScRange aSource( nClipStartX, nClipStartY, nSourceTab, nClipEndX, nClipEndY, nSourceTab );
- BOOL bDone = pTabViewShell->DataPilotMove( aSource, GetViewData()->GetCurPos() );
- if ( !bDone )
- pTabViewShell->ErrorMessage( STR_ERR_DATAPILOT_INPUT );
- }
- else
- {
- // normal paste
- WaitObject aWait( GetViewData()->GetDialogParent() );
- pTabViewShell->PasteFromSystem();
- }
+ PasteFromClipboard ( GetViewData(), pTabViewShell, true );
rReq.Done();
}
- pTabViewShell->CellContentChanged(); // => PasteFromSystem() ???
break;
case SID_CLIPBOARD_FORMAT_ITEMS:
@@ -2226,3 +2195,52 @@ IMPL_LINK( ScCellShell, DialogClosed, AbstractScLinkedAreaDlg*, EMPTYARG )
return 0;
}
+void ScCellShell::PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTabViewShell, bool bShowDialog )
+{
+ Window* pWin = pViewData->GetActiveWin();
+ ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
+ ScDocument* pThisDoc = pViewData->GetDocument();
+ ScDPObject* pDPObj = pThisDoc->GetDPAtCursor( pViewData->GetCurX(),
+ pViewData->GetCurY(), pViewData->GetTabNo() );
+ if ( pOwnClip && pDPObj )
+ {
+ // paste from Calc into DataPilot table: sort (similar to drag & drop)
+
+ ScDocument* pClipDoc = pOwnClip->GetDocument();
+ SCTAB nSourceTab = pOwnClip->GetVisibleTab();
+
+ SCCOL nClipStartX;
+ SCROW nClipStartY;
+ SCCOL nClipEndX;
+ SCROW nClipEndY;
+ pClipDoc->GetClipStart( nClipStartX, nClipStartY );
+ pClipDoc->GetClipArea( nClipEndX, nClipEndY, TRUE );
+ nClipEndX = nClipEndX + nClipStartX;
+ nClipEndY = nClipEndY + nClipStartY; // GetClipArea returns the difference
+
+ ScRange aSource( nClipStartX, nClipStartY, nSourceTab, nClipEndX, nClipEndY, nSourceTab );
+ BOOL bDone = pTabViewShell->DataPilotMove( aSource, pViewData->GetCurPos() );
+ if ( !bDone )
+ pTabViewShell->ErrorMessage( STR_ERR_DATAPILOT_INPUT );
+ }
+ else
+ {
+ // normal paste
+ WaitObject aWait( pViewData->GetDialogParent() );
+ if (!pOwnClip)
+ pTabViewShell->PasteFromSystem();
+ else
+ {
+ ScDocument* pClipDoc = pOwnClip->GetDocument();
+ sal_uInt16 nFlags = IDF_ALL;
+ if (pClipDoc->GetClipParam().isMultiRange())
+ // For multi-range paste, we paste values by default.
+ nFlags &= ~IDF_FORMULA;
+
+ pTabViewShell->PasteFromClip( nFlags, pClipDoc,
+ PASTE_NOFUNC, FALSE, FALSE, FALSE, INS_NONE, IDF_NONE,
+ bShowDialog ); // allow warning dialog
+ }
+ }
+ pTabViewShell->CellContentChanged(); // => PasteFromSystem() ???
+}
diff --git a/sc/source/ui/view/tabcont.cxx b/sc/source/ui/view/tabcont.cxx
index 3bfb8729cd37..db1a8952aeef 100644
--- a/sc/source/ui/view/tabcont.cxx
+++ b/sc/source/ui/view/tabcont.cxx
@@ -49,6 +49,7 @@
#include "sc.hrc"
#include "globstr.hrc"
#include "transobj.hxx"
+#include "clipparam.hxx"
// STATIC DATA -----------------------------------------------------------
@@ -447,7 +448,8 @@ void ScTabControl::DoDrag( const Region& /* rRegion */ )
aTabMark.SetMarkArea( ScRange(0,0,nTab,MAXCOL,MAXROW,nTab) );
ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
- pDoc->CopyToClip( 0,0, MAXCOL,MAXROW, FALSE, pClipDoc, FALSE, &aTabMark );
+ ScClipParam aClipParam(ScRange(0, 0, 0, MAXCOL, MAXROW, 0), false);
+ pDoc->CopyToClip(aClipParam, pClipDoc, &aTabMark, false);
TransferableObjectDescriptor aObjDesc;
pDocSh->FillTransferableObjectDescriptor( aObjDesc );
diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx
index 29ebede481b9..e34741ba4c6b 100644
--- a/sc/source/ui/view/tabvwsh4.cxx
+++ b/sc/source/ui/view/tabvwsh4.cxx
@@ -1510,7 +1510,7 @@ BOOL ScTabViewShell::TabKeyInput(const KeyEvent& rKEvt)
// #51889# Spezialfall: Copy/Cut bei Mehrfachselektion -> Fehlermeldung
// (Slot ist disabled, SfxViewShell::KeyInput wuerde also kommentarlos verschluckt)
KeyFuncType eFunc = aCode.GetFunction();
- if ( eFunc == KEYFUNC_COPY || eFunc == KEYFUNC_CUT )
+ if ( eFunc == KEYFUNC_CUT )
{
ScRange aDummy;
ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy );
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index 9dda9a097395..4b5d59b80284 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -212,6 +212,7 @@
#include "transobj.hxx"
#include "drwtrans.hxx"
#include "docuno.hxx"
+#include "clipparam.hxx"
using namespace com::sun::star;
@@ -312,10 +313,10 @@ BOOL ScViewFunc::CopyToClip( ScDocument* pClipDoc, BOOL bCut, BOOL bApi, BOOL bI
ScRange aRange;
ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange );
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
{
- ScDocument* pDoc = GetViewData()->GetDocument();
- ScMarkData& rMark = GetViewData()->GetMarkData();
if ( !pDoc->HasSelectedBlockMatrixFragment(
aRange.aStart.Col(), aRange.aStart.Row(),
aRange.aEnd.Col(), aRange.aEnd.Row(),
@@ -342,9 +343,8 @@ BOOL ScViewFunc::CopyToClip( ScDocument* pClipDoc, BOOL bCut, BOOL bApi, BOOL bI
ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
}
- pDoc->CopyToClip( aRange.aStart.Col(), aRange.aStart.Row(),
- aRange.aEnd.Col(), aRange.aEnd.Row(),
- bCut, pClipDoc, FALSE, &rMark, FALSE, bIncludeObjects );
+ ScClipParam aClipParam(aRange, bCut);
+ pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects);
if (bSysClip)
{
ScDrawLayer::SetGlobalDrawPersist(NULL);
@@ -382,6 +382,124 @@ BOOL ScViewFunc::CopyToClip( ScDocument* pClipDoc, BOOL bCut, BOOL bApi, BOOL bI
ErrorMessage(STR_MATRIXFRAGMENTERR);
}
}
+ else if (eMarkType == SC_MARK_MULTI)
+ {
+ bool bSuccess = false;
+ ScClipParam aClipParam;
+ aClipParam.mbCutMode = false;
+ rMark.MarkToSimple();
+ rMark.FillRangeListWithMarks(&aClipParam.maRanges, false);
+
+ do
+ {
+ if (bCut)
+ // We con't support cutting of multi-selections.
+ break;
+
+ if (pClipDoc)
+ // TODO: What's this for?
+ break;
+
+ ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
+
+ // Check for geometrical feasibility of the ranges.
+ bool bValidRanges = true;
+ ScRangePtr p = aClipParam.maRanges.First();
+ SCCOL nPrevColDelta = 0;
+ SCROW nPrevRowDelta = 0;
+ SCCOL nPrevCol = p->aStart.Col();
+ SCROW nPrevRow = p->aStart.Row();
+ SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
+ SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
+ for (p = aClipParam.maRanges.Next(); p; p = aClipParam.maRanges.Next())
+ {
+ if (pDoc->HasSelectedBlockMatrixFragment(
+ p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark))
+ {
+ if (!bApi)
+ ErrorMessage(STR_MATRIXFRAGMENTERR);
+ return false;
+ }
+
+ SCCOL nColDelta = p->aStart.Col() - nPrevCol;
+ SCROW nRowDelta = p->aStart.Row() - nPrevRow;
+
+ if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
+ {
+ bValidRanges = false;
+ break;
+ }
+
+ if (aClipParam.meDirection == ScClipParam::Unspecified)
+ {
+ if (nColDelta)
+ aClipParam.meDirection = ScClipParam::Column;
+ if (nRowDelta)
+ aClipParam.meDirection = ScClipParam::Row;
+ }
+
+ SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
+ SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
+
+ if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
+ {
+ // column-oriented ranges must have identical row size.
+ bValidRanges = false;
+ break;
+ }
+ if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
+ {
+ // likewise, row-oriented ranges must have identical
+ // column size.
+ bValidRanges = false;
+ break;
+ }
+
+ nPrevCol = p->aStart.Col();
+ nPrevRow = p->aStart.Row();
+ nPrevColDelta = nColDelta;
+ nPrevRowDelta = nRowDelta;
+ nPrevColSize = nColSize;
+ nPrevRowSize = nRowSize;
+ }
+ if (!bValidRanges)
+ break;
+
+ pDoc->CopyToClip(aClipParam, pDocClip.get(), false, &rMark, false, bIncludeObjects);
+
+ ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
+ if ( pChangeTrack )
+ pChangeTrack->ResetLastCut(); // kein CutMode mehr
+
+ {
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ TransferableObjectDescriptor aObjDesc;
+ pDocSh->FillTransferableObjectDescriptor( aObjDesc );
+ aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
+ // maSize is set in ScTransferObj ctor
+
+ ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
+ uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
+
+ if ( ScGlobal::pDrawClipDocShellRef )
+ {
+ SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
+ pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
+ }
+
+ pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
+ SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
+ }
+
+ bSuccess = true;
+ }
+ while (false);
+
+ if (!bSuccess && !bApi)
+ ErrorMessage(STR_NOMULTISELECT);
+
+ bDone = bSuccess;
+ }
else
{
if (!bApi)
@@ -408,9 +526,8 @@ ScTransferObj* ScViewFunc::CopyToTransferable()
BOOL bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
- pDoc->CopyToClip( aRange.aStart.Col(), aRange.aStart.Row(),
- aRange.aEnd.Col(), aRange.aEnd.Row(),
- FALSE, pClipDoc, FALSE, &rMark, FALSE, TRUE );
+ ScClipParam aClipParam(aRange, false);
+ pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true);
ScDrawLayer::SetGlobalDrawPersist(NULL);
pClipDoc->ExtendMerge( aRange, TRUE );
@@ -739,6 +856,52 @@ BOOL lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2,
// internes Paste
+namespace {
+
+class CursorSwitcher
+{
+public:
+ CursorSwitcher(ScViewFunc* pViewFunc) :
+ mpViewFunc(pViewFunc)
+ {
+ mpViewFunc->HideCursor();
+ }
+
+ ~CursorSwitcher()
+ {
+ mpViewFunc->ShowCursor();
+ }
+private:
+ ScViewFunc* mpViewFunc;
+};
+
+bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
+{
+ bool bIsEmpty = true;
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab < nTabCount && bIsEmpty; ++nTab)
+ {
+ if (!rMark.GetTableSelect(nTab))
+ continue;
+
+ bIsEmpty = pDoc->IsBlockEmpty(nTab, rDestRange.aStart.Col(), rDestRange.aStart.Row(),
+ rDestRange.aEnd.Col(), rDestRange.aEnd.Row());
+ }
+
+ if (!bIsEmpty)
+ {
+ ScReplaceWarnBox aBox(pParentWnd);
+ if (aBox.Execute() != RET_YES)
+ {
+ // changing the configuration is within the ScReplaceWarnBox
+ return false;
+ }
+ }
+ return true;
+}
+
+}
+
BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
USHORT nFunction, BOOL bSkipEmpty,
BOOL bTranspose, BOOL bAsLink,
@@ -764,6 +927,12 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
// do not copy note captions into undo document
nUndoFlags |= IDF_NOCAPTIONS;
+ ScClipParam& rClipParam = pClipDoc->GetClipParam();
+ if (rClipParam.isMultiRange())
+ return PasteMultiRangesFromClip(
+ nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
+ eMoveMode, nContFlags, nUndoFlags);
+
BOOL bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
BOOL bIncludeFiltered = bCutMode;
@@ -992,23 +1161,8 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
if ( bAskIfNotEmpty )
{
- BOOL bIsEmpty = TRUE;
- SCTAB nTabCount = pDoc->GetTableCount();
- for (SCTAB nTab=0; nTab<nTabCount && bIsEmpty; nTab++)
- if ( aFilteredMark.GetTableSelect(nTab) &&
- !pDoc->IsBlockEmpty( nTab, aUserRange.aStart.Col(), aUserRange.aStart.Row(),
- aUserRange.aEnd.Col(), aUserRange.aEnd.Row() ) )
- bIsEmpty = FALSE;
-
- if ( !bIsEmpty )
- {
- ScReplaceWarnBox aBox( GetViewData()->GetDialogParent() );
- if ( aBox.Execute() != RET_YES )
- {
- // changing the configuration is within the ScReplaceWarnBox
- return FALSE;
- }
- }
+ if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
+ return false;
}
}
@@ -1302,7 +1456,179 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
// AdjustBlockHeight has already been called above
aModificator.SetDocumentModified();
- pDocSh->UpdateOle(GetViewData());
+ PostPasteFromClip(aUserRange, rMark);
+ return TRUE;
+}
+
+bool ScViewFunc::PasteMultiRangesFromClip(
+ sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
+ bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
+ InsCellCmd eMoveMode, sal_uInt16 /*nContFlags*/, sal_uInt16 nUndoFlags)
+{
+ ScViewData& rViewData = *GetViewData();
+ ScDocument* pDoc = rViewData.GetDocument();
+ ScDocShell* pDocSh = rViewData.GetDocShell();
+ ScMarkData aMark(rViewData.GetMarkData());
+ const ScAddress& rCurPos = rViewData.GetCurPos();
+ ScClipParam& rClipParam = pClipDoc->GetClipParam();
+ SCCOL nColSize = rClipParam.getPasteColSize();
+ SCROW nRowSize = rClipParam.getPasteRowSize();
+
+ if (bTranspose)
+ {
+ if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
+ {
+ ErrorMessage(STR_PASTE_FULL);
+ return false;
+ }
+
+ ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
+ pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
+ pClipDoc = pTransClip.release();
+ SCCOL nTempColSize = nColSize;
+ nColSize = static_cast<SCCOL>(nRowSize);
+ nRowSize = static_cast<SCROW>(nTempColSize);
+ }
+
+ if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
+ {
+ ErrorMessage(STR_PASTE_FULL);
+ return false;
+ }
+
+ // Determine the first and last selected sheet numbers.
+ SCTAB nTab1 = aMark.GetFirstSelected();
+ SCTAB nTab2 = nTab1;
+ for (SCTAB i = nTab1+1; i <= MAXTAB; ++i)
+ if (aMark.GetTableSelect(i))
+ nTab2 = i;
+
+ ScDocShellModificator aModificator(*pDocSh);
+
+ // For multi-selection paste, we don't support cell duplication for larger
+ // destination range. In case the destination is marked, we reset it to
+ // the clip size.
+ ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
+ rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
+
+ // Extend the marked range to account for filtered rows in the destination
+ // area.
+ if (ScViewUtil::HasFiltered(aMarkedRange, pDoc))
+ {
+ if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize))
+ return false;
+ }
+
+ bool bAskIfNotEmpty =
+ bAllowDialogs && (nFlags & IDF_CONTENTS) &&
+ nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
+
+ if (bAskIfNotEmpty)
+ {
+ if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent()))
+ return false;
+ }
+
+ aMark.SetMarkArea(aMarkedRange);
+ MarkRange(aMarkedRange);
+
+ bool bInsertCells = (eMoveMode != INS_NONE);
+ if (bInsertCells)
+ {
+ if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
+ return false;
+ }
+
+ ::std::auto_ptr<ScDocument> pUndoDoc;
+ if (pDoc->IsUndoEnabled())
+ {
+ pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
+ pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
+ pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true);
+ }
+
+ ::std::auto_ptr<ScDocument> pMixDoc;
+ if ( bSkipEmpty || nFunction )
+ {
+ if ( nFlags & IDF_CONTENTS )
+ {
+ pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
+ pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
+ pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
+ }
+ }
+
+ /* Make draw layer and start drawing undo.
+ - Needed before AdjustBlockHeight to track moved drawing objects.
+ - Needed before pDoc->CopyFromClip to track inserted note caption objects.
+ */
+ if (nFlags & IDF_OBJECTS)
+ pDocSh->MakeDrawLayer();
+ if (pDoc->IsUndoEnabled())
+ pDoc->BeginDrawUndo();
+
+ CursorSwitcher aCursorSwitch(this);
+ sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
+ pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
+ true, bAsLink, false, bSkipEmpty);
+
+ if (pMixDoc.get())
+ pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
+
+ AdjustBlockHeight(); // update row heights before pasting objects
+
+ if (nFlags & IDF_OBJECTS)
+ {
+ // Paste the drawing objects after the row heights have been updated.
+ pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
+ true, false, false, true);
+ }
+
+ pDocSh->PostPaint(
+ aMarkedRange.aStart.Col(), aMarkedRange.aStart.Row(), nTab1,
+ aMarkedRange.aEnd.Col(), aMarkedRange.aEnd.Row(), nTab1, PAINT_GRID);
+
+ if (pDoc->IsUndoEnabled())
+ {
+ SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager();
+ String aUndo = ScGlobal::GetRscString(
+ pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
+ pUndoMgr->EnterListAction(aUndo, aUndo);
+
+ ScUndoPasteOptions aOptions; // store options for repeat
+ aOptions.nFunction = nFunction;
+ aOptions.bSkipEmpty = bSkipEmpty;
+ aOptions.bTranspose = bTranspose;
+ aOptions.bAsLink = bAsLink;
+ aOptions.eMoveMode = eMoveMode;
+
+ ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
+ aMarkedRange.aStart.Col(),
+ aMarkedRange.aStart.Row(),
+ aMarkedRange.aStart.Tab(),
+ aMarkedRange.aEnd.Col(),
+ aMarkedRange.aEnd.Row(),
+ aMarkedRange.aEnd.Tab(),
+ aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions);
+
+ if (bInsertCells)
+ pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
+ else
+ pUndoMgr->AddUndoAction(pUndo, false);
+
+ pUndoMgr->LeaveListAction();
+ }
+ aModificator.SetDocumentModified();
+ PostPasteFromClip(aMarkedRange, aMark);
+ return true;
+}
+
+void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark)
+{
+ ScViewData* pViewData = GetViewData();
+ ScDocShell* pDocSh = pViewData->GetDocShell();
+ ScDocument* pDoc = pViewData->GetDocument();
+ pDocSh->UpdateOle(pViewData);
SelectionChanged();
@@ -1316,7 +1642,7 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
{
if ( rMark.GetTableSelect( i ) )
{
- ScRange aChangeRange( aUserRange );
+ ScRange aChangeRange(rPasteRange);
aChangeRange.aStart.SetTab( i );
aChangeRange.aEnd.SetTab( i );
aChangeRanges.Append( aChangeRange );
@@ -1324,8 +1650,6 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
}
pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
}
-
- return TRUE;
}
diff --git a/sc/source/ui/view/viewfun5.cxx b/sc/source/ui/view/viewfun5.cxx
index f8b89a85e11c..35af3ee2a2e3 100644
--- a/sc/source/ui/view/viewfun5.cxx
+++ b/sc/source/ui/view/viewfun5.cxx
@@ -79,6 +79,7 @@
#include "asciiopt.hxx"
#include "scabstdlg.hxx"
+#include "clipparam.hxx"
#include <vcl/msgbox.hxx>
#include <sfx2/viewfrm.hxx>
#include <svx/dbaexchange.hxx>
@@ -163,12 +164,12 @@ BOOL ScViewFunc::PasteDataFormat( ULONG nFormatId,
if ( pSrcDoc->GetDataStart( nSrcTab, nFirstCol, nFirstRow ) )
pSrcDoc->GetCellArea( nSrcTab, nLastCol, nLastRow );
else
- {
+ {
nFirstCol = nLastCol = 0;
nFirstRow = nLastRow = 0;
- }
- pSrcDoc->CopyToClip( nFirstCol, nFirstRow, nLastCol, nLastRow,
- FALSE, pClipDoc, FALSE, &aSrcMark );
+ }
+ ScClipParam aClipParam(ScRange(nFirstCol, nFirstRow, 0, nLastCol, nLastRow, 0), false);
+ pSrcDoc->CopyToClip(aClipParam, pClipDoc, &aSrcMark);
ScGlobal::SetClipDocName( xDocShRef->GetTitle( SFX_TITLE_FULLNAME ) );
SetCursor( nPosX, nPosY );