Hi Kohei,

On 27/07/11 19:23, Kohei Yoshida wrote:
Hi Noel,

On Wed, 2011-07-27 at 11:50 +0100, Noel Power wrote:
I would really like to get this patch into 3.4,
[...]
Hmm... did you forget to attach your patch by any chance?
yes, ouch I did forget  :-) ( although it is attached to the bug )
   I tried to
cherry-pick the commits you referenced from master, but they don't apply
cleanly...
well, I didn't want the master fix going into 3.4 ( slightly nervous as it affects the core CopyToClip )

Noel
diff --git sc/source/ui/inc/viewfunc.hxx sc/source/ui/inc/viewfunc.hxx
index deca468..5c54d76 100644
--- sc/source/ui/inc/viewfunc.hxx
+++ sc/source/ui/inc/viewfunc.hxx
@@ -108,7 +108,7 @@ public:
     SC_DLLPUBLIC void			CutToClip( ScDocument* pClipDoc = NULL, sal_Bool bIncludeObjects = false );
     SC_DLLPUBLIC sal_Bool			CopyToClip( ScDocument* pClipDoc = NULL, sal_Bool bCut = false, sal_Bool bApi = false,
                                 sal_Bool bIncludeObjects = false, sal_Bool bStopEdit = true );
-    SC_DLLPUBLIC sal_Bool			CopyToClip( ScDocument* pClipDoc, const ScRange& rRange, sal_Bool bCut = false,
+    SC_DLLPUBLIC sal_Bool			CopyToClip( ScDocument* pClipDoc, const ScRangeList& rRange, sal_Bool bCut = false,
                                 sal_Bool bApi = false, sal_Bool bIncludeObjects = false, sal_Bool bStopEdit = true );
     ScTransferObj*              CopyToTransferable();
     SC_DLLPUBLIC sal_Bool			PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
diff --git sc/source/ui/vba/excelvbahelper.cxx sc/source/ui/vba/excelvbahelper.cxx
index cbf30eb..cc2a768 100644
--- sc/source/ui/vba/excelvbahelper.cxx
+++ sc/source/ui/vba/excelvbahelper.cxx
@@ -286,13 +286,22 @@ void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, sal_uInt16
 
 }
 
-void implnCopyRange( const uno::Reference< frame::XModel>& xModel, const ScRange& rRange )
+bool implnCopyRanges( const uno::Reference< frame::XModel>& xModel, ScRangeList& rRangeList )
 {
+    bool bResult = false;
     ScTabViewShell* pViewShell = getBestViewShell( xModel );
     if ( pViewShell )
     {
-        pViewShell->CopyToClip( NULL, rRange, false, true, true );
+        bResult = pViewShell->CopyToClip( NULL, rRangeList, false, true, true );
     }
+    return bResult;
+}
+
+bool implnCopyRange( const uno::Reference< frame::XModel>& xModel, const ScRange& rRange )
+{
+    ScRangeList aRanges;
+    aRanges.Append( rRange );
+    return implnCopyRanges( xModel, aRanges );
 }
 
 ScDocShell*
diff --git sc/source/ui/vba/excelvbahelper.hxx sc/source/ui/vba/excelvbahelper.hxx
index eebeaff..a5ceb81 100644
--- sc/source/ui/vba/excelvbahelper.hxx
+++ sc/source/ui/vba/excelvbahelper.hxx
@@ -55,7 +55,8 @@ void implnCopy( const css::uno::Reference< css::frame::XModel>& xModel );
 void implnPaste ( const css::uno::Reference< css::frame::XModel>& xModel );
 void implnCut( const css::uno::Reference< css::frame::XModel>& xModel );
 void implnPasteSpecial( const css::uno::Reference< css::frame::XModel>& xModel, sal_uInt16 nFlags,sal_uInt16 nFunction,sal_Bool bSkipEmpty, sal_Bool bTranspose);
-void implnCopyRange( const css::uno::Reference< css::frame::XModel>& xModel, const ScRange& rRange );
+bool implnCopyRanges( const css::uno::Reference< css::frame::XModel>& xModel, ScRangeList& rRange );
+bool implnCopyRange( const css::uno::Reference< css::frame::XModel>& xModel, const ScRange& rRange );
 ScTabViewShell* getBestViewShell( const css::uno::Reference< css::frame::XModel>& xModel ) ;
 ScDocShell* getDocShell( const css::uno::Reference< css::frame::XModel>& xModel ) ;
 ScTabViewShell* getCurrentBestViewShell( const css::uno::Reference< css::uno::XComponentContext >& xContext );
diff --git sc/source/ui/vba/vbarange.cxx sc/source/ui/vba/vbarange.cxx
index 1689b13..09a4e5c 100644
--- sc/source/ui/vba/vbarange.cxx
+++ sc/source/ui/vba/vbarange.cxx
@@ -2597,8 +2597,6 @@ ScVbaRange::getMergeCells() throw (script::BasicErrorException, uno::RuntimeExce
 void
 ScVbaRange::Copy(const ::uno::Any& Destination) throw (uno::RuntimeException)
 {
-    if ( m_Areas->getCount() > 1 )
-        throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("That command cannot be used on multiple selections" ) ), uno::Reference< uno::XInterface >() );
     if ( Destination.hasValue() )
     {
         uno::Reference< excel::XRange > xRange( Destination, uno::UNO_QUERY_THROW );
@@ -2616,11 +2614,22 @@ ScVbaRange::Copy(const ::uno::Any& Destination) throw (uno::RuntimeException)
     }
     else
     {
-        ScRange aRange;
-        RangeHelper thisRange( mxRange );
-        ScUnoConversion::FillScRange( aRange, thisRange.getCellRangeAddressable()->getRangeAddress() );
-        uno::Reference< frame::XModel > xModel = excel::GetModelFromRange( mxRange );
-        excel::implnCopyRange( xModel, aRange );
+        if ( m_Areas->getCount() > 1 )
+        {
+            uno::Reference< frame::XModel > xModel = excel::GetModelFromRange( mxRanges );
+            ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
+            ScRangeList aList =  pUnoRangesBase->GetRangeList();
+            if ( !excel::implnCopyRanges( xModel, aList ) )
+                throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("!!! That command cannot be used on multiple selections" ) ), uno::Reference< uno::XInterface >() );
+        }
+        else
+        {
+            ScRange aRange;
+            RangeHelper thisRange( mxRange );
+            uno::Reference< frame::XModel > xModel = excel::GetModelFromRange( mxRange );
+            ScUnoConversion::FillScRange( aRange, thisRange.getCellRangeAddressable()->getRangeAddress() );
+            excel::implnCopyRange( xModel, aRange );
+        }
     }
 }
 
diff --git sc/source/ui/view/viewfun3.cxx sc/source/ui/view/viewfun3.cxx
index 5115ab0..8358b56 100644
--- sc/source/ui/view/viewfun3.cxx
+++ sc/source/ui/view/viewfun3.cxx
@@ -501,15 +501,137 @@ sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, sal_Bool bCut, sal_Bool b
 }
 
 // Copy the content of the Range into clipboard. Adding this method for VBA API: Range.Copy().
-sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRange& rRange, sal_Bool bCut, sal_Bool bApi, sal_Bool bIncludeObjects, sal_Bool bStopEdit )
+sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRangeList& rRanges, sal_Bool bCut, sal_Bool bApi, sal_Bool bIncludeObjects, sal_Bool bStopEdit )
 {
+    if ( rRanges.empty() )
+        return false;
     sal_Bool bDone = false;
     if ( bStopEdit )
         UpdateInputLine();
 
-    ScRange aRange = rRange;
+    ScRange aRange = *rRanges[0];
+    ScClipParam aClipParam( aRange, bCut );
+    aClipParam.maRanges = rRanges;
+
     ScDocument* pDoc = GetViewData()->GetDocument();
-    if ( pDoc && !pDoc->HasSelectedBlockMatrixFragment( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ) )
+
+    if ( aClipParam.isMultiRange() )
+    {
+        bool bSuccess = false;
+        aClipParam.mbCutMode = false;
+
+        do
+        {
+            if (bCut)
+                // We con't support cutting of multi-selections.
+                break;
+
+            if (pClipDoc)
+                // TODO: What's this for?
+                break;
+
+            ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
+
+            // Check for geometrical feasibility of the ranges.
+            bool bValidRanges = true;
+            ScRange* p = aClipParam.maRanges.front();
+            SCCOL nPrevColDelta = 0;
+            SCROW nPrevRowDelta = 0;
+            SCCOL nPrevCol = p->aStart.Col();
+            SCROW nPrevRow = p->aStart.Row();
+            SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
+            SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
+            for ( size_t i = 1; i < aClipParam.maRanges.size(); ++i )
+            {
+                p = aClipParam.maRanges[i];
+                if (pDoc->HasSelectedBlockMatrixFragment(
+                    p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), p->aStart.Tab() ))
+                {
+                    if (!bApi)
+                        ErrorMessage(STR_MATRIXFRAGMENTERR);
+                    return false;
+                }
+
+                SCCOL nColDelta = p->aStart.Col() - nPrevCol;
+                SCROW nRowDelta = p->aStart.Row() - nPrevRow;
+
+                if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
+                {
+                    bValidRanges = false;
+                    break;
+                }
+
+                if (aClipParam.meDirection == ScClipParam::Unspecified)
+                {
+                    if (nColDelta)
+                        aClipParam.meDirection = ScClipParam::Column;
+                    if (nRowDelta)
+                        aClipParam.meDirection = ScClipParam::Row;
+                }
+
+                SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
+                SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
+
+                if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
+                {
+                    // column-oriented ranges must have identical row size.
+                    bValidRanges = false;
+                    break;
+                }
+                if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
+                {
+                    // likewise, row-oriented ranges must have identical
+                    // column size.
+                    bValidRanges = false;
+                    break;
+                }
+
+                nPrevCol = p->aStart.Col();
+                nPrevRow = p->aStart.Row();
+                nPrevColDelta = nColDelta;
+                nPrevRowDelta = nRowDelta;
+                nPrevColSize  = nColSize;
+                nPrevRowSize  = nRowSize;
+            }
+            if (!bValidRanges)
+                break;
+
+            pDoc->CopyToClip4VBA( aClipParam, pClipDoc, false, bIncludeObjects );
+
+            ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
+            if ( pChangeTrack )
+                pChangeTrack->ResetLastCut();	// kein CutMode mehr
+
+            {
+                ScDocShell* pDocSh = GetViewData()->GetDocShell();
+                TransferableObjectDescriptor aObjDesc;
+                pDocSh->FillTransferableObjectDescriptor( aObjDesc );
+                aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
+                // maSize is set in ScTransferObj ctor
+
+                ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
+                uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
+
+                if ( ScGlobal::pDrawClipDocShellRef )
+                {
+                    SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
+                    pTransferObj->SetDrawPersist( aPersistRef );	// keep persist for ole objects alive
+                }
+
+                pTransferObj->CopyToClipboard( GetActiveWin() );	// system clipboard
+                SC_MOD()->SetClipObject( pTransferObj, NULL );		// internal clipboard
+            }
+
+            bSuccess = true;
+        }
+        while (false);
+
+        if (!bSuccess && !bApi)
+            ErrorMessage(STR_NOMULTISELECT);
+
+        bDone = bSuccess;
+    }
+    else if ( pDoc && !pDoc->HasSelectedBlockMatrixFragment( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ) )
     {
         sal_Bool bSysClip = false;
         if ( !pClipDoc )
@@ -532,7 +654,6 @@ sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRange& rRange, sa
             ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
         }
 
-        ScClipParam aClipParam( aRange, bCut );
         pDoc->CopyToClip4VBA( aClipParam, pClipDoc, false, bIncludeObjects );
         if ( bSysClip )
         {
_______________________________________________
LibreOffice mailing list
LibreOffice@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice

Reply via email to