Commits

obo  committed 08b6839

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.

  • Participants
  • Parent commits af148c3

Comments (0)

Files changed (33)

File sc/inc/cell.hxx

 #include <tools/mempool.hxx>
 #include <svtools/listener.hxx>
 #include "global.hxx"
+#include "rangenam.hxx"
 #include "formula/grammar.hxx"
 #include "tokenarray.hxx"
 #include "formularesult.hxx"
     MM_FAKE      = 3                    // Interpret "as-if" matrix formula (legacy)
 };
 
-class ScIndexMap;
-
 class SC_DLLPUBLIC ScFormulaCell : public ScBaseCell, public SvtListener
 {
 private:
 	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; }

File sc/inc/clipparam.hxx

+/*************************************************************************
+ *
+ * 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

File sc/inc/column.hxx

 #include "global.hxx"
 #include "compressedarray.hxx"
 #include "address.hxx"
+#include "rangenam.hxx"
 #include <tools/solar.h>
 
 #include <set>
 };
 
 
-class ScIndexMap;
-
 class ScColumn
 {
 private:
 	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;

File sc/inc/document.hxx

 struct ScLookupCacheMapImpl;
 class SfxUndoManager;
 class ScFormulaParserPool;
+struct ScClipParam;        
+struct ScClipRangeNameData;
 
 namespace com { namespace sun { namespace star {
     namespace lang {
 	ScFieldEditEngine*	pCacheFieldEditEngine;
 
     ::std::auto_ptr<ScDocProtection> pDocProtection;
+    ::std::auto_ptr<ScClipParam>     mpClipParam;
 
     ::std::auto_ptr<ScExternalRefManager> pExternalRefMgr;
 
 
     sal_uInt32          nRangeOverflowType;             // used in (xml) loading for overflow warnings
 
-	ScRange				aClipRange;
 	ScRange				aEmbedRange;
 	ScAddress			aCurTextWidthCalcPos;
 	ScAddress			aOnlineSpellPos;				// within whole document
 	BOOL				bForcedFormulaPending;
 	BOOL				bCalculatingFormulaTree;
 	BOOL				bIsClip;
-	BOOL				bCutMode;
 	BOOL				bIsUndo;
 	BOOL				bIsVisible;						// set from view ctor
 
 	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			CopyTabToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
-								SCTAB nTab, ScDocument* pClipDoc = NULL);
+
+    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,
 									const ScMarkData& rMark, SCsCOL nDx, SCsROW nDy,
 									const ScCopyBlockFromClipParams* pCBFCP );
 									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);
 
 
 	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 );
 
 	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();
 
 	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;

File sc/inc/indexmap.hxx

-/*************************************************************************
- *
- * 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
-

File sc/inc/rangenam.hxx

 #include "formula/grammar.hxx"
 #include "scdllapi.h"
 
+#include <map>
+
 //------------------------------------------------------------------------
 
 class ScDocument;
 //------------------------------------------------------------------------
 
 class ScTokenArray;
-class ScIndexMap;
 
 class ScRangeData : public ScDataObject
 {
 	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,
 
 	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 );

File sc/inc/table.hxx

 class ScTableLink;
 class ScTableProtection;
 class ScUserListData;
-class ScIndexMap;
 struct RowInfo;
 struct ScFunctionData;
 struct ScLineFlags;
 	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,
     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);

File sc/source/core/data/cell2.cxx

 #include "scmatrix.hxx"
 #include "editutil.hxx"
 #include "chgtrack.hxx"
-#include "indexmap.hxx"
 #include "externalrefmgr.hxx"
 
 using namespace formula;
     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 );

File sc/source/core/data/clipparam.cxx

+/*************************************************************************
+ *
+ * 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));
+}

File sc/source/core/data/column.cxx

 }
 
 void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
-									 const ScIndexMap& rMap )
+                                     const ScRangeData::IndexMap& rMap )
 {
-	if (pItems)
-		for (SCSIZE i = 0; i < nCount; i++)
-		{
-			if ((pItems[i].nRow >= nRow1) &&
-				(pItems[i].nRow <= nRow2) &&
-				(pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
-			{
-				SCROW nRow = pItems[i].nRow;
-				((ScFormulaCell*)pItems[i].pCell)->ReplaceRangeNamesInUse( rMap );
-				if ( nRow != pItems[i].nRow )
-					Search( nRow, i );		// Listener geloescht/eingefuegt?
-			}
-		}
+    if (pItems)
+        for (SCSIZE i = 0; i < nCount; i++)
+        {
+            if ((pItems[i].nRow >= nRow1) &&
+                (pItems[i].nRow <= nRow2) &&
+                (pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
+            {
+                SCROW nRow = pItems[i].nRow;
+                ((ScFormulaCell*)pItems[i].pCell)->ReplaceRangeNamesInUse( rMap );
+                if ( nRow != pItems[i].nRow )
+                    Search( nRow, i );      // Listener geloescht/eingefuegt?
+            }
+        }
 }
 
-
 void ScColumn::SetDirtyVar()
 {
 	for (SCSIZE i=0; i<nCount; i++)

File sc/source/core/data/documen2.cxx

 #include "editutil.hxx"
 #include "hints.hxx"
 #include "dpobject.hxx"
-#include "indexmap.hxx"
 #include "scrdata.hxx"
 #include "poolhelp.hxx"
 #include "unoreflist.hxx"
 #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.
 		pScriptTypeData( NULL ),
         pCacheFieldEditEngine( NULL ),
         pDocProtection( NULL ),
+        mpClipParam( NULL),
+        pExternalRefMgr( NULL ),
 		pViewOptions( NULL ),
 		pDocOptions( NULL ),
 		pExtDocOptions( NULL ),
 		bForcedFormulaPending( FALSE ),
 		bCalculatingFormulaTree( FALSE ),
 		bIsClip( eMode == SCDOCMODE_CLIP ),
-		bCutMode( FALSE ),
 		bIsUndo( eMode == SCDOCMODE_UNDO ),
 		bIsVisible( FALSE ),
 		bIsEmbedded( FALSE ),
 			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 )
 			// 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
 				        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;
 				    }
     						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 );
     					}

File sc/source/core/data/documen3.cxx

 #include "listenercalls.hxx"
 #include "tabprotection.hxx"
 #include "formulaparserpool.hxx"
+#include "clipparam.hxx"
 
 #include <memory>
 
 		{
 			ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
 			if (pClipDoc)
-				pClipDoc->bCutMode = FALSE;
+				pClipDoc->GetClipParam().mbCutMode = false;
 		}
 	}
 }
 {
 	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;

File sc/source/core/data/documen8.cxx

 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;
 }
 
 //------------------------------------------------------------------------

File sc/source/core/data/document.cxx

 #include "detdata.hxx"
 #include "cell.hxx"
 #include "dpobject.hxx"
-#include "indexmap.hxx"
 #include "detfunc.hxx"		// for UpdateAllComments
 #include "scmod.hxx"
 #include "dociter.hxx"
 #include "postit.hxx"
 #include "externalrefmgr.hxx"
 #include "tabprotection.hxx"
+#include "clipparam.hxx"
+
+#include <map>
 
 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
 
 void ScDocument::SetCutMode( BOOL bVal )
 {
 	if (bIsClip)
-		bCutMode = bVal;
+        GetClipParam().mbCutMode = bVal;
 	else
 	{
 		DBG_ERROR("SetCutMode without bIsClip");
 BOOL ScDocument::IsCutMode()
 {
 	if (bIsClip)
-		return bCutMode;
+		return GetClipParam().mbCutMode;
 	else
 	{
 		DBG_ERROR("IsCutMode ohne bIsClip");
 	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)
-{
-	DBG_ASSERT( bAllTabs || pMarks, "CopyToClip: ScMarkData fehlt" );
-
-	if (!bIsClip)
-	{
-		PutInOrder( nCol1, nCol2 );
-		PutInOrder( nRow1, nRow2 );
-		if (!pClipDoc)
-		{
-			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);
-
-					if ( pDrawLayer && bIncludeObjects )
-					{
-						//	also copy drawing objects
-
-						Rectangle aObjRect = GetMMRect( nCol1, nRow1, nCol2, nRow2, j );
-						pDrawLayer->CopyToClip( pClipDoc, j, aObjRect );
-					}
-				}
-
-		pClipDoc->bCutMode = bCut;
-	}
-}
-
+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)
+        return;
+
+    if (!pClipDoc)
+    {
+        DBG_ERROR("CopyToClip: no ClipDoc");
+        pClipDoc = SC_MOD()->GetClipDoc();
+    }
+
+    pClipDoc->aDocName = aDocName;
+    pClipDoc->SetClipParam(rClipParam);
+    pClipDoc->ResetClip(this, pMarks);
+
+    ScRange aClipRange = rClipParam.getWholeRange();
+    CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, bAllTabs);
+
+    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);
+
+        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,
 			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;
 	}
 }
 
 
 		//	Daten
 
+    ScRange aClipRange = GetClipParam().getWholeRange();
 	if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) )
 	{
 		for (SCTAB i=0; i<=MAXTAB; i++)
 				}
 			}
 
-		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
 	{
 
 		//	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
 {
                         && ppClipTab[nClipTab + nFollow + 1] )
                     ++nFollow;
 
-                if ( pCBFCP->pClipDoc->bCutMode )
+                if ( pCBFCP->pClipDoc->GetClipParam().mbCutMode )
                 {
                     BOOL bOldInserting = IsInsertingFromOtherDoc();
                     SetInsertingFromOtherDoc( TRUE);
         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 )
 			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;
-			}
-
-			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;
-
-			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;
-					}
-				}
-			}
+            NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
+
+            ScClipRangeNameData aClipRangeNames;
+            CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
+
 			SCCOL nAllCol1 = rDestRange.aStart.Col();
 			SCROW nAllRow1 = rDestRange.aStart.Row();
 			SCCOL nAllCol2 = rDestRange.aEnd.Col();
 
             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 )
 			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);
                         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)
 					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
 	{
 
 void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, BOOL bIncludeFiltered)
 {
+    if (!bIsClip)
+    {    
+        DBG_ERROR("GetClipArea: kein Clip");
+        return;
+    }
+
+    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
+	{
+        //	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
+	}
+}
+
+
+void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY)
+{
 	if (bIsClip)
 	{
-		nClipX = aClipRange.aEnd.Col() - aClipRange.aStart.Col();
-
-		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
-		}
-	}
-	else
-	{
-		DBG_ERROR("GetClipArea: kein Clip");
-	}
-}
-
-
-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
 	{
 	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);
 }
 
 

File sc/source/core/data/makefile.mk

 	$(SLO)$/bcaslot.obj \
 	$(SLO)$/cell.obj \
 	$(SLO)$/cell2.obj \
+        $(SLO)$/clipparam.obj \
 	$(SLO)$/column.obj \
 	$(SLO)$/column2.obj \
 	$(SLO)$/column3.obj \
     $(SLO)$/autonamecache.obj \
     $(SLO)$/bcaslot.obj \
     $(SLO)$/cell2.obj \
+    $(SLO)$/clipparam.obj \
     $(SLO)$/column.obj \
     $(SLO)$/column3.obj \
     $(SLO)$/documen2.obj \

File sc/source/core/data/table1.cxx

 }
 
 void ScTable::ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1,
-									SCCOL nCol2, SCROW nRow2,
-									const ScIndexMap& rMap )
+                                    SCCOL nCol2, SCROW nRow2,
+                                    const ScRangeData::IndexMap& rMap )
 {
-	for (SCCOL i = nCol1; i <= nCol2 && (ValidCol(i)); i++)
-	{
-		aCol[i].ReplaceRangeNamesInUse( nRow1, nRow2, rMap );
-	}
+    for (SCCOL i = nCol1; i <= nCol2 && (ValidCol(i)); i++)
+    {
+        aCol[i].ReplaceRangeNamesInUse( nRow1, nRow2, rMap );
+    }
 }
 
 void ScTable::ExtendPrintArea( OutputDevice* pDev,

File sc/source/core/data/table2.cxx

 	}
 }
 
+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,

File sc/source/core/tool/indexmap.cxx

-/*************************************************************************
- *
- * 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;
-}
-
-

File sc/source/core/tool/makefile.mk

 		$(SLO)$/filtopt.obj \
 		$(SLO)$/formulaparserpool.obj \
 		$(SLO)$/hints.obj \
-		$(SLO)$/indexmap.obj \
 		$(SLO)$/inputopt.obj \
 		$(SLO)$/interpr1.obj \
 		$(SLO)$/interpr2.obj \

File sc/source/core/tool/rangenam.cxx

 #include "rechead.hxx"
 #include "refupdat.hxx"
 #include "document.hxx"
-#include "indexmap.hxx"
 
 using namespace formula;
 
 	}
 }
 
-
-void ScRangeData::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
+void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap )
 {
-	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 );
+    bool bCompile = false;
+    for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
+    {
+        if ( p->GetOpCode() == ocName )
+        {
+            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;
-			}
-		}
-	}
-	if ( bCompile )
-	{
-		ScCompiler aComp( pDoc, aPos, *pCode);
+            {
+                p->SetIndex( nNewIndex );
+                bCompile = true;
+            }
+        }
+    }
+    if ( bCompile )
+    {
+        ScCompiler aComp( pDoc, aPos, *pCode);
         aComp.SetGrammar(pDoc->GetGrammar());
-		aComp.CompileTokenArray();
-	}
+        aComp.CompileTokenArray();
+    }
 }
 
 

File sc/source/ui/docshell/arealink.cxx

 
 #include "sc.hrc" //CHINA001
 #include "scabstdlg.hxx" //CHINA001
+#include "clipparam.hxx"
 
 struct AreaLink_Impl
 {
 					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 ) )

File sc/source/ui/docshell/docfunc.cxx

 #include "compiler.hxx"
 #include "scui_def.hxx" //CHINA001
 #include "tabprotection.hxx"
+#include "clipparam.hxx"
 
 #include <memory>
 
 	}
 	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);
 

File sc/source/ui/inc/cellsh.hxx

 class TransferableDataHelper;
 class TransferableClipboardListener;
 class AbstractScLinkedAreaDlg;
+class ScTabViewShell;
 
 struct CellShell_Impl
 {
 	void		ExecutePageSel( SfxRequest& rReq );
 	void		ExecuteMove( SfxRequest& rReq );
 	void		GetStateCursor( SfxItemSet& rSet );
+
+	static void PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTabViewShell, bool bShowDialog );
 };
 
 #endif

File sc/source/ui/inc/viewfunc.hxx

 	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();

File sc/source/ui/navipi/content.cxx

 #include "navicfg.hxx"
 #include "navsett.hxx"
 #include "postit.hxx"
+#include "clipparam.hxx"
 
 using namespace com::sun::star;
 
 												   aMark ) )