[Libreoffice-commits] .: 18 commits - sc/inc sc/Library_sc.mk sc/qa sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Mon Sep 12 10:35:02 PDT 2011


 sc/Library_sc.mk                   |    1 
 sc/inc/document.hxx                |    2 
 sc/inc/rangelst.hxx                |   28 +--
 sc/qa/unit/ucalc.cxx               |    3 
 sc/source/core/data/document.cxx   |   17 +-
 sc/source/core/tool/rangelst.cxx   |   44 ++++++
 sc/source/ui/docshell/arealink.cxx |    5 
 sc/source/ui/docshell/dbdocfun.cxx |   24 +--
 sc/source/ui/docshell/dbdocimp.cxx |    2 
 sc/source/ui/docshell/docfunc.cxx  |    4 
 sc/source/ui/docshell/docsh3.cxx   |  110 ++++++++-------
 sc/source/ui/docshell/impex.cxx    |    5 
 sc/source/ui/inc/cellsh.hxx        |    2 
 sc/source/ui/inc/cliputil.hxx      |   51 +++++++
 sc/source/ui/inc/docsh.hxx         |    2 
 sc/source/ui/inc/undobase.hxx      |   21 ++
 sc/source/ui/inc/undoblk.hxx       |   40 ++---
 sc/source/ui/inc/viewfunc.hxx      |   14 +
 sc/source/ui/miscdlgs/crnrdlg.cxx  |    2 
 sc/source/ui/undo/undobase.cxx     |  110 +++++++++++++++
 sc/source/ui/undo/undoblk.cxx      |  180 +++++++++++++------------
 sc/source/ui/unoobj/cellsuno.cxx   |   12 -
 sc/source/ui/unoobj/confuno.cxx    |    2 
 sc/source/ui/unoobj/defltuno.cxx   |    2 
 sc/source/ui/view/cellsh.cxx       |   55 ++++++-
 sc/source/ui/view/cellsh1.cxx      |   53 -------
 sc/source/ui/view/cliputil.cxx     |  122 +++++++++++++++++
 sc/source/ui/view/dbfunc.cxx       |    8 -
 sc/source/ui/view/dbfunc3.cxx      |    9 -
 sc/source/ui/view/gridwin.cxx      |    3 
 sc/source/ui/view/viewfun3.cxx     |  262 +++++++++++++++++++++++++++++++------
 sc/source/ui/view/viewfun4.cxx     |    6 
 32 files changed, 877 insertions(+), 324 deletions(-)

New commits:
commit e9a73d9a10d1a0c4a6e0c9280b0d19c8bb8e7c86
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Sep 12 12:16:16 2011 -0400

    Modified GetClipState in ScCellShell to allow multiple dest ranges.

diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index b2fe280..531ac70 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -65,6 +65,8 @@
 #include "scabstdlg.hxx"
 #include "dociter.hxx"
 #include "postit.hxx"
+#include "cliputil.hxx"
+#include "clipparam.hxx"
 
 //------------------------------------------------------------------
 
@@ -444,6 +446,48 @@ IMPL_LINK( ScCellShell, ClipboardChanged, TransferableDataHelper*, pDataHelper )
     return 0;
 }
 
+namespace {
+
+bool checkDestRanges(ScViewData& rViewData)
+{
+    ScRange aDummy;
+    ScMarkType eMarkType = rViewData.GetSimpleArea( aDummy);
+    if (eMarkType != SC_MARK_MULTI)
+    {
+        // Single destination range.
+        if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
+            return false;
+    }
+
+    // Multiple destination ranges.
+
+    ScDocument* pDoc = rViewData.GetDocument();
+    Window* pWin = rViewData.GetActiveWin();
+    if (!pWin)
+        return false;
+
+    ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(pWin);
+    if (!pOwnClip)
+        // If it's not a Calc document, we won't be picky.
+        return true;
+
+    ScDocument* pClipDoc = pOwnClip->GetDocument();
+    if (!pClipDoc)
+        return false;
+
+    ScRange aSrcRange = pClipDoc->GetClipParam().getWholeRange();
+    SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
+    SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
+
+    ScMarkData aMark = rViewData.GetMarkData();
+    ScRangeList aRanges;
+    aMark.MarkToSimple();
+    aMark.FillRangeListWithMarks(&aRanges, false);
+
+    return ScClipUtil::CheckDestRanges(pDoc, nColSize, nRowSize, aMark, aRanges);
+}
+
+}
 
 void ScCellShell::GetClipState( SfxItemSet& rSet )
 {
@@ -464,7 +508,7 @@ void ScCellShell::GetClipState( SfxItemSet& rSet )
         bPastePossible = lcl_IsCellPastePossible( aDataHelper );
     }
 
-    sal_Bool bDisable = !bPastePossible;
+    bool bDisable = !bPastePossible;
 
     //  Zellschutz / Multiselektion
 
@@ -475,11 +519,10 @@ void ScCellShell::GetClipState( SfxItemSet& rSet )
         SCTAB nTab = GetViewData()->GetTabNo();
         ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument();
         if (!pDoc->IsBlockEditable( nTab, nCol,nRow, nCol,nRow ))
-            bDisable = sal_True;
-        ScRange aDummy;
-        ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy);
-        if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
-            bDisable = sal_True;
+            bDisable = true;
+
+        if (!checkDestRanges(*GetViewData()))
+            bDisable = true;
     }
 
     if (bDisable)
commit 458fd23a540465ad308300de250e118a4a7ef50f
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Sep 12 11:36:44 2011 -0400

    Moved the code that checks destination ranges to ScClipUtil.

diff --git a/sc/source/ui/inc/cliputil.hxx b/sc/source/ui/inc/cliputil.hxx
index 04a966c..f5ddc47 100644
--- a/sc/source/ui/inc/cliputil.hxx
+++ b/sc/source/ui/inc/cliputil.hxx
@@ -28,8 +28,13 @@
 #ifndef __SC_CLIPUTIL_HXX__
 #define __SC_CLIPUTIL_HXX__
 
+#include "address.hxx"
+
 class ScViewData;
 class ScTabViewShell;
+class ScDocument;
+class ScMarkData;
+class ScRangeList;
 
 class ScClipUtil
 {
@@ -37,6 +42,10 @@ class ScClipUtil
     ~ScClipUtil();
 public:
     static void PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTabViewShell, bool bShowDialog );
+
+    static bool CheckDestRanges(
+        ScDocument* pDoc, SCCOL nSrcCols, SCROW nSrcRows, const ScMarkData& rMark,
+        const ScRangeList& rDest);
 };
 
 #endif
diff --git a/sc/source/ui/view/cliputil.cxx b/sc/source/ui/view/cliputil.cxx
index d7a6f88..620b9c0 100644
--- a/sc/source/ui/view/cliputil.cxx
+++ b/sc/source/ui/view/cliputil.cxx
@@ -33,6 +33,8 @@
 #include "dpobject.hxx"
 #include "globstr.hrc"
 #include "clipparam.hxx"
+#include "rangelst.hxx"
+#include "viewutil.hxx"
 
 #include "vcl/waitobj.hxx"
 
@@ -85,3 +87,36 @@ void ScClipUtil::PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTab
     }
     pTabViewShell->CellContentChanged();        // => PasteFromSystem() ???
 }
+
+bool ScClipUtil::CheckDestRanges(
+    ScDocument* pDoc, SCCOL nSrcCols, SCROW nSrcRows, const ScMarkData& rMark, const ScRangeList& rDest)
+{
+    for (size_t i = 0, n = rDest.size(); i < n; ++i)
+    {
+        ScRange aTest = *rDest[i];
+        // Check for filtered rows in all selected sheets.
+        ScMarkData::const_iterator itrTab = rMark.begin(), itrTabEnd = rMark.end();
+        for (; itrTab != itrTabEnd; ++itrTab)
+        {
+            aTest.aStart.SetTab(*itrTab);
+            aTest.aEnd.SetTab(*itrTab);
+            if (ScViewUtil::HasFiltered(aTest, pDoc))
+            {
+                // I don't know how to handle pasting into filtered rows yet.
+                return false;
+            }
+        }
+
+        // Destination range must be an exact multiple of the source range.
+        SCROW nRows = aTest.aEnd.Row() - aTest.aStart.Row() + 1;
+        SCCOL nCols = aTest.aEnd.Col() - aTest.aStart.Col() + 1;
+        SCROW nRowTest = (nRows / nSrcRows) * nSrcRows;
+        SCCOL nColTest = (nCols / nSrcCols) * nSrcCols;
+        if (nRows != nRowTest || nCols != nColTest)
+        {
+            // Destination range is not a multiple of the source range. Bail out.
+            return false;
+        }
+    }
+    return true;
+}
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index aaa07f9..028b68c 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -182,6 +182,7 @@
 #include "clipparam.hxx"
 #include "undodat.hxx"
 #include "drawview.hxx"
+#include "cliputil.hxx"
 
 using namespace com::sun::star;
 
@@ -1736,34 +1737,10 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
     ScRangeList aRanges;
     aMark.MarkToSimple();
     aMark.FillRangeListWithMarks(&aRanges, false);
-    for (size_t i = 0, n = aRanges.size(); i < n; ++i)
+    if (!ScClipUtil::CheckDestRanges(pDoc, nColSize, nRowSize, aMark, aRanges))
     {
-        ScRange aTest = *aRanges[i];
-        // Check for filtered rows in all selected sheets.
-        ScMarkData::const_iterator itrTab = aMark.begin(), itrTabEnd = aMark.end();
-        for (; itrTab != itrTabEnd; ++itrTab)
-        {
-            aTest.aStart.SetTab(*itrTab);
-            aTest.aEnd.SetTab(*itrTab);
-            if (ScViewUtil::HasFiltered(aTest, pDoc))
-            {
-                // I don't know how to handle pasting into filtered rows yet.
-                ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
-                return false;
-            }
-        }
-
-        // Destination range must be an exact multiple of the source range.
-        SCROW nRows = aTest.aEnd.Row() - aTest.aStart.Row() + 1;
-        SCCOL nCols = aTest.aEnd.Col() - aTest.aStart.Col() + 1;
-        SCROW nRowTest = (nRows / nRowSize) * nRowSize;
-        SCCOL nColTest = (nCols / nColSize) * nColSize;
-        if (nRows != nRowTest || nCols != nColTest)
-        {
-            // Destination range is not a multiple of the source range. Bail out.
-            ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
-            return false;
-        }
+        ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
+        return false;
     }
 
     ScDocShell* pDocSh = rViewData.GetDocShell();
commit abccf9b8e5f331a27f188ec5246a9e0f64f287dd
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Sep 12 11:18:07 2011 -0400

    Moved PasteFromClipboard() from ScCellShell to ScClipUtil (new class).

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 70cd612..27b142f 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -472,6 +472,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
 	sc/source/ui/view/cellsh3 \
 	sc/source/ui/view/cellsh4 \
 	sc/source/ui/view/colrowba \
+	sc/source/ui/view/cliputil \
 	sc/source/ui/view/dbfunc \
 	sc/source/ui/view/dbfunc2 \
 	sc/source/ui/view/dbfunc3 \
diff --git a/sc/source/ui/inc/cellsh.hxx b/sc/source/ui/inc/cellsh.hxx
index b7cc54f..2666029 100644
--- a/sc/source/ui/inc/cellsh.hxx
+++ b/sc/source/ui/inc/cellsh.hxx
@@ -108,8 +108,6 @@ 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/cliputil.hxx b/sc/source/ui/inc/cliputil.hxx
new file mode 100644
index 0000000..04a966c
--- /dev/null
+++ b/sc/source/ui/inc/cliputil.hxx
@@ -0,0 +1,42 @@
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ *   Copyright (C) 2011 Kohei Yoshida <kohei.yoshida at suse.com>
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#ifndef __SC_CLIPUTIL_HXX__
+#define __SC_CLIPUTIL_HXX__
+
+class ScViewData;
+class ScTabViewShell;
+
+class ScClipUtil
+{
+    ScClipUtil();
+    ~ScClipUtil();
+public:
+    static void PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTabViewShell, bool bShowDialog );
+};
+
+#endif
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index a959020..8a703b8 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -100,6 +100,7 @@
 #include "dpshttab.hxx"     // ScSheetSourceDesc
 #include "dbdata.hxx"
 #include "docsh.hxx"
+#include "cliputil.hxx"
 
 #include "globstr.hrc"
 #include "scui_def.hxx"
@@ -1169,7 +1170,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
 
         case SID_PASTE:
             {
-                PasteFromClipboard ( GetViewData(), pTabViewShell, true );
+                ScClipUtil::PasteFromClipboard ( GetViewData(), pTabViewShell, true );
                 rReq.Done();
             }
             break;
@@ -2433,54 +2434,4 @@ 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, sal_True );
-        nClipEndX = nClipEndX + nClipStartX;
-        nClipEndY = nClipEndY + nClipStartY;   // GetClipArea returns the difference
-
-        ScRange aSource( nClipStartX, nClipStartY, nSourceTab, nClipEndX, nClipEndY, nSourceTab );
-        sal_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() ???
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/cliputil.cxx b/sc/source/ui/view/cliputil.cxx
new file mode 100644
index 0000000..d7a6f88
--- /dev/null
+++ b/sc/source/ui/view/cliputil.cxx
@@ -0,0 +1,87 @@
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ *   Copyright (C) 2011 Kohei Yoshida <kohei.yoshida at suse.com>
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#include "cliputil.hxx"
+#include "viewdata.hxx"
+#include "tabvwsh.hxx"
+#include "transobj.hxx"
+#include "document.hxx"
+#include "dpobject.hxx"
+#include "globstr.hrc"
+#include "clipparam.hxx"
+
+#include "vcl/waitobj.hxx"
+
+void ScClipUtil::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, sal_True );
+        nClipEndX = nClipEndX + nClipStartX;
+        nClipEndY = nClipEndY + nClipStartY;   // GetClipArea returns the difference
+
+        ScRange aSource( nClipStartX, nClipStartY, nSourceTab, nClipEndX, nClipEndY, nSourceTab );
+        sal_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/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 305a68e..1e66a2b 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -130,6 +130,7 @@
 #include "cellsuno.hxx"
 #include "drawview.hxx"
 #include "dragdata.hxx"
+#include "cliputil.hxx"
 
 #include <svx/sdrpagewindow.hxx>
 #include <svx/sdr/overlay/overlaymanager.hxx>
@@ -3044,7 +3045,7 @@ void ScGridWindow::KeyInput(const KeyEvent& rKEvt)
     else if( rKeyCode.GetCode() == KEY_RETURN && pViewData->IsPasteMode() )
     {
         ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
-        ScCellShell::PasteFromClipboard( pViewData, pTabViewShell, false );
+        ScClipUtil::PasteFromClipboard( pViewData, pTabViewShell, false );
 
         // Clear clipboard content.
         uno::Reference<datatransfer::clipboard::XClipboard> xSystemClipboard =
commit ea280cef9c5293a1865786a2e8736bb9524f8751
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Sat Sep 10 00:43:05 2011 -0400

    Added code to handle paste functions and skip empties.

diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index e839a70..aaa07f9 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -1792,6 +1792,21 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
         }
     }
 
+    std::auto_ptr<ScDocument> pMixDoc;
+    if (bSkipEmpty || nFunction)
+    {
+        if (nFlags & IDF_CONTENTS)
+        {
+            pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
+            pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
+            for (size_t i = 0, n = aRanges.size(); i < n; ++i)
+            {
+                pDoc->CopyToDocument(
+                    *aRanges[i], IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
+            }
+        }
+    }
+
     if (nFlags & IDF_OBJECTS)
         pDocSh->MakeDrawLayer();
     if (pDoc->IsUndoEnabled())
@@ -1807,6 +1822,12 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
             false, false, true, bSkipEmpty, NULL);
     }
 
+    if (pMixDoc.get())
+    {
+        for (size_t i = 0, n = aRanges.size(); i < n; ++i)
+            pDoc->MixDocument(*aRanges[i], nFunction, bSkipEmpty, pMixDoc.get());
+    }
+
     AdjustBlockHeight();            // update row heights before pasting objects
 
     // Then paste the objects.
commit 463b1b56868474808eed087da1d1e542f2fed067
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Sat Sep 10 00:30:53 2011 -0400

    Allow paste when the dest range is a multiple of the source range.

diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index 2d0e78e..e839a70 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -1753,11 +1753,14 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
             }
         }
 
+        // Destination range must be an exact multiple of the source range.
         SCROW nRows = aTest.aEnd.Row() - aTest.aStart.Row() + 1;
         SCCOL nCols = aTest.aEnd.Col() - aTest.aStart.Col() + 1;
-        if (nRows != nRowSize || nCols != nColSize)
+        SCROW nRowTest = (nRows / nRowSize) * nRowSize;
+        SCCOL nColTest = (nCols / nColSize) * nColSize;
+        if (nRows != nRowTest || nCols != nColTest)
         {
-            // Source and destination sizes don't match.  Bail out.
+            // Destination range is not a multiple of the source range. Bail out.
             ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
             return false;
         }
commit f7d29b4494824a8560f062a704502e6d960bed4f
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Sat Sep 10 00:22:51 2011 -0400

    Properly mark multiple ranges during undo and redo.

diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx
index 5db3124..89d7160 100644
--- a/sc/source/ui/undo/undobase.cxx
+++ b/sc/source/ui/undo/undobase.cxx
@@ -372,15 +372,23 @@ void ScMultiBlockUndo::ShowBlock()
     if (maBlockRanges.empty())
         return;
 
-    // Show the very first range.
-    ScRange aRange = *maBlockRanges[0];
+    // Move to the sheet of the first range.
+    ScRange aRange = *maBlockRanges.front();
     ShowTable(aRange);
     pViewShell->MoveCursorAbs(
         aRange.aStart.Col(), aRange.aStart.Row(), SC_FOLLOW_JUMP, false, false);
     SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
     aRange.aStart.SetTab(nTab);
     aRange.aEnd.SetTab(nTab);
-    pViewShell->MarkRange(aRange);
+    pViewShell->MarkRange(aRange, false, false);
+
+    for (size_t i = 1, n = maBlockRanges.size(); i < n; ++i)
+    {
+        aRange = *maBlockRanges[i];
+        aRange.aStart.SetTab(nTab);
+        aRange.aEnd.SetTab(nTab);
+        pViewShell->MarkRange(aRange, false, true);
+    }
 }
 
 // -----------------------------------------------------------------------
commit 64340f4c2b7aa25a9f9e98ad2668df13660c08d1
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 23:34:08 2011 -0400

    Now I can pass range list to PostPaint() when appropriate.

diff --git a/sc/source/core/tool/rangelst.cxx b/sc/source/core/tool/rangelst.cxx
index 9a6ded0..e02dd11 100644
--- a/sc/source/core/tool/rangelst.cxx
+++ b/sc/source/core/tool/rangelst.cxx
@@ -492,15 +492,20 @@ ScRange ScRangeList::Combine() const
     {
         const ScRange& r = **itr;
         SCROW nRow1 = r.aStart.Row(), nRow2 = r.aEnd.Row();
-        SCROW nCol1 = r.aStart.Col(), nCol2 = r.aEnd.Col();
+        SCCOL nCol1 = r.aStart.Col(), nCol2 = r.aEnd.Col();
+        SCTAB nTab1 = r.aStart.Tab(), nTab2 = r.aEnd.Tab();
         if (aRet.aStart.Row() > nRow1)
             aRet.aStart.SetRow(nRow1);
         if (aRet.aStart.Col() > nCol1)
             aRet.aStart.SetCol(nCol1);
+        if (aRet.aStart.Tab() > nTab1)
+            aRet.aStart.SetTab(nTab1);
         if (aRet.aEnd.Row() < nRow2)
             aRet.aEnd.SetRow(nRow2);
         if (aRet.aEnd.Col() < nCol2)
             aRet.aEnd.SetCol(nCol2);
+        if (aRet.aEnd.Tab() < nTab2)
+            aRet.aEnd.SetTab(nTab2);
     }
     return aRet;
 }
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index e5c6151..32e223f 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -1093,7 +1093,7 @@ void ScUndoPaste::DoChange(bool bUndo)
     if ( !bUndo )                               //   draw redo after updating row heights
         RedoSdrUndoAction(mpDrawUndo);
 
-    pDocShell->PostPaint(aDrawRanges.Combine(), nPaint, nExtFlags);
+    pDocShell->PostPaint(aDrawRanges, nPaint, nExtFlags);
 
     pDocShell->PostDataChanged();
     if (pViewShell)
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index 80019d2..2d0e78e 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -1819,10 +1819,7 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
 
     // Refresh the range that includes all pasted ranges.  We only need to
     // refresh the current sheet.
-    ScRange aWholeRange = aRanges.Combine();
-    aWholeRange.aStart.SetTab(rViewData.GetTabNo());
-    aWholeRange.aEnd.SetTab(rViewData.GetTabNo());
-    pDocSh->PostPaint(aWholeRange, PAINT_GRID);
+    pDocSh->PostPaint(aRanges, PAINT_GRID);
 
     if (pDoc->IsUndoEnabled())
     {
commit a6d2e1ef128b375a76997f6fcc9b9c29a9dedc24
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 23:23:24 2011 -0400

    ResetChanged() now takes range list.

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 53d796d..64ceab9 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -863,7 +863,7 @@ public:
                                     const ::editeng::SvxBorderLine** ppRight,
                                     const ::editeng::SvxBorderLine** ppBottom ) const;
 
-    void            ResetChanged( const ScRange& rRange );
+    void            ResetChanged( const ScRangeList& rRanges );
 
     void            SetDirty();
     void            SetDirty( const ScRange& );
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 5522ac1..0b561ab 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -3490,13 +3490,18 @@ sal_uInt16 ScDocument::GetErrCode( const ScAddress& rPos ) const
 }
 
 
-void ScDocument::ResetChanged( const ScRange& rRange )
+void ScDocument::ResetChanged( const ScRangeList& rRanges )
 {
-    SCTAB nStartTab = rRange.aStart.Tab();
-    SCTAB nEndTab = rRange.aEnd.Tab();
-    for (SCTAB nTab=nStartTab; nTab<=nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++)
-        if (maTabs[nTab])
-            maTabs[nTab]->ResetChanged( rRange );
+    SCTAB nTabSize = static_cast<SCTAB>(maTabs.size());
+    for (size_t i = 0, n = rRanges.size(); i < n; ++i)
+    {
+        const ScRange& rRange = *rRanges[i];
+        SCTAB nTab1 = rRange.aStart.Tab();
+        SCTAB nTab2 = rRange.aEnd.Tab();
+        for (SCTAB nTab = nTab1; nTab1 <= nTab2 && nTab < nTabSize; ++nTab)
+            if (maTabs[nTab])
+                maTabs[nTab]->ResetChanged(rRange);
+    }
 }
 
 //
diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx
index 3b71f72..49b5f45 100644
--- a/sc/source/ui/docshell/docsh3.cxx
+++ b/sc/source/ui/docshell/docsh3.cxx
@@ -182,14 +182,10 @@ void ScDocShell::PostPaint( const ScRangeList& rRanges, sal_uInt16 nPart, sal_uI
         aPaintRanges.Append(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
     }
 
-    for (size_t i = 0, n = aPaintRanges.size(); i < n; ++i)
-    {
-        const ScRange& r = *aPaintRanges[i];
-        Broadcast(ScPaintHint(r, nPart));
+    Broadcast(ScPaintHint(aPaintRanges.Combine(), nPart));
 
-        if (nPart & PAINT_GRID)
-            aDocument.ResetChanged(r);
-    }
+    if (nPart & PAINT_GRID)
+        aDocument.ResetChanged(aPaintRanges);
 }
 
 void ScDocShell::PostPaintGridAll()
commit bc0afba780200f61462d7aeba40ca82ebb4bb21f
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 23:02:00 2011 -0400

    PostPaint() now takes range list.

diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx
index fc9ab4a..3b71f72 100644
--- a/sc/source/ui/docshell/docsh3.cxx
+++ b/sc/source/ui/docshell/docsh3.cxx
@@ -118,69 +118,78 @@ void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
     PostPaint(aRange, nPart, nExtFlags);
 }
 
-void ScDocShell::PostPaint( const ScRange& rRange, sal_uInt16 nPart, sal_uInt16 nExtFlags )
+void ScDocShell::PostPaint( const ScRangeList& rRanges, sal_uInt16 nPart, sal_uInt16 nExtFlags )
 {
-    SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
-    SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
-    SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
+    ScRangeList aPaintRanges;
+    for (size_t i = 0, n = rRanges.size(); i < n; ++i)
+    {
+        const ScRange& rRange = *rRanges[i];
+        SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
+        SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
+        SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
 
-    if (!ValidCol(nCol1)) nCol1 = MAXCOL;
-    if (!ValidRow(nRow1)) nRow1 = MAXROW;
-    if (!ValidCol(nCol2)) nCol2 = MAXCOL;
-    if (!ValidRow(nRow2)) nRow2 = MAXROW;
+        if (!ValidCol(nCol1)) nCol1 = MAXCOL;
+        if (!ValidRow(nRow1)) nRow1 = MAXROW;
+        if (!ValidCol(nCol2)) nCol2 = MAXCOL;
+        if (!ValidRow(nRow2)) nRow2 = MAXROW;
 
-    if ( pPaintLockData )
-    {
-        // #i54081# PAINT_EXTRAS still has to be brodcast because it changes the
-        // current sheet if it's invalid. All other flags added to pPaintLockData.
-        sal_uInt16 nLockPart = nPart & ~PAINT_EXTRAS;
-        if ( nLockPart )
+        if ( pPaintLockData )
         {
-            //! nExtFlags ???
-            pPaintLockData->AddRange( ScRange( nCol1, nRow1, nTab1,
-                                               nCol2, nRow2, nTab2 ), nLockPart );
-        }
+            // #i54081# PAINT_EXTRAS still has to be brodcast because it changes the
+            // current sheet if it's invalid. All other flags added to pPaintLockData.
+            sal_uInt16 nLockPart = nPart & ~PAINT_EXTRAS;
+            if ( nLockPart )
+            {
+                //! nExtFlags ???
+                pPaintLockData->AddRange( ScRange( nCol1, nRow1, nTab1,
+                                                   nCol2, nRow2, nTab2 ), nLockPart );
+            }
 
-        nPart &= PAINT_EXTRAS;  // for broadcasting
-        if ( !nPart )
-            return;
-    }
+            nPart &= PAINT_EXTRAS;  // for broadcasting
+            if (!nPart)
+                continue;
+        }
 
 
-    if (nExtFlags & SC_PF_LINES)            // Platz fuer Linien beruecksichtigen
-    {
-                                            //! Abfrage auf versteckte Spalten/Zeilen!
-        if (nCol1>0) --nCol1;
-        if (nCol2<MAXCOL) ++nCol2;
-        if (nRow1>0) --nRow1;
-        if (nRow2<MAXROW) ++nRow2;
-    }
+        if (nExtFlags & SC_PF_LINES)            // Platz fuer Linien beruecksichtigen
+        {
+                                                //! Abfrage auf versteckte Spalten/Zeilen!
+            if (nCol1>0) --nCol1;
+            if (nCol2<MAXCOL) ++nCol2;
+            if (nRow1>0) --nRow1;
+            if (nRow2<MAXROW) ++nRow2;
+        }
 
-                                            // um zusammengefasste erweitern
-    if (nExtFlags & SC_PF_TESTMERGE)
-        aDocument.ExtendMerge( nCol1, nRow1, nCol2, nRow2, nTab1 );
+                                                // um zusammengefasste erweitern
+        if (nExtFlags & SC_PF_TESTMERGE)
+            aDocument.ExtendMerge( nCol1, nRow1, nCol2, nRow2, nTab1 );
 
-    if ( nCol1 != 0 || nCol2 != MAXCOL )
-    {
-        //  Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
-        //  aligned cells are contained (see UpdatePaintExt).
-        //  Special handling for RTL text (#i9731#) is unnecessary now with full
-        //  support of right-aligned text.
-
-        if ( ( nExtFlags & SC_PF_WHOLEROWS ) ||
-             aDocument.HasAttrib( nCol1,nRow1,nTab1,
-                                  MAXCOL,nRow2,nTab2, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
+        if ( nCol1 != 0 || nCol2 != MAXCOL )
         {
-            nCol1 = 0;
-            nCol2 = MAXCOL;
+            //  Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
+            //  aligned cells are contained (see UpdatePaintExt).
+            //  Special handling for RTL text (#i9731#) is unnecessary now with full
+            //  support of right-aligned text.
+
+            if ( ( nExtFlags & SC_PF_WHOLEROWS ) ||
+                 aDocument.HasAttrib( nCol1,nRow1,nTab1,
+                                      MAXCOL,nRow2,nTab2, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
+            {
+                nCol1 = 0;
+                nCol2 = MAXCOL;
+            }
         }
+        aPaintRanges.Append(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
     }
 
-    Broadcast( ScPaintHint( ScRange( nCol1, nRow1, nTab1,
-                                     nCol2, nRow2, nTab2 ), nPart ) );
+    for (size_t i = 0, n = aPaintRanges.size(); i < n; ++i)
+    {
+        const ScRange& r = *aPaintRanges[i];
+        Broadcast(ScPaintHint(r, nPart));
 
-    if ( nPart & PAINT_GRID )
-        aDocument.ResetChanged( ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2) );
+        if (nPart & PAINT_GRID)
+            aDocument.ResetChanged(r);
+    }
 }
 
 void ScDocShell::PostPaintGridAll()
diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx
index e03bb84..c3b5c93 100644
--- a/sc/source/ui/inc/docsh.hxx
+++ b/sc/source/ui/inc/docsh.hxx
@@ -334,7 +334,7 @@ public:
     void            PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
                             SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, sal_uInt16 nPart,
                             sal_uInt16 nExtFlags = 0 );
-    void            PostPaint( const ScRange& rRange, sal_uInt16 nPart, sal_uInt16 nExtFlags = 0 );
+    void            PostPaint( const ScRangeList& rRanges, sal_uInt16 nPart, sal_uInt16 nExtFlags = 0 );
 
     void            PostPaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab );
     void            PostPaintCell( const ScAddress& rPos );
commit 1920e46282dc096153304d75e2a684d23a3b962c
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 22:14:37 2011 -0400

    Swapped the 8-param and 3-param variants of PostPaint().

diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx
index 9034e39..fc9ab4a 100644
--- a/sc/source/ui/docshell/docsh3.cxx
+++ b/sc/source/ui/docshell/docsh3.cxx
@@ -114,10 +114,20 @@ void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
                             SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, sal_uInt16 nPart,
                             sal_uInt16 nExtFlags )
 {
-    if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
-    if (!ValidRow(nStartRow)) nStartRow = MAXROW;
-    if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
-    if (!ValidRow(nEndRow)) nEndRow = MAXROW;
+    ScRange aRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
+    PostPaint(aRange, nPart, nExtFlags);
+}
+
+void ScDocShell::PostPaint( const ScRange& rRange, sal_uInt16 nPart, sal_uInt16 nExtFlags )
+{
+    SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
+    SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
+    SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
+
+    if (!ValidCol(nCol1)) nCol1 = MAXCOL;
+    if (!ValidRow(nRow1)) nRow1 = MAXROW;
+    if (!ValidCol(nCol2)) nCol2 = MAXCOL;
+    if (!ValidRow(nRow2)) nRow2 = MAXROW;
 
     if ( pPaintLockData )
     {
@@ -127,8 +137,8 @@ void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
         if ( nLockPart )
         {
             //! nExtFlags ???
-            pPaintLockData->AddRange( ScRange( nStartCol, nStartRow, nStartTab,
-                                               nEndCol, nEndRow, nEndTab ), nLockPart );
+            pPaintLockData->AddRange( ScRange( nCol1, nRow1, nTab1,
+                                               nCol2, nRow2, nTab2 ), nLockPart );
         }
 
         nPart &= PAINT_EXTRAS;  // for broadcasting
@@ -140,17 +150,17 @@ void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
     if (nExtFlags & SC_PF_LINES)            // Platz fuer Linien beruecksichtigen
     {
                                             //! Abfrage auf versteckte Spalten/Zeilen!
-        if (nStartCol>0) --nStartCol;
-        if (nEndCol<MAXCOL) ++nEndCol;
-        if (nStartRow>0) --nStartRow;
-        if (nEndRow<MAXROW) ++nEndRow;
+        if (nCol1>0) --nCol1;
+        if (nCol2<MAXCOL) ++nCol2;
+        if (nRow1>0) --nRow1;
+        if (nRow2<MAXROW) ++nRow2;
     }
 
                                             // um zusammengefasste erweitern
     if (nExtFlags & SC_PF_TESTMERGE)
-        aDocument.ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nStartTab );
+        aDocument.ExtendMerge( nCol1, nRow1, nCol2, nRow2, nTab1 );
 
-    if ( nStartCol != 0 || nEndCol != MAXCOL )
+    if ( nCol1 != 0 || nCol2 != MAXCOL )
     {
         //  Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
         //  aligned cells are contained (see UpdatePaintExt).
@@ -158,26 +168,19 @@ void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
         //  support of right-aligned text.
 
         if ( ( nExtFlags & SC_PF_WHOLEROWS ) ||
-             aDocument.HasAttrib( nStartCol,nStartRow,nStartTab,
-                                  MAXCOL,nEndRow,nEndTab, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
+             aDocument.HasAttrib( nCol1,nRow1,nTab1,
+                                  MAXCOL,nRow2,nTab2, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
         {
-            nStartCol = 0;
-            nEndCol = MAXCOL;
+            nCol1 = 0;
+            nCol2 = MAXCOL;
         }
     }
 
-    Broadcast( ScPaintHint( ScRange( nStartCol, nStartRow, nStartTab,
-                                     nEndCol, nEndRow, nEndTab ), nPart ) );
+    Broadcast( ScPaintHint( ScRange( nCol1, nRow1, nTab1,
+                                     nCol2, nRow2, nTab2 ), nPart ) );
 
     if ( nPart & PAINT_GRID )
-        aDocument.ResetChanged( ScRange(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) );
-}
-
-void ScDocShell::PostPaint( const ScRange& rRange, sal_uInt16 nPart, sal_uInt16 nExtFlags )
-{
-    PostPaint( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
-               rRange.aEnd.Col(),   rRange.aEnd.Row(),   rRange.aEnd.Tab(),
-               nPart, nExtFlags );
+        aDocument.ResetChanged( ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2) );
 }
 
 void ScDocShell::PostPaintGridAll()
commit f1f4c877304cf3cd040d5402481a9ff6c73a0ab9
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 22:08:28 2011 -0400

    Some attempts to remove the 8-param variant of PostPaint().
    
    But there are way too many codes calling that one.  Maybe someday...

diff --git a/sc/source/ui/docshell/arealink.cxx b/sc/source/ui/docshell/arealink.cxx
index 9928ea7..1fe0b98 100644
--- a/sc/source/ui/docshell/arealink.cxx
+++ b/sc/source/ui/docshell/arealink.cxx
@@ -473,8 +473,9 @@ sal_Bool ScAreaLink::Refresh( const String& rNewFile, const String& rNewFilter,
             nPaintEndY = MAXROW;
 
         if ( !pImpl->m_pDocSh->AdjustRowHeight( aDestPos.Row(), nPaintEndY, nDestTab ) )
-            pImpl->m_pDocSh->PostPaint( aDestPos.Col(),aDestPos.Row(),nDestTab,
-                                    nPaintEndX,nPaintEndY,nDestTab, PAINT_GRID );
+            pImpl->m_pDocSh->PostPaint(
+                ScRange(aDestPos.Col(), aDestPos.Row(), nDestTab, nPaintEndX, nPaintEndY, nDestTab),
+                PAINT_GRID);
         aModificator.SetDocumentModified();
     }
     else
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index 5cc9e77..6bf85b5 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -419,8 +419,8 @@ bool ScDBDocFunc::RepeatDB( const ::rtl::OUString& rDBName, bool bRecord, bool b
                                             pOld, pNew ) );
             }
 
-            rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
-                                    PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
+            rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab),
+                                PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
             bDone = sal_True;
         }
         else if (!bApi)     // "Keine Operationen auszufuehren"
@@ -654,7 +654,7 @@ sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
             if ( nEndY < aOldDest.aEnd.Row() )
                 nEndY = aOldDest.aEnd.Row();
         }
-        rDocShell.PostPaint( nStartX, nStartY, nTab, nEndX, nEndY, nTab, nPaint );
+        rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint);
     }
 
     //  AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, bPaint );
@@ -991,12 +991,14 @@ sal_Bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
         }
         if (bDoSize)
             nEndY = MAXROW;
-        rDocShell.PostPaint( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
-                                    nEndX, nEndY, nDestTab, PAINT_GRID );
+        rDocShell.PostPaint(
+            ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, nEndX, nEndY, nDestTab),
+            PAINT_GRID);
     }
     else
-        rDocShell.PostPaint( 0, rQueryParam.nRow1, nTab, MAXCOL, MAXROW, nTab,
-                                                PAINT_GRID | PAINT_LEFT );
+        rDocShell.PostPaint(
+            ScRange(0, rQueryParam.nRow1, nTab, MAXCOL, MAXROW, nTab),
+            PAINT_GRID | PAINT_LEFT);
     aModificator.SetDocumentModified();
 
     return sal_True;
@@ -1159,8 +1161,8 @@ sal_Bool ScDBDocFunc::DoSubTotals( SCTAB nTab, const ScSubTotalParam& rParam,
         pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
         pDoc->CompileDBFormula();
 
-        rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
-                                                PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
+        rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL,MAXROW,nTab),
+                            PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
         aModificator.SetDocumentModified();
 
         bRet = bSuccess;
@@ -1259,9 +1261,7 @@ sal_Bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pN
             pDoc->GetDPCollection()->FreeTable( pOldObj );  // object is deleted here
 
             rDocShell.PostPaintGridAll();   //! only necessary parts
-            rDocShell.PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), nTab,
-                                 aRange.aEnd.Col(),   aRange.aEnd.Row(),   nTab,
-                                 PAINT_GRID );
+            rDocShell.PostPaint(aRange, PAINT_GRID);
             bDone = sal_True;
         }
         else if ( pNewObj )
diff --git a/sc/source/ui/docshell/dbdocimp.cxx b/sc/source/ui/docshell/dbdocimp.cxx
index 88a1a54..1dc6c1c 100644
--- a/sc/source/ui/docshell/dbdocimp.cxx
+++ b/sc/source/ui/docshell/dbdocimp.cxx
@@ -682,7 +682,7 @@ bool ScDBDocFunc::DoImport( SCTAB nTab, const ScImportParam& rParam,
         }
 
         pDoc->SetDirty();
-        rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
+        rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab), PAINT_GRID);
         aModificator.SetDocumentModified();
 
         ScDBRangeRefreshedHint aHint( rParam );
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index dbb567f..6dad099 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -178,8 +178,8 @@ sal_Bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, sal_Bool bPaint )
                                             aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, false );
 
     if ( bPaint && bChanged )
-        rDocShell.PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
-                                            PAINT_GRID | PAINT_LEFT );
+        rDocShell.PostPaint(ScRange(0, nStartRow, nTab, MAXCOL, MAXROW, nTab),
+                            PAINT_GRID | PAINT_LEFT);
 
     return bChanged;
 }
diff --git a/sc/source/ui/miscdlgs/crnrdlg.cxx b/sc/source/ui/miscdlgs/crnrdlg.cxx
index 49fbe93..ebe2bb1 100644
--- a/sc/source/ui/miscdlgs/crnrdlg.cxx
+++ b/sc/source/ui/miscdlgs/crnrdlg.cxx
@@ -720,7 +720,7 @@ IMPL_LINK( ScColRowNameRangesDlg, OkBtnHdl, void *, EMPTYARG )
     // geaenderte Datenbereiche muessen sich auswirken
     pDoc->CompileColRowNameFormula();
     ScDocShell* pDocShell = pViewData->GetDocShell();
-    pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID );
+    pDocShell->PostPaint(ScRange(0, 0, 0, MAXCOL, MAXROW, MAXTAB), PAINT_GRID);
     pDocShell->SetDocumentModified();
 
     Close();
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 294d426..52587e5 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -7196,7 +7196,7 @@ void SAL_CALL ScTableSheetObj::removeAllManualPageBreaks() throw(uno::RuntimeExc
 
         //? UpdatePageBreakData( sal_True );
         pDocSh->SetDocumentModified();
-        pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
+        pDocSh->PostPaint(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab), PAINT_GRID);
     }
 }
 
diff --git a/sc/source/ui/unoobj/confuno.cxx b/sc/source/ui/unoobj/confuno.cxx
index fc05a9a..c8f0bf2 100644
--- a/sc/source/ui/unoobj/confuno.cxx
+++ b/sc/source/ui/unoobj/confuno.cxx
@@ -320,7 +320,7 @@ void SAL_CALL ScDocumentConfiguration::setPropertyValue(
                 SCTAB nTabCount = pDoc->GetTableCount();
                 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
                     if ( !pDocShell->AdjustRowHeight( 0, MAXROW, nTab ) )
-                        pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
+                        pDocShell->PostPaint(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab), PAINT_GRID);
                 pDocShell->SetDocumentModified();
             }
         }
diff --git a/sc/source/ui/unoobj/defltuno.cxx b/sc/source/ui/unoobj/defltuno.cxx
index 71193ff..916d958 100644
--- a/sc/source/ui/unoobj/defltuno.cxx
+++ b/sc/source/ui/unoobj/defltuno.cxx
@@ -120,7 +120,7 @@ void ScDocDefaultsObj::ItemsChanged()
     {
         //! if not in XML import, adjust row heights
 
-        pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID );
+        pDocShell->PostPaint(ScRange(0, 0, 0, MAXCOL, MAXROW, MAXTAB), PAINT_GRID);
     }
 }
 
diff --git a/sc/source/ui/view/dbfunc.cxx b/sc/source/ui/view/dbfunc.cxx
index c1b5502..23ac9a9 100644
--- a/sc/source/ui/view/dbfunc.cxx
+++ b/sc/source/ui/view/dbfunc.cxx
@@ -243,7 +243,7 @@ void ScDBFunc::NotifyCloseDbNameDlg( const ScDBCollection& rNewColl, const std::
     pDoc->SetDBCollection( new ScDBCollection( rNewColl ) );
     pDoc->CompileDBFormula( false );    // CompileFormulaString
     pOldColl = NULL;
-    pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID );
+    pDocShell->PostPaint(ScRange(0, 0, 0, MAXCOL, MAXROW, MAXTAB), PAINT_GRID);
     aModificator.SetDocumentModified();
     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
 
@@ -442,8 +442,8 @@ void ScDBFunc::ToggleAutoFilter()
                         GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->GetValue();
                 pDoc->ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr( nFlag | SC_MF_AUTO ) );
             }
-            pDocSh->PostPaint( aParam.nCol1, nRow, nTab, aParam.nCol2, nRow, nTab,
-                                                     PAINT_GRID );
+            pDocSh->PostPaint(ScRange(aParam.nCol1, nRow, nTab, aParam.nCol2, nRow, nTab),
+                              PAINT_GRID);
             bPaint = sal_True;
         }
         else
@@ -495,7 +495,7 @@ void ScDBFunc::HideAutoFilter()
 
     pDBData->SetAutoFilter(false);
 
-    pDocSh->PostPaint( nCol1,nRow1,nTab, nCol2,nRow1,nTab, PAINT_GRID );
+    pDocSh->PostPaint(ScRange(nCol1, nRow1, nTab, nCol2, nRow1, nTab), PAINT_GRID );
     aModificator.SetDocumentModified();
 
     SfxBindings& rBindings = GetViewData()->GetBindings();
diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx
index 0788988..9bacc39 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -560,8 +560,8 @@ void ScDBFunc::DoSubTotals( const ScSubTotalParam& rParam, sal_Bool bRecord,
                                     aNewParam.nCol2,aNewParam.nRow2,nTab ) );
         MarkDataChanged();
 
-        pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
-                                                PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
+        pDocSh->PostPaint(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab),
+                          PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
 
         aModificator.SetDocumentModified();
 
@@ -2324,8 +2324,9 @@ void ScDBFunc::RepeatDB( sal_Bool bRecord )
                                         pOld, pNew ) );
         }
 
-        GetViewData()->GetDocShell()->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
-                                                    PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
+        GetViewData()->GetDocShell()->PostPaint(
+            ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab),
+            PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
     }
     else        // "Keine Operationen auszufuehren"
         ErrorMessage(STR_MSSG_REPEATDB_0);
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index b914a2a..80019d2 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -1436,9 +1436,11 @@ bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
     if (bCutMode)
         if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX,
                                         nClipStartY+nClipSizeY, nStartTab ))
-            pDocSh->PostPaint( nClipStartX,nClipStartY,nStartTab,
-                                nClipStartX+nClipSizeX,nClipStartY,nStartTab,
-                                PAINT_GRID );
+        {
+            pDocSh->PostPaint(
+                ScRange(nClipStartX, nClipStartY, nStartTab, nClipStartX+nClipSizeX, nClipStartY, nStartTab),
+                PAINT_GRID );
+        }
 
     ShowCursor();                           // Cursor aendert sich !
 
@@ -1508,8 +1510,9 @@ bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
         nPaint |= PAINT_LEFT;
         nUndoEndRow = MAXROW;               // nur zum Zeichnen !
     }
-    pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
-                        nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags );
+    pDocSh->PostPaint(
+        ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
+        nPaint, nExtFlags);
     // AdjustBlockHeight has already been called above
 
     aModificator.SetDocumentModified();
@@ -1653,9 +1656,10 @@ bool ScViewFunc::PasteMultiRangesFromClip(
                                      true, false, false, true);
     }
 
-    pDocSh->PostPaint(
-        aMarkedRange.aStart.Col(), aMarkedRange.aStart.Row(), nTab1,
-        aMarkedRange.aEnd.Col(), aMarkedRange.aEnd.Row(), nTab1, PAINT_GRID);
+    ScRange aTmp = aMarkedRange;
+    aTmp.aStart.SetTab(nTab1);
+    aTmp.aEnd.SetTab(nTab1);
+    pDocSh->PostPaint(aTmp, PAINT_GRID);
 
     if (pDoc->IsUndoEnabled())
     {
@@ -2082,8 +2086,9 @@ void ScViewFunc::DataFormPutData( SCROW nCurrentRow ,
                 nUndoEndRow = MAXROW;                           // nur zum Zeichnen !
         }
 
-        pDocSh->PostPaint( nStartCol, nCurrentRow, nStartTab,
-                                                nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags );
+        pDocSh->PostPaint(
+            ScRange(nStartCol, nCurrentRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
+            nPaint, nExtFlags);
         pDocSh->UpdateOle(GetViewData());
     }
 }
commit cb0f9de5bce9622bd98582a6f69ceb10a93402c4
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 21:48:26 2011 -0400

    Pass multi-ranges to the undo object.

diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index dc33c8c..b914a2a 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -1835,7 +1835,7 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
         aOptions.eMoveMode  = eMoveMode;
 
         ScUndoPaste* pUndo = new ScUndoPaste(
-            pDocSh, aWholeRange, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
+            pDocSh, aRanges, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
 
         pUndoMgr->AddUndoAction(pUndo, false);
         pUndoMgr->LeaveListAction();
commit 64a36fd4f4085ed05e4c0ee40ac109452ff81a78
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 21:44:23 2011 -0400

    ScUndoPaste to handle multiple ranges.

diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx
index 8c74f28..255c59a 100644
--- a/sc/source/ui/inc/undoblk.hxx
+++ b/sc/source/ui/inc/undoblk.hxx
@@ -195,11 +195,11 @@ struct ScUndoPasteOptions
     {}
 };
 
-class ScUndoPaste: public ScBlockUndo
+class ScUndoPaste: public ScMultiBlockUndo
 {
 public:
     TYPEINFO();
-    ScUndoPaste(ScDocShell* pNewDocShell, const ScRange& rRange,
+    ScUndoPaste(ScDocShell* pNewDocShell, const ScRangeList& rRanges,
                 const ScMarkData& rMark,
                 ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc,
                 sal_uInt16 nNewFlags,
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index a5344a8..e5c6151 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -876,13 +876,13 @@ sal_Bool ScUndoCut::CanRepeat(SfxRepeatTarget& rTarget) const
 //      Einfuegen (Paste)
 //
 
-ScUndoPaste::ScUndoPaste( ScDocShell* pNewDocShell, const ScRange& rRange,
+ScUndoPaste::ScUndoPaste( ScDocShell* pNewDocShell, const ScRangeList& rRanges,
                 const ScMarkData& rMark,
                 ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc,
                 sal_uInt16 nNewFlags,
                 ScRefUndoData* pRefData,
                 bool bRedoIsFilled, const ScUndoPasteOptions* pOptions ) :
-    ScBlockUndo( pNewDocShell, rRange, SC_UNDO_SIMPLE ),
+    ScMultiBlockUndo( pNewDocShell, rRanges, SC_UNDO_SIMPLE ),
     aMarkData( rMark ),
     pUndoDoc( pNewUndoDoc ),
     pRedoDoc( pNewRedoDoc ),
@@ -891,13 +891,6 @@ ScUndoPaste::ScUndoPaste( ScDocShell* pNewDocShell, const ScRange& rRange,
     pRefRedoData( NULL ),
     bRedoFilled( bRedoIsFilled )
 {
-    //  pFill1,pFill2,pFill3 are there so the ctor calls for simple paste (without cutting)
-    //  don't have to be changed and branched for 641.
-    //  They can be removed later.
-
-    if ( !aMarkData.IsMarked() )                // no cell marked:
-        aMarkData.SetMarkArea( aBlockRange );   //  mark paste block
-
     if ( pRefUndoData )
         pRefUndoData->DeleteUnchanged( pDocShell->GetDocument() );
 
@@ -924,8 +917,13 @@ void ScUndoPaste::SetChangeTrack()
 {
     ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
     if ( pChangeTrack && (nFlags & IDF_CONTENTS) )
-        pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc,
-            nStartChangeAction, nEndChangeAction, SC_CACM_PASTE );
+    {
+        for (size_t i = 0, n = maBlockRanges.size(); i < n; ++i)
+        {
+            pChangeTrack->AppendContentRange(*maBlockRanges[i], pUndoDoc,
+                nStartChangeAction, nEndChangeAction, SC_CACM_PASTE );
+        }
+    }
     else
         nStartChangeAction = nEndChangeAction = 0;
 }
@@ -936,7 +934,7 @@ void ScUndoPaste::DoChange(bool bUndo)
 
     //  RefUndoData for redo is created before first undo
     //  (with DeleteUnchanged after the DoUndo call)
-    sal_Bool bCreateRedoData = ( bUndo && pRefUndoData && !pRefRedoData );
+    bool bCreateRedoData = ( bUndo && pRefUndoData && !pRefRedoData );
     if ( bCreateRedoData )
         pRefRedoData = new ScRefUndoData( pDoc );
 
@@ -952,63 +950,77 @@ void ScUndoPaste::DoChange(bool bUndo)
     // do not undo/redo objects and note captions, they are handled via drawing undo
     (nUndoFlags &= ~IDF_OBJECTS) |= IDF_NOCAPTIONS;
 
-    sal_Bool bPaintAll = false;
+    bool bPaintAll = false;
 
     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
 
-    // marking is in ScBlockUndo...
-    ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockRange );
-
     SCTAB nTabCount = pDoc->GetTableCount();
     if ( bUndo && !bRedoFilled )
     {
         if (!pRedoDoc)
         {
-            sal_Bool bColInfo = ( aBlockRange.aStart.Row()==0 && aBlockRange.aEnd.Row()==MAXROW );
-            sal_Bool bRowInfo = ( aBlockRange.aStart.Col()==0 && aBlockRange.aEnd.Col()==MAXCOL );
+            bool bColInfo = true;
+            bool bRowInfo = true;
+            for (size_t i = 0, n = maBlockRanges.size(); i < n; ++i)
+            {
+                const ScRange& r = *maBlockRanges[i];
+                bColInfo &= (r.aStart.Row() == 0 && r.aEnd.Row() == MAXROW);
+                bRowInfo &= (r.aStart.Col() == 0 && r.aEnd.Col() == MAXCOL);
+                if (!bColInfo && !bRowInfo)
+                    break;
+            }
 
             pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
             pRedoDoc->InitUndoSelected( pDoc, aMarkData, bColInfo, bRowInfo );
         }
         //  read "redo" data from the document in the first undo
         //  all sheets - CopyToDocument skips those that don't exist in pRedoDoc
-        ScRange aCopyRange = aBlockRange;
-        aCopyRange.aStart.SetTab(0);
-        aCopyRange.aEnd.SetTab(nTabCount-1);
-        pDoc->CopyToDocument( aCopyRange, nUndoFlags, false, pRedoDoc );
-        bRedoFilled = sal_True;
+        for (size_t i = 0, n = maBlockRanges.size(); i < n; ++i)
+        {
+            ScRange aCopyRange = *maBlockRanges[i];
+            aCopyRange.aStart.SetTab(0);
+            aCopyRange.aEnd.SetTab(nTabCount-1);
+            pDoc->CopyToDocument( aCopyRange, nUndoFlags, false, pRedoDoc );
+            bRedoFilled = true;
+        }
     }
 
     sal_uInt16 nExtFlags = 0;
-    pDocShell->UpdatePaintExt( nExtFlags, aBlockRange );
+    pDocShell->UpdatePaintExt(nExtFlags, maBlockRanges.Combine());
 
     aMarkData.MarkToMulti();
     pDoc->DeleteSelection( nUndoFlags, aMarkData );
     aMarkData.MarkToSimple();
 
     SCTAB nFirstSelected = aMarkData.GetFirstSelected();
-    ScRange aTabSelectRange = aBlockRange;
 
     if ( !bUndo && pRedoDoc )       // Redo: UndoToDocument before handling RefData
     {
-        aTabSelectRange.aStart.SetTab( nFirstSelected );
-        aTabSelectRange.aEnd.SetTab( nFirstSelected );
-        pRedoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, false, pDoc );
-        ScMarkData::iterator itr = aMarkData.begin(), itrEnd = aMarkData.end();
-        for (; itr != itrEnd && *itr < nTabCount; ++itr)
-            if (*itr != nFirstSelected)
+        for (size_t i = 0, n = maBlockRanges.size(); i < n; ++i)
+        {
+            ScRange aRange = *maBlockRanges[i];
+            aRange.aStart.SetTab(nFirstSelected);
+            aRange.aEnd.SetTab(nFirstSelected);
+            pRedoDoc->UndoToDocument(aRange, nUndoFlags, false, pDoc);
+            ScMarkData::iterator itr = aMarkData.begin(), itrEnd = aMarkData.end();
+            for (; itr != itrEnd && *itr < nTabCount; ++itr)
             {
-                aTabSelectRange.aStart.SetTab( *itr );
-                aTabSelectRange.aEnd.SetTab( *itr );
-                pRedoDoc->CopyToDocument( aTabSelectRange, nUndoFlags, false, pDoc );
+                if (*itr == nFirstSelected)
+                    continue;
+
+                aRange.aStart.SetTab(*itr);
+                aRange.aEnd.SetTab(*itr);
+                pRedoDoc->CopyToDocument( aRange, nUndoFlags, false, pDoc );
             }
+        }
     }
 
     if (pWorkRefData)
     {
-        pWorkRefData->DoUndo( pDoc, sal_True );     // sal_True = bSetChartRangeLists for SetChartListenerCollection
-        if ( pDoc->RefreshAutoFilter( 0,0, MAXCOL,MAXROW, aBlockRange.aStart.Tab() ) )
-            bPaintAll = sal_True;
+        pWorkRefData->DoUndo( pDoc, true );     // true = bSetChartRangeLists for SetChartListenerCollection
+        if (!maBlockRanges.empty() &&
+            pDoc->RefreshAutoFilter(0, 0, MAXCOL, MAXROW, maBlockRanges[0]->aStart.Tab()))
+            bPaintAll = true;
     }
 
     if ( bCreateRedoData && pRefRedoData )
@@ -1016,17 +1028,17 @@ void ScUndoPaste::DoChange(bool bUndo)
 
     if (bUndo)      // Undo: UndoToDocument after handling RefData
     {
-        aTabSelectRange.aStart.SetTab( nFirstSelected );
-        aTabSelectRange.aEnd.SetTab( nFirstSelected );
-        pUndoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, false, pDoc );
-        ScMarkData::iterator itr = aMarkData.begin(), itrEnd = aMarkData.end();
-        for (; itr != itrEnd && *itr < nTabCount; ++itr)
-            if (*itr != nFirstSelected)
+        for (size_t i = 0, n = maBlockRanges.size(); i < n; ++i)
+        {
+            ScRange aRange = *maBlockRanges[i];
+            ScMarkData::iterator itr = aMarkData.begin(), itrEnd = aMarkData.end();
+            for (; itr != itrEnd && *itr < nTabCount; ++itr)
             {
-                aTabSelectRange.aStart.SetTab( *itr );
-                aTabSelectRange.aEnd.SetTab( *itr );
-                pUndoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, false, pDoc );
+                aRange.aStart.SetTab(*itr);
+                aRange.aEnd.SetTab(*itr);
+                pUndoDoc->UndoToDocument(aRange, nUndoFlags, false, pDoc);
             }
+        }
     }
 
     if ( bUndo )
@@ -1038,46 +1050,50 @@ void ScUndoPaste::DoChange(bool bUndo)
     else
         SetChangeTrack();
 
-    ScRange aDrawRange( aBlockRange );
-    pDoc->ExtendMerge( aDrawRange, sal_True );      // only needed for single sheet (text/rtf etc.)
+    ScRangeList aDrawRanges(maBlockRanges);
     sal_uInt16 nPaint = PAINT_GRID;
-    if (bPaintAll)
+    for (size_t i = 0, n = aDrawRanges.size(); i < n; ++i)
     {
-        aDrawRange.aStart.SetCol(0);
-        aDrawRange.aStart.SetRow(0);
-        aDrawRange.aEnd.SetCol(MAXCOL);
-        aDrawRange.aEnd.SetRow(MAXROW);
-        nPaint |= PAINT_TOP | PAINT_LEFT;
-/*A*/   if (pViewShell)
-            pViewShell->AdjustBlockHeight(false);
-    }
-    else
-    {
-        if ( aBlockRange.aStart.Row() == 0 && aBlockRange.aEnd.Row() == MAXROW )    // ganze Spalte
+        ScRange& rDrawRange = *aDrawRanges[i];
+        pDoc->ExtendMerge(rDrawRange, true);      // only needed for single sheet (text/rtf etc.)
+        if (bPaintAll)
         {
-            nPaint |= PAINT_TOP;
-            aDrawRange.aEnd.SetCol(MAXCOL);
+            rDrawRange.aStart.SetCol(0);
+            rDrawRange.aStart.SetRow(0);
+            rDrawRange.aEnd.SetCol(MAXCOL);
+            rDrawRange.aEnd.SetRow(MAXROW);
+            nPaint |= PAINT_TOP | PAINT_LEFT;
+            if (pViewShell)
+                pViewShell->AdjustBlockHeight(false);
         }
-        if ( aBlockRange.aStart.Col() == 0 && aBlockRange.aEnd.Col() == MAXCOL )    // ganze Zeile
-        {
-            nPaint |= PAINT_LEFT;
-            aDrawRange.aEnd.SetRow(MAXROW);
-        }
-/*A*/   if ((pViewShell) && pViewShell->AdjustBlockHeight(false))
+        else
         {
-            aDrawRange.aStart.SetCol(0);
-            aDrawRange.aStart.SetRow(0);
-            aDrawRange.aEnd.SetCol(MAXCOL);
-            aDrawRange.aEnd.SetRow(MAXROW);
-            nPaint |= PAINT_LEFT;
+            if (maBlockRanges[i]->aStart.Row() == 0 && maBlockRanges[i]->aEnd.Row() == MAXROW) // whole column
+            {
+                nPaint |= PAINT_TOP;
+                rDrawRange.aEnd.SetCol(MAXCOL);
+            }
+            if (maBlockRanges[i]->aStart.Col() == 0 && maBlockRanges[i]->aEnd.Col() == MAXCOL) // whole row
+            {
+                nPaint |= PAINT_LEFT;
+                rDrawRange.aEnd.SetRow(MAXROW);
+            }
+            if (pViewShell && pViewShell->AdjustBlockHeight(false))
+            {
+                rDrawRange.aStart.SetCol(0);
+                rDrawRange.aStart.SetRow(0);
+                rDrawRange.aEnd.SetCol(MAXCOL);
+                rDrawRange.aEnd.SetRow(MAXROW);
+                nPaint |= PAINT_LEFT;
+            }
+            pDocShell->UpdatePaintExt(nExtFlags, rDrawRange);
         }
-        pDocShell->UpdatePaintExt( nExtFlags, aDrawRange );
     }
 
     if ( !bUndo )                               //   draw redo after updating row heights
-        RedoSdrUndoAction( pDrawUndo );         //! include in ScBlockUndo?
+        RedoSdrUndoAction(mpDrawUndo);
 
-    pDocShell->PostPaint( aDrawRange, nPaint, nExtFlags );
+    pDocShell->PostPaint(aDrawRanges.Combine(), nPaint, nExtFlags);
 
     pDocShell->PostDataChanged();
     if (pViewShell)
@@ -1087,8 +1103,9 @@ void ScUndoPaste::DoChange(bool bUndo)
 void ScUndoPaste::Undo()
 {
     BeginUndo();
-    DoChange( sal_True );
-    ShowTable( aBlockRange );
+    DoChange(true);
+    if (!maBlockRanges.empty())
+        ShowTable(*maBlockRanges.front());
     EndUndo();
     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
 }
commit 7e76086272078c6f7d420e4cdc22f5d5841095b2
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 18:27:16 2011 -0400

    ScPateUndo cleaned up.

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index ec03cd6..8b30366 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -2237,7 +2237,8 @@ void Test::testCopyPaste()
     ScMarkData aMarkData2;
     aMarkData2.SetMarkArea(aRange);
     ScRefUndoData* pRefUndoData= new ScRefUndoData(m_pDoc);
-    SfxUndoAction* pUndo = new ScUndoPaste(&m_xDocShRef, 0, 1, 1, 2, 1, 1, aMarkData2, pUndoDoc, NULL, IDF_ALL, pRefUndoData, NULL, NULL, NULL, false);
+    SfxUndoAction* pUndo = new ScUndoPaste(
+        &m_xDocShRef, ScRange(0, 1, 1, 2, 1, 1), aMarkData2, pUndoDoc, NULL, IDF_ALL, pRefUndoData, false);
     m_pDoc->CopyFromClip(aRange, aMarkData2, nFlags, NULL, pClipDoc);
 
     //check values after copying
diff --git a/sc/source/ui/docshell/impex.cxx b/sc/source/ui/docshell/impex.cxx
index 165fefe..830d832 100644
--- a/sc/source/ui/docshell/impex.cxx
+++ b/sc/source/ui/docshell/impex.cxx
@@ -269,10 +269,7 @@ void ScImportExport::EndPaste()
         ScMarkData aDestMark;
         aDestMark.SelectOneTable( aRange.aStart.Tab() );
         pDocSh->GetUndoManager()->AddUndoAction(
-            new ScUndoPaste( pDocSh,
-                aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(),
-                aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(), aDestMark,
-                pUndoDoc, pRedoDoc, IDF_ALL, NULL,NULL,NULL,NULL ) );
+            new ScUndoPaste(pDocSh, aRange, aDestMark, pUndoDoc, pRedoDoc, IDF_ALL, NULL));
     }
     pUndoDoc = NULL;
     if( pDocSh )
diff --git a/sc/source/ui/inc/undobase.hxx b/sc/source/ui/inc/undobase.hxx
index 6f4135c..f997c2a 100644
--- a/sc/source/ui/inc/undobase.hxx
+++ b/sc/source/ui/inc/undobase.hxx
@@ -97,6 +97,7 @@ protected:
 class ScMultiBlockUndo: public ScSimpleUndo
 {
 public:
+    TYPEINFO();
     ScMultiBlockUndo(ScDocShell* pDocSh, const ScRangeList& rRanges,
                      ScBlockUndoMode eBlockMode);
     virtual ~ScMultiBlockUndo();
diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx
index 16fc759..8c74f28 100644
--- a/sc/source/ui/inc/undoblk.hxx
+++ b/sc/source/ui/inc/undoblk.hxx
@@ -198,24 +198,22 @@ struct ScUndoPasteOptions
 class ScUndoPaste: public ScBlockUndo
 {
 public:
-                    TYPEINFO();
-                    ScUndoPaste( ScDocShell* pNewDocShell,
-                                 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
-                                 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
-                                 const ScMarkData& rMark,
-                                 ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc,
-                                 sal_uInt16 nNewFlags,
-                                 ScRefUndoData* pRefData, void* pFill1, void* pFill2, void* pFill3,
-                                 sal_Bool bRedoIsFilled = sal_True,
-                                 const ScUndoPasteOptions* pOptions = NULL );
-    virtual         ~ScUndoPaste();
-
-    virtual void    Undo();
-    virtual void    Redo();
-    virtual void    Repeat(SfxRepeatTarget& rTarget);
-    virtual sal_Bool    CanRepeat(SfxRepeatTarget& rTarget) const;
-
-    virtual String  GetComment() const;
+    TYPEINFO();
+    ScUndoPaste(ScDocShell* pNewDocShell, const ScRange& rRange,
+                const ScMarkData& rMark,
+                ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc,
+                sal_uInt16 nNewFlags,
+                ScRefUndoData* pRefData,
+                bool bRedoIsFilled = true,
+                const ScUndoPasteOptions* pOptions = NULL);
+    virtual ~ScUndoPaste();
+
+    virtual void Undo();
+    virtual void Redo();
+    virtual void Repeat(SfxRepeatTarget& rTarget);
+    virtual sal_Bool CanRepeat(SfxRepeatTarget& rTarget) const;
+
+    virtual String GetComment() const;
 
 private:
     ScMarkData      aMarkData;
@@ -229,8 +227,8 @@ private:
     sal_Bool            bRedoFilled;
     ScUndoPasteOptions aPasteOptions;
 
-    void            DoChange( const sal_Bool bUndo );
-    void            SetChangeTrack();
+    void DoChange(bool bUndo);
+    void SetChangeTrack();
 };
 
 
diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx
index 42487b2..5db3124 100644
--- a/sc/source/ui/undo/undobase.cxx
+++ b/sc/source/ui/undo/undobase.cxx
@@ -51,6 +51,7 @@
 
 TYPEINIT1(ScSimpleUndo,     SfxUndoAction);
 TYPEINIT1(ScBlockUndo,      ScSimpleUndo);
+TYPEINIT1(ScMultiBlockUndo, ScSimpleUndo);
 TYPEINIT1(ScMoveUndo,       ScSimpleUndo);
 TYPEINIT1(ScDBFuncUndo,     ScSimpleUndo);
 TYPEINIT1(ScUndoWrapper,    SfxUndoAction);
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index 79496b0..a5344a8 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -876,16 +876,13 @@ sal_Bool ScUndoCut::CanRepeat(SfxRepeatTarget& rTarget) const
 //      Einfuegen (Paste)
 //
 
-ScUndoPaste::ScUndoPaste( ScDocShell* pNewDocShell,
-                SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
-                SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
+ScUndoPaste::ScUndoPaste( ScDocShell* pNewDocShell, const ScRange& rRange,
                 const ScMarkData& rMark,
                 ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc,
                 sal_uInt16 nNewFlags,
                 ScRefUndoData* pRefData,
-                void* /* pFill1 */, void* /* pFill2 */, void* /* pFill3 */,
-                sal_Bool bRedoIsFilled, const ScUndoPasteOptions* pOptions ) :
-    ScBlockUndo( pNewDocShell, ScRange( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), SC_UNDO_SIMPLE ),
+                bool bRedoIsFilled, const ScUndoPasteOptions* pOptions ) :
+    ScBlockUndo( pNewDocShell, rRange, SC_UNDO_SIMPLE ),
     aMarkData( rMark ),
     pUndoDoc( pNewUndoDoc ),
     pRedoDoc( pNewRedoDoc ),
@@ -933,7 +930,7 @@ void ScUndoPaste::SetChangeTrack()
         nStartChangeAction = nEndChangeAction = 0;
 }
 
-void ScUndoPaste::DoChange( const sal_Bool bUndo )
+void ScUndoPaste::DoChange(bool bUndo)
 {
     ScDocument* pDoc = pDocShell->GetDocument();
 
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index e44cea5..294d426 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -1167,9 +1167,9 @@ sal_Bool lcl_PutDataArray( ScDocShell& rDocShell, const ScRange& rRange,
         ScMarkData aDestMark;
         aDestMark.SelectOneTable( nTab );
         rDocShell.GetUndoManager()->AddUndoAction(
-            new ScUndoPaste( &rDocShell,
-                nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, aDestMark,
-                pUndoDoc, NULL, IDF_CONTENTS, NULL,NULL,NULL,NULL, false ) );
+            new ScUndoPaste(
+                &rDocShell, ScRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab),
+                aDestMark, pUndoDoc, NULL, IDF_CONTENTS, NULL, false));
     }
 
     if (!bHeight)
@@ -1255,8 +1255,8 @@ sal_Bool lcl_PutFormulaArray( ScDocShell& rDocShell, const ScRange& rRange,
         aDestMark.SelectOneTable( nTab );
         rDocShell.GetUndoManager()->AddUndoAction(
             new ScUndoPaste( &rDocShell,
-                nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, aDestMark,
-                pUndoDoc, NULL, IDF_CONTENTS, NULL,NULL,NULL,NULL, false ) );
+                ScRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab), aDestMark,
+                pUndoDoc, NULL, IDF_CONTENTS, NULL, false));
     }
 
     if (!bHeight)
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index 5aa8c50..dc33c8c 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -1480,12 +1480,10 @@ bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
         aOptions.bAsLink    = bAsLink;
         aOptions.eMoveMode  = eMoveMode;
 
-        SfxUndoAction* pUndo = new ScUndoPaste( pDocSh,
-                                nStartCol, nStartRow, nStartTab,
-                                nUndoEndCol, nUndoEndRow, nEndTab, aFilteredMark,
-                                pUndoDoc, pRedoDoc, nFlags | nUndoFlags,
-                                pUndoData, NULL, NULL, NULL,
-                                false, &aOptions );     // false = Redo data not yet copied
+        SfxUndoAction* pUndo = new ScUndoPaste(
+            pDocSh, ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
+            aFilteredMark, pUndoDoc, pRedoDoc, nFlags | nUndoFlags, pUndoData,
+            false, &aOptions );     // false = Redo data not yet copied
 
         if ( bInsertCells )
         {
@@ -1674,13 +1672,7 @@ bool ScViewFunc::PasteMultiRangesFromClip(
         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);
+            aMarkedRange, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
 
         if (bInsertCells)
             pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
@@ -1842,14 +1834,8 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
         aOptions.bAsLink    = bAsLink;
         aOptions.eMoveMode  = eMoveMode;
 
-        ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
-            aWholeRange.aStart.Col(),
-            aWholeRange.aStart.Row(),
-            aWholeRange.aStart.Tab(),
-            aWholeRange.aEnd.Col(),
-            aWholeRange.aEnd.Row(),
-            aWholeRange.aEnd.Tab(),
-            aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions);
+        ScUndoPaste* pUndo = new ScUndoPaste(
+            pDocSh, aWholeRange, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
 
         pUndoMgr->AddUndoAction(pUndo, false);
         pUndoMgr->LeaveListAction();
diff --git a/sc/source/ui/view/viewfun4.cxx b/sc/source/ui/view/viewfun4.cxx
index e0e4ee3..40252f0 100644
--- a/sc/source/ui/view/viewfun4.cxx
+++ b/sc/source/ui/view/viewfun4.cxx
@@ -157,9 +157,9 @@ void ScViewFunc::PasteRTF( SCCOL nStartCol, SCROW nStartRow,
                 ScMarkData aDestMark;
                 aDestMark.SelectOneTable( nTab );
                 pDocSh->GetUndoManager()->AddUndoAction(
-                    new ScUndoPaste( pDocSh, nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab,
-                                        aDestMark,
-                                        pUndoDoc, pRedoDoc, IDF_ALL, NULL,NULL,NULL,NULL ) );
+                    new ScUndoPaste(
+                        pDocSh, ScRange(nStartCol, nStartRow, nTab, nStartCol, nEndRow, nTab),
+                        aDestMark, pUndoDoc, pRedoDoc, IDF_ALL, NULL));
             }
         }
 
commit 6a3a25fa40ac9a7f1f579c3fb114cbcc9ed158db
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 18:09:47 2011 -0400

    ScMultiBlockUndo in place.

diff --git a/sc/source/ui/inc/undobase.hxx b/sc/source/ui/inc/undobase.hxx
index 7013784..6f4135c 100644
--- a/sc/source/ui/inc/undobase.hxx
+++ b/sc/source/ui/inc/undobase.hxx
@@ -94,6 +94,26 @@ protected:
     void            ShowBlock();
 };
 
+class ScMultiBlockUndo: public ScSimpleUndo
+{
+public:
+    ScMultiBlockUndo(ScDocShell* pDocSh, const ScRangeList& rRanges,
+                     ScBlockUndoMode eBlockMode);
+    virtual ~ScMultiBlockUndo();
+
+protected:
+    ScRangeList     maBlockRanges;
+    SdrUndoAction*  mpDrawUndo;
+    ScBlockUndoMode meMode;
+
+    void BeginUndo();
+    void EndUndo();
+    void EndRedo();
+
+    void AdjustHeight();
+    void ShowBlock();
+};
+
 //----------------------------------------------------------------------------
 
 // for functions that act on a database range - takes care of the unnamed database range
diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx
index 0fddef5..42487b2 100644
--- a/sc/source/ui/undo/undobase.cxx
+++ b/sc/source/ui/undo/undobase.cxx
@@ -280,6 +280,107 @@ void ScBlockUndo::ShowBlock()
     }
 }
 
+ScMultiBlockUndo::ScMultiBlockUndo(
+    ScDocShell* pDocSh, const ScRangeList& rRanges, ScBlockUndoMode eBlockMode) :
+    ScSimpleUndo(pDocSh),
+    maBlockRanges(rRanges),
+    meMode(eBlockMode)
+{
+    mpDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() );
+}
+
+ScMultiBlockUndo::~ScMultiBlockUndo()
+{
+    DeleteSdrUndoAction( mpDrawUndo );
+}
+
+void ScMultiBlockUndo::BeginUndo()
+{
+    ScSimpleUndo::BeginUndo();
+    EnableDrawAdjust(pDocShell->GetDocument(), false);
+}
+
+void ScMultiBlockUndo::EndUndo()
+{
+    if (meMode == SC_UNDO_AUTOHEIGHT)
+        AdjustHeight();
+
+    EnableDrawAdjust(pDocShell->GetDocument(), true);
+    DoSdrUndoAction(mpDrawUndo, pDocShell->GetDocument());
+
+    ShowBlock();
+    ScSimpleUndo::EndUndo();
+}
+
+void ScMultiBlockUndo::EndRedo()
+{
+    if (meMode == SC_UNDO_AUTOHEIGHT)
+        AdjustHeight();
+
+    ShowBlock();
+    ScSimpleUndo::EndRedo();
+}
+
+void ScMultiBlockUndo::AdjustHeight()
+{
+    ScDocument* pDoc = pDocShell->GetDocument();
+
+    VirtualDevice aVirtDev;
+    Fraction aZoomX( 1, 1 );
+    Fraction aZoomY = aZoomX;
+    double nPPTX, nPPTY;
+    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+    if (pViewShell)
+    {
+        ScViewData* pData = pViewShell->GetViewData();
+        nPPTX = pData->GetPPTX();
+        nPPTY = pData->GetPPTY();
+        aZoomX = pData->GetZoomX();
+        aZoomY = pData->GetZoomY();
+    }
+    else
+    {
+        //  Zoom auf 100 lassen
+        nPPTX = ScGlobal::nScreenPPTX;
+        nPPTY = ScGlobal::nScreenPPTY;
+    }
+
+    for (size_t i = 0, n = maBlockRanges.size(); i < n; ++i)
+    {
+        const ScRange& r = *maBlockRanges[i];
+        bool bRet = pDoc->SetOptimalHeight(
+            r.aStart.Row(), r.aEnd.Row(), r.aStart.Tab(), 0, &aVirtDev,
+            nPPTX, nPPTY, aZoomX, aZoomY, false);
+
+        if (bRet)
+            pDocShell->PostPaint(
+                0, r.aStart.Row(), r.aStart.Tab(), MAXCOL, MAXROW, r.aEnd.Tab(),
+                PAINT_GRID | PAINT_LEFT);
+    }
+}
+
+void ScMultiBlockUndo::ShowBlock()
+{
+    if ( IsPaintLocked() )
+        return;
+
+    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+    if (!pViewShell)
+        return;
+
+    if (maBlockRanges.empty())
+        return;
+
+    // Show the very first range.
+    ScRange aRange = *maBlockRanges[0];
+    ShowTable(aRange);
+    pViewShell->MoveCursorAbs(
+        aRange.aStart.Col(), aRange.aStart.Row(), SC_FOLLOW_JUMP, false, false);
+    SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
+    aRange.aStart.SetTab(nTab);
+    aRange.aEnd.SetTab(nTab);
+    pViewShell->MarkRange(aRange);
+}
 
 // -----------------------------------------------------------------------
 
commit 90f571cf964edea8ce6f6e37aeb1c36a8adfd226
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 17:24:55 2011 -0400

    PostPasteFromClip to work with ScRangeList.

diff --git a/sc/inc/rangelst.hxx b/sc/inc/rangelst.hxx
index cc2c83a..e497e49 100644
--- a/sc/inc/rangelst.hxx
+++ b/sc/inc/rangelst.hxx
@@ -39,20 +39,18 @@ class ScDocument;
 class SC_DLLPUBLIC ScRangeList : public SvRefBase
 {
 public:
-                    ScRangeList() {}
-                    ScRangeList( const ScRangeList& rList );
-    virtual     ~ScRangeList();
-    ScRangeList&    operator=(const ScRangeList& rList);
-    void            Append( const ScRange& rRange )
-                    {
-                        ScRange* pR = new ScRange( rRange );
-                        maRanges.push_back( pR );
-                    }
-
-    sal_uInt16          Parse( const String&, ScDocument* = NULL,
-                           sal_uInt16 nMask = SCA_VALID,
-                           formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_OOO,
-                           sal_Unicode cDelimiter = 0 );
+    ScRangeList();
+    ScRangeList( const ScRangeList& rList );
+    ScRangeList( const ScRange& rRange );
+    virtual ~ScRangeList();
+
+    ScRangeList& operator=(const ScRangeList& rList);
+    void Append( const ScRange& rRange );
+
+    sal_uInt16 Parse( const String&, ScDocument* = NULL,
+                      sal_uInt16 nMask = SCA_VALID,
+                      formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_OOO,
+                      sal_Unicode cDelimiter = 0 );
 
     void            Format( String&, sal_uInt16 nFlags = 0, ScDocument* = NULL,
                             formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_OOO,
diff --git a/sc/source/core/tool/rangelst.cxx b/sc/source/core/tool/rangelst.cxx
index 7a5f0a2..9a6ded0 100644
--- a/sc/source/core/tool/rangelst.cxx
+++ b/sc/source/core/tool/rangelst.cxx
@@ -409,6 +409,8 @@ ScRange* ScRangeList::Find( const ScAddress& rAdr )
     return itr == maRanges.end() ? NULL : *itr;
 }
 
+ScRangeList::ScRangeList() {}
+
 ScRangeList::ScRangeList( const ScRangeList& rList ) :
     SvRefBase()
 {
@@ -416,6 +418,12 @@ ScRangeList::ScRangeList( const ScRangeList& rList ) :
     for_each(rList.maRanges.begin(), rList.maRanges.end(), AppendToList(maRanges));
 }
 
+ScRangeList::ScRangeList( const ScRange& rRange )
+{
+    maRanges.reserve(1);
+    Append(rRange);
+}
+
 ScRangeList& ScRangeList::operator=(const ScRangeList& rList)
 {
     RemoveAll();
@@ -424,6 +432,12 @@ ScRangeList& ScRangeList::operator=(const ScRangeList& rList)
     return *this;
 }
 
+void ScRangeList::Append( const ScRange& rRange )
+{
+    ScRange* pR = new ScRange( rRange );
+    maRanges.push_back( pR );
+}
+
 bool ScRangeList::Intersects( const ScRange& rRange ) const
 {
     vector<ScRange*>::const_iterator itrEnd = maRanges.end();
diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index e8b2651..29e10f3 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -367,7 +367,7 @@ private:
                                      bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
                                      InsCellCmd eMoveMode, sal_uInt16 nUndoFlags );
 
-    void            PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark);
+    void            PostPasteFromClip(const ScRangeList& rPasteRanges, const ScMarkData& rMark);
 
     sal_uInt16          GetOptimalColWidth( SCCOL nCol, SCTAB nTab, sal_Bool bFormula );
 
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index 490bd9c..5aa8c50 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -1855,12 +1855,12 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
         pUndoMgr->LeaveListAction();
     }
     aModificator.SetDocumentModified();
-//  PostPasteFromClip(aMarkedRange, aMark);
+    PostPasteFromClip(aRanges, aMark);
 
     return false;
 }
 
-void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark)
+void ScViewFunc::PostPasteFromClip(const ScRangeList& rPasteRanges, const ScMarkData& rMark)
 {
     ScViewData* pViewData = GetViewData();
     ScDocShell* pDocSh = pViewData->GetDocShell();
@@ -1870,19 +1870,23 @@ void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData&
 
     // #i97876# Spreadsheet data changes are not notified
     ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
-    if ( pModelObj && pModelObj->HasChangesListeners() )
+    if (!pModelObj || !pModelObj->HasChangesListeners())
+        return;
+
+    ScRangeList aChangeRanges;
+    for (size_t i = 0, n = rPasteRanges.size(); i < n; ++i)
     {
-        ScRangeList aChangeRanges;
+        const ScRange& r = *rPasteRanges[i];
         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
         for (; itr != itrEnd; ++itr)
         {
-            ScRange aChangeRange(rPasteRange);
-            aChangeRange.aStart.SetTab( *itr );
-            aChangeRange.aEnd.SetTab( *itr );
-            aChangeRanges.Append( aChangeRange );
+            ScRange aChangeRange(r);
+            aChangeRange.aStart.SetTab(*itr);
+            aChangeRange.aEnd.SetTab(*itr);
+            aChangeRanges.Append(aChangeRange);
         }
-        pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
     }
+    pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
 }
 
 
commit 3d37dd2a484f82026750635d0ad26d7b531bb7a2
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 17:01:49 2011 -0400

    Undo to work.

diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index f253c77..490bd9c 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -1781,12 +1781,31 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
             return false;
     }
 
+    std::auto_ptr<ScDocument> pUndoDoc;
+    if (pDoc->IsUndoEnabled())
+    {
+        pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
+        pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
+        for (size_t i = 0, n = aRanges.size(); i < n; ++i)
+        {
+            pDoc->CopyToDocument(
+                *aRanges[i], nUndoFlags, false, pUndoDoc.get(), &aMark, true);
+        }
+    }
+
+    if (nFlags & IDF_OBJECTS)
+        pDocSh->MakeDrawLayer();
+    if (pDoc->IsUndoEnabled())
+        pDoc->BeginDrawUndo();
+
+    CursorSwitcher aCursorSwitch(this);
+
     // First, paste everything but the drawing objects.
     for (size_t i = 0, n = aRanges.size(); i < n; ++i)
     {
         pDoc->CopyFromClip(
             *aRanges[i], aMark, (nFlags & ~IDF_OBJECTS), NULL, pClipDoc,
-            true, false, true, bSkipEmpty, NULL);
+            false, false, true, bSkipEmpty, NULL);
     }
 
     AdjustBlockHeight();            // update row heights before pasting objects
@@ -1798,16 +1817,45 @@ bool ScViewFunc::PasteFromClipToMultiRanges(
         {
             pDoc->CopyFromClip(
                 *aRanges[i], aMark, IDF_OBJECTS, NULL, pClipDoc,
-                true, false, true, bSkipEmpty, NULL);
+                false, false, true, bSkipEmpty, NULL);
         }
     }
 
     // Refresh the range that includes all pasted ranges.  We only need to
     // refresh the current sheet.
-    ScRange aRefreshRange = aRanges.Combine();
-    aRefreshRange.aStart.SetTab(rViewData.GetTabNo());
-    aRefreshRange.aEnd.SetTab(rViewData.GetTabNo());
-    pDocSh->PostPaint(aRefreshRange, PAINT_GRID);
+    ScRange aWholeRange = aRanges.Combine();
+    aWholeRange.aStart.SetTab(rViewData.GetTabNo());
+    aWholeRange.aEnd.SetTab(rViewData.GetTabNo());
+    pDocSh->PostPaint(aWholeRange, PAINT_GRID);
+
+    if (pDoc->IsUndoEnabled())
+    {
+        svl::IUndoManager* 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,
+            aWholeRange.aStart.Col(),
+            aWholeRange.aStart.Row(),
+            aWholeRange.aStart.Tab(),
+            aWholeRange.aEnd.Col(),
+            aWholeRange.aEnd.Row(),
+            aWholeRange.aEnd.Tab(),
+            aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions);
+
+        pUndoMgr->AddUndoAction(pUndo, false);
+        pUndoMgr->LeaveListAction();
+    }
+    aModificator.SetDocumentModified();
+//  PostPasteFromClip(aMarkedRange, aMark);
 
     return false;
 }
commit b2f1120984b60715c01b6c743e980b89835bc135
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Fri Sep 9 16:30:46 2011 -0400

    Got the normal paste to work. Still no undo etc.

diff --git a/sc/inc/rangelst.hxx b/sc/inc/rangelst.hxx
index b07c7c9..cc2c83a 100644
--- a/sc/inc/rangelst.hxx
+++ b/sc/inc/rangelst.hxx
@@ -78,6 +78,8 @@ public:
     ScRange*        Remove(size_t nPos);
     void            RemoveAll();
 
+    ScRange         Combine() const;
+
     bool            empty() const;
     size_t          size() const;
     ScRange*        operator[](size_t idx);
diff --git a/sc/source/core/tool/rangelst.cxx b/sc/source/core/tool/rangelst.cxx
index cadd0d1..7a5f0a2 100644
--- a/sc/source/core/tool/rangelst.cxx
+++ b/sc/source/core/tool/rangelst.cxx
@@ -466,6 +466,31 @@ void ScRangeList::RemoveAll()
     maRanges.clear();
 }
 
+ScRange ScRangeList::Combine() const
+{
+    if (maRanges.empty())
+        return ScRange();
+
+    vector<ScRange*>::const_iterator itr = maRanges.begin(), itrEnd = maRanges.end();
+    ScRange aRet = **itr;
+    ++itr;
+    for (; itr != itrEnd; ++itr)
+    {
+        const ScRange& r = **itr;
+        SCROW nRow1 = r.aStart.Row(), nRow2 = r.aEnd.Row();
+        SCROW nCol1 = r.aStart.Col(), nCol2 = r.aEnd.Col();
+        if (aRet.aStart.Row() > nRow1)
+            aRet.aStart.SetRow(nRow1);
+        if (aRet.aStart.Col() > nCol1)
+            aRet.aStart.SetCol(nCol1);
+        if (aRet.aEnd.Row() < nRow2)
+            aRet.aEnd.SetRow(nRow2);
+        if (aRet.aEnd.Col() < nCol2)
+            aRet.aEnd.SetCol(nCol2);
+    }
+    return aRet;
+}
+
 bool ScRangeList::empty() const
 {
     return maRanges.empty();
diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index c11c77f..e8b2651 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -358,9 +358,15 @@ 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 );
+
+    bool PasteMultiRangesFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
+                                   bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
+                                   InsCellCmd eMoveMode, sal_uInt16 nUndoFlags );
+
+    bool PasteFromClipToMultiRanges( sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
+                                     bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
+                                     InsCellCmd eMoveMode, sal_uInt16 nUndoFlags );
+
     void            PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark);
 
     sal_uInt16          GetOptimalColWidth( SCCOL nCol, SCTAB nTab, sal_Bool bFormula );
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index 62dcdbe..f253c77 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -907,14 +907,20 @@ private:
     ScViewFunc* mpViewFunc;
 };
 
-bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
+bool checkDestRangeForOverwrite(const ScRangeList& rDestRanges, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
 {
     bool bIsEmpty = true;
-    ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
-    for (; itr != itrEnd && bIsEmpty; ++itr)
+    ScMarkData::const_iterator itrTab = rMark.begin(), itrTabEnd = rMark.end();
+    size_t nRangeSize = rDestRanges.size();
+    for (; itrTab != itrTabEnd && bIsEmpty; ++itrTab)
     {
-        bIsEmpty = pDoc->IsBlockEmpty(*itr, rDestRange.aStart.Col(), rDestRange.aStart.Row(),
-                                      rDestRange.aEnd.Col(), rDestRange.aEnd.Row());
+        for (size_t i = 0; i < nRangeSize && bIsEmpty; ++i)
+        {
+            const ScRange& rRange = *rDestRanges[i];
+            bIsEmpty = pDoc->IsBlockEmpty(
+                *itrTab, rRange.aStart.Col(), rRange.aStart.Row(),
+                rRange.aEnd.Col(), rRange.aEnd.Row());
+        }
     }
 
     if (!bIsEmpty)
@@ -958,9 +964,21 @@ bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
 
     ScClipParam& rClipParam = pClipDoc->GetClipParam();
     if (rClipParam.isMultiRange())
+    {
+        // Source data is multi-range.
         return PasteMultiRangesFromClip(
             nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
-            eMoveMode, nContFlags, nUndoFlags);
+            eMoveMode, nUndoFlags);
+    }
+
+    ScMarkData& rMark = GetViewData()->GetMarkData();
+    if (rMark.IsMultiMarked())
+    {
+        // Source data is single-range but destination is multi-range.
+        return PasteFromClipToMultiRanges(
+            nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
+            eMoveMode, nUndoFlags);
+    }
 
     bool bCutMode = pClipDoc->IsCutMode();      // if transposing, take from original clipdoc
     bool bIncludeFiltered = bCutMode;
@@ -1016,7 +1034,6 @@ bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
 
     ScDocument* pDoc = GetViewData()->GetDocument();
     ScDocShell* pDocSh = GetViewData()->GetDocShell();
-    ScMarkData& rMark = GetViewData()->GetMarkData();
     ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
     const bool bRecord(pDoc->IsUndoEnabled());
 
@@ -1202,7 +1219,9 @@ bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
                                 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
         if ( bAskIfNotEmpty )
         {
-            if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
+            ScRangeList aTestRanges;
+            aTestRanges.Append(aUserRange);
+            if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
                 return false;
         }
     }
@@ -1516,7 +1535,7 @@ bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
 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)
+    InsCellCmd eMoveMode, sal_uInt16 nUndoFlags)
 {
     ScViewData& rViewData = *GetViewData();
     ScDocument* pDoc = rViewData.GetDocument();
@@ -1575,7 +1594,9 @@ bool ScViewFunc::PasteMultiRangesFromClip(
 
     if (bAskIfNotEmpty)
     {
-        if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent()))
+        ScRangeList aTestRanges;
+        aTestRanges.Append(aMarkedRange);
+        if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aMark, rViewData.GetDialogParent()))
             return false;
     }
 
@@ -1673,6 +1694,124 @@ bool ScViewFunc::PasteMultiRangesFromClip(
     return true;
 }
 
+bool ScViewFunc::PasteFromClipToMultiRanges(
+    sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
+    bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
+    InsCellCmd eMoveMode, sal_uInt16 nUndoFlags )
+{
+    if (bTranspose)
+    {
+        // We don't allow transpose for this yet.
+        ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
+        return false;
+    }
+
+    if (eMoveMode != INS_NONE)
+    {
+        // We don't allow insertion mode either.  Too complicated.
+        ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
+        return false;
+    }
+
+    ScViewData& rViewData = *GetViewData();
+    ScClipParam& rClipParam = pClipDoc->GetClipParam();
+    if (rClipParam.mbCutMode)
+    {
+        // No cut and paste with this, please.
+        ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
+        return false;
+    }
+
+    const ScAddress& rCurPos = rViewData.GetCurPos();
+    ScDocument* pDoc = rViewData.GetDocument();
+
+    ScRange aSrcRange = rClipParam.getWholeRange();
+    SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
+    SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
+
+    if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
+    {
+        ErrorMessage(STR_PASTE_FULL);
+        return false;
+    }
+
+    ScMarkData aMark(rViewData.GetMarkData());
+
+    ScRangeList aRanges;
+    aMark.MarkToSimple();
+    aMark.FillRangeListWithMarks(&aRanges, false);
+    for (size_t i = 0, n = aRanges.size(); i < n; ++i)
+    {
+        ScRange aTest = *aRanges[i];
+        // Check for filtered rows in all selected sheets.
+        ScMarkData::const_iterator itrTab = aMark.begin(), itrTabEnd = aMark.end();
+        for (; itrTab != itrTabEnd; ++itrTab)
+        {
+            aTest.aStart.SetTab(*itrTab);
+            aTest.aEnd.SetTab(*itrTab);
+            if (ScViewUtil::HasFiltered(aTest, pDoc))
+            {
+                // I don't know how to handle pasting into filtered rows yet.
+                ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
+                return false;
+            }
+        }
+
+        SCROW nRows = aTest.aEnd.Row() - aTest.aStart.Row() + 1;
+        SCCOL nCols = aTest.aEnd.Col() - aTest.aStart.Col() + 1;
+        if (nRows != nRowSize || nCols != nColSize)
+        {
+            // Source and destination sizes don't match.  Bail out.
+            ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
+            return false;
+        }
+    }
+
+    ScDocShell* pDocSh = rViewData.GetDocShell();
+
+    ScDocShellModificator aModificator(*pDocSh);
+
+    bool bAskIfNotEmpty =
+        bAllowDialogs && (nFlags & IDF_CONTENTS) &&
+        nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
+
+    if (bAskIfNotEmpty)
+    {
+        if (!checkDestRangeForOverwrite(aRanges, pDoc, aMark, rViewData.GetDialogParent()))
+            return false;
+    }
+
+    // First, paste everything but the drawing objects.
+    for (size_t i = 0, n = aRanges.size(); i < n; ++i)
+    {
+        pDoc->CopyFromClip(

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list