diff options
author | Oliver Bolte <obo@openoffice.org> | 2009-09-09 07:31:32 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2009-09-09 07:31:32 +0000 |
commit | c24ab8def12f8a7a305e35d39c91976e345dd3b0 (patch) | |
tree | 019d5541f524e4f5691328f1d8b5f9f24e5a01a0 /sc | |
parent | fbb3c82a81750cf7744e25af48a3372b8aafbd53 (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.
Diffstat (limited to 'sc')
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 ); |