[ooo-build-commit] Branch 'ooo/master' - sc/inc sc/source

Jan Holesovsky kendy at kemper.freedesktop.org
Wed Sep 9 19:20:51 PDT 2009


 sc/inc/cell.hxx                    |    5 
 sc/inc/clipparam.hxx               |   91 +++++
 sc/inc/column.hxx                  |    5 
 sc/inc/document.hxx                |   48 ++
 sc/inc/indexmap.hxx                |   59 ---
 sc/inc/rangenam.hxx                |    7 
 sc/inc/table.hxx                   |    5 
 sc/source/core/data/cell2.cxx      |    8 
 sc/source/core/data/clipparam.cxx  |  203 +++++++++++
 sc/source/core/data/column.cxx     |    5 
 sc/source/core/data/documen2.cxx   |   38 +-
 sc/source/core/data/documen3.cxx   |    8 
 sc/source/core/data/documen8.cxx   |   14 
 sc/source/core/data/document.cxx   |  658 ++++++++++++++++++++++++-------------
 sc/source/core/data/makefile.mk    |    2 
 sc/source/core/data/table1.cxx     |    2 
 sc/source/core/data/table2.cxx     |   10 
 sc/source/core/tool/indexmap.cxx   |   80 ----
 sc/source/core/tool/makefile.mk    |    1 
 sc/source/core/tool/rangenam.cxx   |   13 
 sc/source/ui/docshell/arealink.cxx |    6 
 sc/source/ui/docshell/docfunc.cxx  |    5 
 sc/source/ui/inc/cellsh.hxx        |    3 
 sc/source/ui/inc/viewfunc.hxx      |    5 
 sc/source/ui/navipi/content.cxx    |    6 
 sc/source/ui/undo/undoblk.cxx      |    6 
 sc/source/ui/unoobj/funcuno.cxx    |    6 
 sc/source/ui/view/cellsh.cxx       |    1 
 sc/source/ui/view/cellsh1.cxx      |   84 ++--
 sc/source/ui/view/tabcont.cxx      |    4 
 sc/source/ui/view/tabvwsh4.cxx     |    2 
 sc/source/ui/view/viewfun3.cxx     |  382 +++++++++++++++++++--
 sc/source/ui/view/viewfun5.cxx     |    9 
 33 files changed, 1274 insertions(+), 507 deletions(-)

New commits:
commit 6932a49811640d8170b524626d5507dacf75b42c
Author: Oliver Bolte <obo at openoffice.org>
Date:   Wed Sep 9 07:31:32 2009 +0000

    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 at 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.

diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx
index 96a32ab..72be0b2 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 0000000..544cef3
--- /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 fd2473b..740a4d7 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 54055cc..8fdf113 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 a599e6b..0000000
--- 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 87b279f..980f593 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 f60fd40..e0187f9 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 c92676f..40d6e45 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 0000000..b2ec555
--- /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 0932cda..81586a1 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++)
@@ -1886,12 +1886,11 @@ void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
                 SCROW nRow = pItems[i].nRow;
                 ((ScFormulaCell*)pItems[i].pCell)->ReplaceRangeNamesInUse( rMap );
                 if ( nRow != pItems[i].nRow )
-                    Search( nRow, i );		// Listener geloescht/eingefuegt?
+                    Search( nRow, i );      // Listener geloescht/eingefuegt?
             }
         }
 }
 
-
 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 f6bcfa9..26933b3 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 810f322..f0806eb 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 dc2a0b4..c99054b 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 efdb16d..08db233 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)
-    {
-        nClipX = aClipRange.aEnd.Col() - aClipRange.aStart.Col();
+    if (!bIsClip)
+    {    
+        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 29618da..d2c700c 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 6291213..15db733 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 999fd71..12e56ea 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 4ee5086..0000000
--- 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 ac0aa23..52d9bad 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 9fa4c84..4d9e6bf 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 b288d52..1a686d9 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 c55b9ff..9b8b4f7 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 8ba08d8..439ca3f 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 f3530d5..3d703da 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 e6451f4..78fefb3 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 71d08a2..20148cc 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 e20936e..0042325 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 ddfa8e9..e782dd2 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 308ca7f..d87d081 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 2bedd87..1040c10 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 12396b7..46e25c1 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 285f791..266b456 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 e37e9d4..54bca75 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 );


More information about the ooo-build-commit mailing list