summaryrefslogtreecommitdiff
path: root/sc/source/ui/view/viewfun3.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/view/viewfun3.cxx')
-rw-r--r--sc/source/ui/view/viewfun3.cxx1955
1 files changed, 1955 insertions, 0 deletions
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
new file mode 100644
index 000000000000..30c9b1ea35eb
--- /dev/null
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -0,0 +1,1955 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+//----------------------------------------------------------------------------
+
+#define _SV_NOXSOUND
+
+#define _BASE_DLGS_HXX
+#define _BIGINT_HXX
+#define _CACHESTR_HXX
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _CTRLTOOL_HXX
+#define _DLGCFG_HXX
+#define _DYNARR_HXX
+#define _EXTATTR_HXX
+#define _FILDLG_HXX
+#define _FONTDLG_HXX
+#define _FRM3D_HXX
+#define _INTRO_HXX
+#define _ISETBWR_HXX
+#define _NO_SVRTF_PARSER_HXX
+#define _MACRODLG_HXX
+#define _MODALDLG_HXX
+#define _MOREBUTTON_HXX
+#define _OUTLINER_HXX
+#define _PVRWIN_HXX
+#define _RULER_HXX
+#define _SCRWIN_HXX
+#define _SETBRW_HXX
+#define _STDCTRL_HXX
+#define _STDMENU_HXX
+#define _TABBAR_HXX
+#define _TREELIST_HXX
+#define _VALUESET_HXX
+#define _VCATTR_HXX
+#define _VCBRW_HXX
+#define _VCTRLS_HXX
+#define _VCSBX_HXX
+#define _VCONT_HXX
+#define _VDRWOBJ_HXX
+
+#define _PASSWD_HXX
+
+#define _SFX_DOCFILE_HXX
+#define _SFX_DOCINF_HXX
+#define _SFX_DOCSH_HXX
+#define _SFX_PRNMON_HXX
+#define _SFX_RESMGR_HXX
+#define _SFX_TEMPLDLG_HXX
+#define _SFXBASIC_HXX
+#define _SFXCTRLITEM
+#define _SFXDLGCFG_HXX
+#define _SFXFILEDLG_HXX
+#define _SFXIPFRM_HXX
+#define _SFX_MACRO_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXMNUMGR_HXX
+#define _SFXMULTISEL_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXOBJFACE_HXX
+#define _SFXOBJFAC_HXX
+#define _SFX_SAVEOPT_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXSTBMGR_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXTBXMGR_HXX
+
+#define _SI_HXX
+
+#define _SVBOXITM_HXX
+#define _SVCONTNR_HXX //
+
+#define _SDR_NOTRANSFORM
+
+#define _SVDRAG_HXX
+#define _SVINCVW_HXX
+#define _SVRTV_HXX
+#define _SVTABBX_HXX
+#define _SVTREEBOX_HXX
+#define _SVTREELIST_HXX
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_LAYCTRL_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SELCTRL_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_STDDLG_HXX
+#define _SVX_THESDLG_HXX
+
+// INCLUDE -------------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/dbexch.hrc>
+#include <svx/svdetc.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdpage.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/docfile.hxx>
+#include <svl/stritem.hxx>
+#include <svl/ptitem.hxx>
+#include <svl/urlbmk.hxx>
+#include <sot/clsids.hxx>
+#include <sot/formats.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/msgbox.hxx>
+#include <tools/urlobj.hxx>
+#include <sot/exchange.hxx>
+#include <memory>
+
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "dociter.hxx"
+#include "viewfunc.hxx"
+#include "tabvwsh.hxx"
+#include "docsh.hxx"
+#include "docfunc.hxx"
+#include "undoblk.hxx"
+#include "refundo.hxx"
+#include "globstr.hrc"
+#include "global.hxx"
+#include "transobj.hxx"
+#include "drwtrans.hxx"
+#include "rangenam.hxx"
+#include "dbcolect.hxx"
+#include "impex.hxx" // Sylk-ID fuer CB
+#include "chgtrack.hxx"
+#include "waitoff.hxx"
+#include "scmod.hxx"
+#include "sc.hrc"
+#include "inputopt.hxx"
+#include "warnbox.hxx"
+#include "drwlayer.hxx"
+#include "editable.hxx"
+#include "transobj.hxx"
+#include "drwtrans.hxx"
+#include "docuno.hxx"
+#include "clipparam.hxx"
+#include "undodat.hxx"
+#include "drawview.hxx"
+
+using namespace com::sun::star;
+
+// STATIC DATA ---------------------------------------------------------------
+
+
+//============================================================================
+
+// GlobalName der Writer-DocShell kommt jetzt aus comphelper/classids.hxx
+
+//----------------------------------------------------------------------------
+// C U T
+
+void ScViewFunc::CutToClip( ScDocument* pClipDoc, sal_Bool bIncludeObjects )
+{
+ UpdateInputLine();
+
+ ScEditableTester aTester( this );
+ if (!aTester.IsEditable()) // selection editable?
+ {
+ ErrorMessage( aTester.GetMessageId() );
+ return;
+ }
+
+ ScRange aRange; // zu loeschender Bereich
+ if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
+ {
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ const sal_Bool bRecord(pDoc->IsUndoEnabled()); // Undo/Redo
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) // mark the range if not marked yet
+ {
+ DoneBlockMode();
+ InitOwnBlockMode();
+ rMark.SetMarkArea( aRange );
+ MarkDataChanged();
+ }
+
+ CopyToClip( pClipDoc, sal_True, false, bIncludeObjects ); // Ab ins Clipboard
+
+ ScAddress aOldEnd( aRange.aEnd ); // Zusammengefasste Zellen im Bereich?
+ pDoc->ExtendMerge( aRange, sal_True );
+
+ ScDocument* pUndoDoc = NULL;
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndoSelected( pDoc, rMark );
+ // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
+ ScRange aCopyRange = aRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(pDoc->GetTableCount()-1);
+ pDoc->CopyToDocument( aCopyRange, (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS, false, pUndoDoc );
+ pDoc->BeginDrawUndo();
+ }
+
+ sal_uInt16 nExtFlags = 0;
+ pDocSh->UpdatePaintExt( nExtFlags, aRange );
+
+ HideCursor(); // Cursor aendert sich !
+
+ rMark.MarkToMulti();
+ pDoc->DeleteSelection( IDF_ALL, rMark );
+ if ( bIncludeObjects )
+ pDoc->DeleteObjectsInSelection( rMark );
+ rMark.MarkToSimple();
+
+ if ( !AdjustRowHeight( aRange.aStart.Row(), aRange.aEnd.Row() ) )
+ pDocSh->PostPaint( aRange, PAINT_GRID, nExtFlags );
+
+ if ( bRecord ) // erst jetzt ist Draw-Undo verfuegbar
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoCut( pDocSh, aRange, aOldEnd, rMark, pUndoDoc ) );
+
+ aModificator.SetDocumentModified();
+ ShowCursor(); // Cursor aendert sich !
+ pDocSh->UpdateOle(GetViewData());
+
+ CellContentChanged();
+ }
+ else
+ ErrorMessage( STR_NOMULTISELECT );
+}
+
+
+//----------------------------------------------------------------------------
+// C O P Y
+
+sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, sal_Bool bCut, sal_Bool bApi, sal_Bool bIncludeObjects, sal_Bool bStopEdit )
+{
+ sal_Bool bDone = false;
+ if ( bStopEdit )
+ UpdateInputLine();
+
+ ScRange aRange;
+ ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange );
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
+ {
+ if ( !pDoc->HasSelectedBlockMatrixFragment(
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(),
+ rMark ) )
+ {
+ sal_Bool bSysClip = false;
+ if ( !pClipDoc ) // no clip doc specified
+ {
+ pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj)
+ bSysClip = sal_True; // and copy into system
+ }
+
+ if ( !bCut )
+ {
+ ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
+ if ( pChangeTrack )
+ pChangeTrack->ResetLastCut(); // kein CutMode mehr
+ }
+
+ if ( bSysClip && bIncludeObjects )
+ {
+ sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
+ // update ScGlobal::pDrawClipDocShellRef
+ ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
+ }
+
+ ScClipParam aClipParam(aRange, bCut);
+ aClipParam.setSourceDocID( pDoc->GetDocumentID() );
+ pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects);
+
+ if ( pDoc && pClipDoc )
+ {
+ ScDrawLayer* pDrawLayer = pClipDoc->GetDrawLayer();
+ if ( pDrawLayer )
+ {
+ ScClipParam& rClipParam = pClipDoc->GetClipParam();
+ ScRangeListVector& rRangesVector = rClipParam.maProtectedChartRangesVector;
+ SCTAB nTabCount = pClipDoc->GetTableCount();
+ for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab )
+ {
+ SdrPage* pPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
+ if ( pPage )
+ {
+ ScChartHelper::FillProtectedChartRangesVector( rRangesVector, pDoc, pPage );
+ }
+ }
+ }
+ }
+
+ if (bSysClip)
+ {
+ ScDrawLayer::SetGlobalDrawPersist(NULL);
+
+ ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) );
+ }
+ pClipDoc->ExtendMerge( aRange, sal_True );
+
+ if (bSysClip)
+ {
+ 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( pClipDoc, 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
+ }
+
+ bDone = sal_True;
+ }
+ else
+ {
+ if (!bApi)
+ ErrorMessage(STR_MATRIXFRAGMENTERR);
+ }
+ }
+ else if (eMarkType == SC_MARK_MULTI)
+ {
+ bool bSuccess = false;
+ ScClipParam aClipParam;
+ aClipParam.mbCutMode = false;
+ rMark.MarkToSimple();
+ rMark.FillRangeListWithMarks(&aClipParam.maRanges, false);
+
+ do
+ {
+ if (bCut)
+ // We con't support cutting of multi-selections.
+ break;
+
+ if (pClipDoc)
+ // TODO: What's this for?
+ break;
+
+ ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
+
+ // Check for geometrical feasibility of the ranges.
+ bool bValidRanges = true;
+ 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(), rMark))
+ {
+ if (!bApi)
+ ErrorMessage(STR_MATRIXFRAGMENTERR);
+ return false;
+ }
+
+ SCCOL nColDelta = p->aStart.Col() - nPrevCol;
+ SCROW nRowDelta = p->aStart.Row() - nPrevRow;
+
+ if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
+ {
+ bValidRanges = false;
+ break;
+ }
+
+ if (aClipParam.meDirection == ScClipParam::Unspecified)
+ {
+ if (nColDelta)
+ aClipParam.meDirection = ScClipParam::Column;
+ if (nRowDelta)
+ aClipParam.meDirection = ScClipParam::Row;
+ }
+
+ SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
+ SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
+
+ if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
+ {
+ // column-oriented ranges must have identical row size.
+ bValidRanges = false;
+ break;
+ }
+ if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
+ {
+ // likewise, row-oriented ranges must have identical
+ // column size.
+ bValidRanges = false;
+ break;
+ }
+
+ nPrevCol = p->aStart.Col();
+ nPrevRow = p->aStart.Row();
+ nPrevColDelta = nColDelta;
+ nPrevRowDelta = nRowDelta;
+ nPrevColSize = nColSize;
+ nPrevRowSize = nRowSize;
+ }
+ if (!bValidRanges)
+ break;
+
+ pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, false, bIncludeObjects);
+
+ ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
+ if ( pChangeTrack )
+ pChangeTrack->ResetLastCut(); // kein CutMode mehr
+
+ {
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ TransferableObjectDescriptor aObjDesc;
+ pDocSh->FillTransferableObjectDescriptor( aObjDesc );
+ aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
+ // maSize is set in ScTransferObj ctor
+
+ ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
+ uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
+
+ if ( ScGlobal::pDrawClipDocShellRef )
+ {
+ SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
+ pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
+ }
+
+ pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
+ SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
+ }
+
+ bSuccess = true;
+ }
+ while (false);
+
+ if (!bSuccess && !bApi)
+ ErrorMessage(STR_NOMULTISELECT);
+
+ bDone = bSuccess;
+ }
+ else
+ {
+ if (!bApi)
+ ErrorMessage(STR_NOMULTISELECT);
+ }
+
+ return bDone;
+}
+
+// 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 bDone = false;
+ if ( bStopEdit )
+ UpdateInputLine();
+
+ ScRange aRange = rRange;
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ 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 )
+ {
+ // Create one (deleted by ScTransferObj).
+ pClipDoc = new ScDocument( SCDOCMODE_CLIP );
+ bSysClip = true;
+ }
+ if ( !bCut )
+ {
+ ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
+ if ( pChangeTrack )
+ pChangeTrack->ResetLastCut();
+ }
+
+ if ( bSysClip && bIncludeObjects )
+ {
+ sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange );
+ // Update ScGlobal::pDrawClipDocShellRef.
+ ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
+ }
+
+ ScClipParam aClipParam( aRange, bCut );
+ pDoc->CopyToClip4VBA( aClipParam, pClipDoc, false, bIncludeObjects );
+ if ( bSysClip )
+ {
+ ScDrawLayer::SetGlobalDrawPersist(NULL);
+ ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) );
+ }
+ pClipDoc->ExtendMerge( aRange, true );
+
+ if ( bSysClip )
+ {
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ TransferableObjectDescriptor aObjDesc;
+ pDocSh->FillTransferableObjectDescriptor( aObjDesc );
+ aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
+
+ ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
+ uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
+ if ( ScGlobal::pDrawClipDocShellRef )
+ {
+ SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
+ pTransferObj->SetDrawPersist( aPersistRef );
+ }
+ pTransferObj->CopyToClipboard( GetActiveWin() );
+ SC_MOD()->SetClipObject( pTransferObj, NULL );
+ }
+
+ bDone = true;
+ }
+ else
+ {
+ if ( !bApi )
+ ErrorMessage(STR_MATRIXFRAGMENTERR);
+ }
+
+ return bDone;
+}
+
+ScTransferObj* ScViewFunc::CopyToTransferable()
+{
+ ScRange aRange;
+ if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
+ {
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ if ( !pDoc->HasSelectedBlockMatrixFragment(
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(),
+ rMark ) )
+ {
+ ScDocument *pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj)
+
+ sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
+ ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
+
+ ScClipParam aClipParam(aRange, false);
+ pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true);
+
+ ScDrawLayer::SetGlobalDrawPersist(NULL);
+ pClipDoc->ExtendMerge( aRange, sal_True );
+
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ TransferableObjectDescriptor aObjDesc;
+ pDocSh->FillTransferableObjectDescriptor( aObjDesc );
+ aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
+ ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
+ return pTransferObj;
+ }
+ }
+
+ return NULL;
+}
+
+//----------------------------------------------------------------------------
+// P A S T E
+
+void ScViewFunc::PasteDraw()
+{
+ ScViewData* pViewData = GetViewData();
+ SCCOL nPosX = pViewData->GetCurX();
+ SCROW nPosY = pViewData->GetCurY();
+ Window* pWin = GetActiveWin();
+ Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY,
+ pViewData->GetActivePart() ) );
+ ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
+ if (pDrawClip)
+ PasteDraw( aPos, pDrawClip->GetModel(), false,
+ pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
+}
+
+void ScViewFunc::PasteFromSystem()
+{
+ UpdateInputLine();
+
+ Window* pWin = GetActiveWin();
+ ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
+ ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
+
+ if (pOwnClip)
+ {
+ // keep a reference in case the clipboard is changed during PasteFromClip
+ uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
+ PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
+ PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
+ sal_True ); // allow warning dialog
+ }
+ else if (pDrawClip)
+ PasteDraw();
+ else
+ {
+ TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
+
+ {
+ sal_uLong nBiff8 = SotExchange::RegisterFormatName(
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff8")));
+ sal_uLong nBiff5 = SotExchange::RegisterFormatName(
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff5")));
+
+ // als erstes SvDraw-Model, dann Grafik
+ // (Grafik darf nur bei einzelner Grafik drinstehen)
+
+ if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
+ {
+ // special case for tables from drawing
+ if( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
+ {
+ PasteFromSystem( FORMAT_RTF );
+ }
+ else
+ {
+ PasteFromSystem( SOT_FORMATSTR_ID_DRAWING );
+ }
+ }
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
+ PasteFromSystem( SOT_FORMATSTR_ID_SVXB );
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
+ {
+ // If it's a Writer object, insert RTF instead of OLE
+
+ // Else, if the class id is all-zero, and SYLK is available,
+ // it probably is spreadsheet cells that have been put
+ // on the clipboard by OOo, so use the SYLK. (fdo#31077)
+
+ sal_Bool bDoRtf = false;
+ TransferableObjectDescriptor aObjDesc;
+ if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
+ {
+ bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
+ aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
+ && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
+ }
+ if ( bDoRtf )
+ PasteFromSystem( FORMAT_RTF );
+ else if ( aObjDesc.maClassName == SvGlobalName( 0,0,0,0,0,0,0,0,0,0,0 )
+ && aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ))
+ PasteFromSystem( SOT_FORMATSTR_ID_SYLK );
+ else
+ PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE );
+ }
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
+ PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE );
+ // the following format can not affect scenario from #89579#
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
+ PasteFromSystem( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE );
+ // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
+ else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
+ PasteFromSystem(nBiff8);
+ else if (aDataHelper.HasFormat(nBiff5))
+ PasteFromSystem(nBiff5);
+ else if (aDataHelper.HasFormat(FORMAT_RTF))
+ PasteFromSystem(FORMAT_RTF);
+ else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
+ PasteFromSystem(SOT_FORMATSTR_ID_HTML);
+ else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
+ PasteFromSystem(SOT_FORMATSTR_ID_HTML_SIMPLE);
+ else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
+ PasteFromSystem(SOT_FORMATSTR_ID_SYLK);
+ else if (aDataHelper.HasFormat(FORMAT_STRING))
+ PasteFromSystem(FORMAT_STRING);
+ else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
+ PasteFromSystem(FORMAT_GDIMETAFILE);
+ else if (aDataHelper.HasFormat(FORMAT_BITMAP))
+ PasteFromSystem(FORMAT_BITMAP);
+ // xxx_OLE formats come last, like in SotExchange tables
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
+ PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE );
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
+ PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE_OLE );
+ }
+ }
+ // keine Fehlermeldung, weil SID_PASTE in der idl das FastCall-Flag hat,
+ // also auch gerufen wird, wenn nichts im Clipboard steht (#42531#)
+}
+
+void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTransferable>& rxTransferable )
+{
+ ScTransferObj *pOwnClip=0;
+ ScDrawTransferObj *pDrawClip=0;
+ uno::Reference<lang::XUnoTunnel> xTunnel( rxTransferable, uno::UNO_QUERY );
+ if ( xTunnel.is() )
+ {
+ sal_Int64 nHandle = xTunnel->getSomething( ScTransferObj::getUnoTunnelId() );
+ if ( nHandle )
+ pOwnClip = (ScTransferObj*) (sal_IntPtr) nHandle;
+ else
+ {
+ nHandle = xTunnel->getSomething( ScDrawTransferObj::getUnoTunnelId() );
+ if ( nHandle )
+ pDrawClip = (ScDrawTransferObj*) (sal_IntPtr) nHandle;
+ }
+ }
+
+ if (pOwnClip)
+ {
+ PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
+ PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
+ sal_True ); // allow warning dialog
+ }
+ else if (pDrawClip)
+ {
+ ScViewData* pViewData = GetViewData();
+ SCCOL nPosX = pViewData->GetCurX();
+ SCROW nPosY = pViewData->GetCurY();
+ Window* pWin = GetActiveWin();
+ Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY, pViewData->GetActivePart() ) );
+ PasteDraw( aPos, pDrawClip->GetModel(), false, pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
+ }
+ else
+ {
+ TransferableDataHelper aDataHelper( rxTransferable );
+ {
+ sal_uLong nBiff8 = SotExchange::RegisterFormatName(
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff8")));
+ sal_uLong nBiff5 = SotExchange::RegisterFormatName(
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff5")));
+ sal_uLong nFormatId = 0;
+ // als erstes SvDraw-Model, dann Grafik
+ // (Grafik darf nur bei einzelner Grafik drinstehen)
+
+ if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
+ nFormatId = SOT_FORMATSTR_ID_DRAWING;
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
+ nFormatId = SOT_FORMATSTR_ID_SVXB;
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
+ {
+ // If it's a Writer object, insert RTF instead of OLE
+ sal_Bool bDoRtf = false;
+ TransferableObjectDescriptor aObjDesc;
+ if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
+ {
+ bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
+ aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
+ && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
+ }
+ if ( bDoRtf )
+ nFormatId = FORMAT_RTF;
+ else
+ nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
+ }
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
+ nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
+ // the following format can not affect scenario from #89579#
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
+ nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
+ // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
+ else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
+ nFormatId = nBiff8;
+ else if (aDataHelper.HasFormat(nBiff5))
+ nFormatId = nBiff5;
+ else if (aDataHelper.HasFormat(FORMAT_RTF))
+ nFormatId = FORMAT_RTF;
+ else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
+ nFormatId = SOT_FORMATSTR_ID_HTML;
+ else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
+ nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
+ else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
+ nFormatId = SOT_FORMATSTR_ID_SYLK;
+ else if (aDataHelper.HasFormat(FORMAT_STRING))
+ nFormatId = FORMAT_STRING;
+ else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
+ nFormatId = FORMAT_GDIMETAFILE;
+ else if (aDataHelper.HasFormat(FORMAT_BITMAP))
+ nFormatId = FORMAT_BITMAP;
+ // xxx_OLE formats come last, like in SotExchange tables
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
+ nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
+ else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
+ nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
+ else
+ return;
+
+ PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
+ GetViewData()->GetCurX(), GetViewData()->GetCurY(),
+ NULL, false, false );
+ }
+ }
+}
+
+sal_Bool ScViewFunc::PasteFromSystem( sal_uLong nFormatId, sal_Bool bApi )
+{
+ UpdateInputLine();
+
+ sal_Bool bRet = sal_True;
+ Window* pWin = GetActiveWin();
+ ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
+ if ( nFormatId == 0 && pOwnClip )
+ {
+ // keep a reference in case the clipboard is changed during PasteFromClip
+ uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
+ PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
+ PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
+ !bApi ); // allow warning dialog
+ }
+ else
+ {
+ TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
+ if ( !aDataHelper.GetTransferable().is() )
+ return false;
+
+ bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
+ GetViewData()->GetCurX(), GetViewData()->GetCurY(),
+ NULL, false, !bApi ); // allow warning dialog
+
+ if ( !bRet && !bApi )
+ ErrorMessage(STR_PASTE_ERROR);
+ }
+ return bRet;
+}
+
+
+//----------------------------------------------------------------------------
+// P A S T E
+
+sal_Bool ScViewFunc::PasteOnDrawObject( const uno::Reference<datatransfer::XTransferable>& rxTransferable,
+ SdrObject* pHitObj, sal_Bool bLink )
+{
+ sal_Bool bRet = false;
+ if ( bLink )
+ {
+ TransferableDataHelper aDataHelper( rxTransferable );
+ if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
+ {
+ SotStorageStreamRef xStm;
+ if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) )
+ {
+ Graphic aGraphic;
+ *xStm >> aGraphic;
+ bRet = ApplyGraphicToObject( pHitObj, aGraphic );
+ }
+ }
+ else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
+ {
+ GDIMetaFile aMtf;
+ if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) )
+ bRet = ApplyGraphicToObject( pHitObj, Graphic(aMtf) );
+ }
+ else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
+ {
+ Bitmap aBmp;
+ if( aDataHelper.GetBitmap( FORMAT_BITMAP, aBmp ) )
+ bRet = ApplyGraphicToObject( pHitObj, Graphic(aBmp) );
+ }
+ }
+ else
+ {
+ // ham' wa noch nich
+ }
+ return bRet;
+}
+
+sal_Bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+ const ScMarkData& rTabSelection, sal_uInt16 nMask )
+{
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if ( rTabSelection.GetTableSelect(nTab) && pDoc->HasAttrib( nCol1, nRow1, nTab, nCol2, nRow2, nTab, nMask ) )
+ return sal_True;
+ return false;
+}
+
+//
+// Einfuegen auf Tabelle:
+//
+
+// internes Paste
+
+namespace {
+
+class CursorSwitcher
+{
+public:
+ CursorSwitcher(ScViewFunc* pViewFunc) :
+ mpViewFunc(pViewFunc)
+ {
+ mpViewFunc->HideCursor();
+ }
+
+ ~CursorSwitcher()
+ {
+ mpViewFunc->ShowCursor();
+ }
+private:
+ ScViewFunc* mpViewFunc;
+};
+
+bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
+{
+ bool bIsEmpty = true;
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab < nTabCount && bIsEmpty; ++nTab)
+ {
+ if (!rMark.GetTableSelect(nTab))
+ continue;
+
+ bIsEmpty = pDoc->IsBlockEmpty(nTab, rDestRange.aStart.Col(), rDestRange.aStart.Row(),
+ rDestRange.aEnd.Col(), rDestRange.aEnd.Row());
+ }
+
+ if (!bIsEmpty)
+ {
+ ScReplaceWarnBox aBox(pParentWnd);
+ if (aBox.Execute() != RET_YES)
+ {
+ // changing the configuration is within the ScReplaceWarnBox
+ return false;
+ }
+ }
+ return true;
+}
+
+}
+
+sal_Bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
+ sal_uInt16 nFunction, sal_Bool bSkipEmpty,
+ sal_Bool bTranspose, sal_Bool bAsLink,
+ InsCellCmd eMoveMode, sal_uInt16 nUndoExtraFlags,
+ sal_Bool bAllowDialogs )
+{
+ if (!pClipDoc)
+ {
+ OSL_FAIL("PasteFromClip: pClipDoc=0 not allowed");
+ return false;
+ }
+
+ // fuer Undo etc. immer alle oder keine Inhalte sichern
+ sal_uInt16 nContFlags = IDF_NONE;
+ if (nFlags & IDF_CONTENTS)
+ nContFlags |= IDF_CONTENTS;
+ if (nFlags & IDF_ATTRIB)
+ nContFlags |= IDF_ATTRIB;
+ // evtl. Attribute ins Undo ohne sie vom Clip ins Doc zu kopieren
+ sal_uInt16 nUndoFlags = nContFlags;
+ if (nUndoExtraFlags & IDF_ATTRIB)
+ nUndoFlags |= IDF_ATTRIB;
+ // do not copy note captions into undo document
+ nUndoFlags |= IDF_NOCAPTIONS;
+
+ ScClipParam& rClipParam = pClipDoc->GetClipParam();
+ if (rClipParam.isMultiRange())
+ return PasteMultiRangesFromClip(
+ nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
+ eMoveMode, nContFlags, nUndoFlags);
+
+ sal_Bool bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
+ sal_Bool bIncludeFiltered = bCutMode;
+
+ // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions)
+ sal_Bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) );
+
+ ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip
+ ScDocument* pOrigClipDoc = NULL;
+ ::std::auto_ptr< ScDocument > xTransClip;
+ if ( bTranspose )
+ {
+ SCCOL nX;
+ SCROW nY;
+ // include filtered rows until TransposeClip can skip them
+ bIncludeFiltered = sal_True;
+ pClipDoc->GetClipArea( nX, nY, sal_True );
+ if ( nY > static_cast<sal_Int32>(MAXCOL) ) // zuviele Zeilen zum Transponieren
+ {
+ ErrorMessage(STR_PASTE_FULL);
+ return false;
+ }
+ pOrigClipDoc = pClipDoc; // fuer Referenzen
+
+ if ( bPasteDraw )
+ {
+ aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately
+ aTransShellRef->DoInitNew(NULL);
+ }
+ ScDrawLayer::SetGlobalDrawPersist(aTransShellRef);
+
+ xTransClip.reset( new ScDocument( SCDOCMODE_CLIP ));
+ pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink );
+ pClipDoc = xTransClip.get();
+
+ ScDrawLayer::SetGlobalDrawPersist(NULL);
+ }
+
+ SCCOL nStartCol;
+ SCROW nStartRow;
+ SCTAB nStartTab;
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ SCTAB nEndTab;
+ SCCOL nClipSizeX;
+ SCROW nClipSizeY;
+ pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, sal_True ); // size in clipboard doc
+
+ // size in target doc: include filtered rows only if CutMode is set
+ SCCOL nDestSizeX;
+ SCROW nDestSizeY;
+ pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered );
+
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
+ const sal_Bool bRecord(pDoc->IsUndoEnabled());
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ ScRange aMarkRange;
+ ScMarkData aFilteredMark( rMark); // local copy for all modifications
+ ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange, aFilteredMark);
+ bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED);
+ bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) ||
+ (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink)));
+
+ if (!bNoPaste)
+ {
+ if (!rMark.IsMarked())
+ {
+ // Create a selection with clipboard row count and check that for
+ // filtered.
+ nStartCol = GetViewData()->GetCurX();
+ nStartRow = GetViewData()->GetCurY();
+ nStartTab = GetViewData()->GetTabNo();
+ nEndCol = nStartCol + nDestSizeX;
+ nEndRow = nStartRow + nDestSizeY;
+ nEndTab = nStartTab;
+ aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
+ if (ScViewUtil::HasFiltered( aMarkRange, pDoc))
+ {
+ bMarkIsFiltered = true;
+ // Fit to clipboard's row count unfiltered rows. If there is no
+ // fit assume that pasting is not possible. Note that nDestSizeY is
+ // size-1 (difference).
+ if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
+ bNoPaste = true;
+ }
+ aFilteredMark.SetMarkArea( aMarkRange);
+ }
+ else
+ {
+ // Expand the marked area when the destination area is larger than the
+ // current selection, to get the undo do the right thing. (i#106711)
+ ScRange aRange;
+ aFilteredMark.GetMarkArea( aRange );
+ if( (aRange.aEnd.Col() - aRange.aStart.Col()) < nDestSizeX )
+ {
+ aRange.aEnd.SetCol(aRange.aStart.Col() + nDestSizeX);
+ aFilteredMark.SetMarkArea(aRange);
+ }
+ }
+ }
+
+ if (bNoPaste)
+ {
+ ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
+ return false;
+ }
+
+ SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1;
+ ScRangeList aRangeList;
+ if (bMarkIsFiltered)
+ {
+ ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
+ aFilteredMark.FillRangeListWithMarks( &aRangeList, false);
+ nUnfilteredRows = 0;
+ size_t ListSize = aRangeList.size();
+ for ( size_t i = 0; i < ListSize; ++i )
+ {
+ ScRange* p = aRangeList[i];
+ nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1;
+ }
+#if 0
+ /* This isn't needed but could be a desired restriction. */
+ // For filtered, destination rows have to be an exact multiple of
+ // source rows. Note that nDestSizeY is size-1 (difference), so
+ // nDestSizeY==0 fits always.
+ if ((nUnfilteredRows % (nDestSizeY+1)) != 0)
+ {
+ /* FIXME: this should be a more descriptive error message then. */
+ ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
+ return false;
+ }
+#endif
+ }
+
+ // Also for a filtered selection the area is used, for undo et al.
+ if ( aFilteredMark.IsMarked() || bMarkIsFiltered )
+ {
+ aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
+ SCCOL nBlockAddX = nEndCol-nStartCol;
+ SCROW nBlockAddY = nEndRow-nStartRow;
+
+ // Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner
+ // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt)
+
+ // ClipSize is not size, but difference
+ if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) ||
+ ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) ||
+ ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) )
+ {
+ ScWaitCursorOff aWaitOff( GetFrameWin() );
+ String aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER );
+ QueryBox aBox( GetViewData()->GetDialogParent(),
+ WinBits(WB_YES_NO | WB_DEF_NO), aMessage );
+ if ( aBox.Execute() != RET_YES )
+ {
+ return false;
+ }
+ }
+
+ if (nBlockAddX <= nDestSizeX)
+ nEndCol = nStartCol + nDestSizeX;
+
+ if (nBlockAddY <= nDestSizeY)
+ {
+ nEndRow = nStartRow + nDestSizeY;
+ if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row())
+ {
+ // Same as above if nothing was marked: re-fit selection to
+ // unfiltered rows. Extending the selection actually may
+ // introduce filtered rows where there weren't any before, so
+ // we also need to test for that.
+ aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
+ if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc))
+ {
+ bMarkIsFiltered = true;
+ // Worst case: all rows up to the end of the sheet are filtered.
+ if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
+ {
+ ErrorMessage(STR_PASTE_FULL);
+ return false;
+ }
+ }
+ aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
+ aFilteredMark.SetMarkArea( aMarkRange);
+ if (bMarkIsFiltered)
+ {
+ ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
+ aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True);
+ }
+ }
+ }
+ }
+ else
+ {
+ nStartCol = GetViewData()->GetCurX();
+ nStartRow = GetViewData()->GetCurY();
+ nStartTab = GetViewData()->GetTabNo();
+ nEndCol = nStartCol + nDestSizeX;
+ nEndRow = nStartRow + nDestSizeY;
+ nEndTab = nStartTab;
+ }
+
+ bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow);
+
+ // Zielbereich, wie er angezeigt wird:
+ ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
+
+ // Sollen Zellen eingefuegt werden?
+ // (zu grosse nEndCol/nEndRow werden weiter unten erkannt)
+ sal_Bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits );
+ if ( bInsertCells )
+ {
+ // Instead of EnterListAction, the paste undo action is merged into the
+ // insert action, so Repeat can insert the right cells
+
+ MarkRange( aUserRange ); // wird vor CopyFromClip sowieso gesetzt
+
+ // CutMode is reset on insertion of cols/rows but needed again on cell move
+ sal_Bool bCut = pClipDoc->IsCutMode();
+ if (!InsertCells( eMoveMode, bRecord, true )) // is inserting possible?
+ {
+ return false;
+ // #i21036# EnterListAction isn't used, and InsertCells doesn't insert
+ // its undo action on failure, so no undo handling is needed here
+ }
+ if ( bCut )
+ pClipDoc->SetCutMode( bCut );
+ }
+ else if (!bOffLimits)
+ {
+ sal_Bool bAskIfNotEmpty = bAllowDialogs &&
+ ( nFlags & IDF_CONTENTS ) &&
+ nFunction == PASTE_NOFUNC &&
+ SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
+ if ( bAskIfNotEmpty )
+ {
+ if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
+ return false;
+ }
+ }
+
+ SCCOL nClipStartX; // Clipboard-Bereich erweitern
+ SCROW nClipStartY;
+ pClipDoc->GetClipStart( nClipStartX, nClipStartY );
+ SCCOL nUndoEndCol = nClipStartX + nClipSizeX;
+ SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document
+ sal_Bool bClipOver = false;
+ // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers.
+ // The same end column/row can be used for all calls because the clip doc doesn't contain
+ // content outside the clip area.
+ for (SCTAB nClipTab=0; nClipTab<=MAXTAB; nClipTab++)
+ if ( pClipDoc->HasTable(nClipTab) )
+ if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, false ) )
+ bClipOver = sal_True;
+ nUndoEndCol -= nClipStartX + nClipSizeX;
+ nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge
+ nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol );
+ nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells
+
+ if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW)
+ {
+ ErrorMessage(STR_PASTE_FULL);
+ return false;
+ }
+
+ pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, false );
+
+ // Test auf Zellschutz
+
+ ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow );
+ if (!aTester.IsEditable())
+ {
+ ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ //! Test auf Ueberlappung
+ //! nur wirkliche Schnittmenge testen !!!!!!!
+
+ ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
+ if ( bRecord )
+ {
+ String aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY );
+ pUndoMgr->EnterListAction( aUndo, aUndo );
+ }
+
+ if (bClipOver)
+ if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED ))
+ { // "Cell merge not possible if cells already merged"
+ ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow );
+ const ScPatternAttr* pPattern = NULL;
+ const ScMergeAttr* pMergeFlag = NULL;
+ const ScMergeFlagAttr* pMergeFlagAttr = NULL;
+ SCCOL nCol = -1;
+ SCROW nRow1 = -1;
+ SCROW nRow2 = -1;
+ while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL )
+ {
+ pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
+ pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
+ if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) )
+ {
+ ScRange aRange(nCol, nRow1, nStartTab);
+ pDoc->ExtendOverlapped(aRange);
+ pDoc->ExtendMerge(aRange, sal_True, sal_True);
+ rDocFunc.UnmergeCells(aRange, bRecord, sal_True);
+ }
+ }
+ }
+
+ if ( !bCutMode )
+ {
+ ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
+ if ( pChangeTrack )
+ pChangeTrack->ResetLastCut(); // kein CutMode mehr
+ }
+
+ sal_Bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
+ sal_Bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
+
+ ScDocument* pUndoDoc = NULL;
+ ScDocument* pRefUndoDoc = NULL;
+ ScDocument* pRedoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo );
+
+ // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
+ SCTAB nTabCount = pDoc->GetTableCount();
+ pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1,
+ nUndoFlags, false, pUndoDoc );
+
+ if ( bCutMode )
+ {
+ pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
+
+ pUndoData = new ScRefUndoData( pDoc );
+ }
+ }
+
+ sal_uInt16 nExtFlags = 0;
+ pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
+ nEndCol, nEndRow, nEndTab ); // content before the change
+
+ if (GetViewData()->IsActive())
+ {
+ DoneBlockMode();
+ InitOwnBlockMode();
+ }
+ rMark.SetMarkArea( aUserRange );
+ MarkDataChanged();
+
+ HideCursor(); // Cursor aendert sich !
+
+ //
+ // Aus Clipboard kopieren,
+ // wenn gerechnet werden soll, Originaldaten merken
+ //
+
+ ScDocument* pMixDoc = NULL;
+ if ( bSkipEmpty || nFunction )
+ {
+ if ( nFlags & IDF_CONTENTS )
+ {
+ pMixDoc = new ScDocument( SCDOCMODE_UNDO );
+ pMixDoc->InitUndo( pDoc, nStartTab, nEndTab );
+ pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
+ IDF_CONTENTS, false, pMixDoc );
+ }
+ }
+
+ /* Make draw layer and start drawing undo.
+ - Needed before AdjustBlockHeight to track moved drawing objects.
+ - Needed before pDoc->CopyFromClip to track inserted note caption objects.
+ */
+ if ( bPasteDraw )
+ pDocSh->MakeDrawLayer();
+ if ( bRecord )
+ pDoc->BeginDrawUndo();
+
+ sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
+ if (!bAsLink)
+ {
+ // copy normally (original range)
+ pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags,
+ pRefUndoDoc, pClipDoc, sal_True, false, bIncludeFiltered,
+ bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) );
+
+ // bei Transpose Referenzen per Hand anpassen
+ if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) )
+ pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc );
+ }
+ else if (!bTranspose)
+ {
+ // copy with bAsLink=TRUE
+ pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc,
+ sal_True, sal_True, bIncludeFiltered, bSkipEmpty );
+ }
+ else
+ {
+ // alle Inhalte kopieren (im TransClipDoc stehen nur Formeln)
+ pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc );
+ }
+
+ // skipped rows and merged cells don't mix
+ if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
+ rDocFunc.UnmergeCells( aUserRange, false, sal_True );
+
+ pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, sal_True ); // Refresh
+ // und Bereich neu
+
+ if ( pMixDoc ) // Rechenfunktionen mit Original-Daten auszufuehren ?
+ {
+ pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc );
+ }
+ delete pMixDoc;
+
+ AdjustBlockHeight(); // update row heights before pasting objects
+
+ ::std::vector< ::rtl::OUString > aExcludedChartNames;
+ SdrPage* pPage = NULL;
+
+ if ( nFlags & IDF_OBJECTS )
+ {
+ ScDrawView* pScDrawView = GetScDrawView();
+ SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL );
+ pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL );
+ if ( pPage )
+ {
+ ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
+ }
+
+ // Paste the drawing objects after the row heights have been updated.
+
+ pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc,
+ sal_True, false, bIncludeFiltered );
+ }
+
+
+ pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
+ nEndCol, nEndRow, nEndTab ); // content after the change
+
+
+ // ggf. Autofilter-Koepfe loeschen
+ if (bCutMode)
+ if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX,
+ nClipStartY+nClipSizeY, nStartTab ))
+ pDocSh->PostPaint( nClipStartX,nClipStartY,nStartTab,
+ nClipStartX+nClipSizeX,nClipStartY,nStartTab,
+ PAINT_GRID );
+
+ ShowCursor(); // Cursor aendert sich !
+
+ //! Block-Bereich bei RefUndoDoc weglassen !!!
+
+ if ( bRecord )
+ {
+ // Redo-Daten werden erst beim ersten Undo kopiert
+ // ohne RefUndoDoc muss das Redo-Doc noch nicht angelegt werden
+
+ if (pRefUndoDoc)
+ {
+ pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo );
+
+ // angepasste Referenzen ins Redo-Doc
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ pRedoDoc->AddUndoTab( 0, nTabCount-1 );
+ pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc );
+
+ // alte Referenzen ins Undo-Doc
+
+ //! Tabellen selektieren ?
+ pUndoDoc->AddUndoTab( 0, nTabCount-1 );
+ pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL );
+ pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
+ IDF_FORMULA, false, pUndoDoc );
+ delete pRefUndoDoc;
+ }
+
+ // DeleteUnchanged for pUndoData is in ScUndoPaste ctor,
+ // UndoData for redo is made during first undo
+
+ ScUndoPasteOptions aOptions; // store options for repeat
+ aOptions.nFunction = nFunction;
+ aOptions.bSkipEmpty = bSkipEmpty;
+ aOptions.bTranspose = bTranspose;
+ 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 ); // sal_False = Redo data not yet copied
+
+ if ( bInsertCells )
+ {
+ // Merge the paste undo action into the insert action.
+ // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action.
+
+ pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), sal_True );
+ }
+ else
+ pUndoMgr->AddUndoAction( pUndo );
+ pUndoMgr->LeaveListAction();
+ }
+
+ sal_uInt16 nPaint = PAINT_GRID;
+ if (bColInfo)
+ {
+ nPaint |= PAINT_TOP;
+ nUndoEndCol = MAXCOL; // nur zum Zeichnen !
+ }
+ if (bRowInfo)
+ {
+ nPaint |= PAINT_LEFT;
+ nUndoEndRow = MAXROW; // nur zum Zeichnen !
+ }
+ pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
+ nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags );
+ // AdjustBlockHeight has already been called above
+
+ aModificator.SetDocumentModified();
+ PostPasteFromClip(aUserRange, rMark);
+
+ if ( nFlags & IDF_OBJECTS )
+ {
+ ScModelObj* pModelObj = ( pDocSh ? ScModelObj::getImplementation( pDocSh->GetModel() ) : NULL );
+ if ( pDoc && pPage && pModelObj )
+ {
+ bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() );
+ const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector );
+ ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab,
+ rProtectedChartRangesVector, aExcludedChartNames, bSameDoc );
+ }
+ }
+
+ return sal_True;
+}
+
+bool ScViewFunc::PasteMultiRangesFromClip(
+ sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
+ bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
+ InsCellCmd eMoveMode, sal_uInt16 /*nContFlags*/, sal_uInt16 nUndoFlags)
+{
+ ScViewData& rViewData = *GetViewData();
+ ScDocument* pDoc = rViewData.GetDocument();
+ ScDocShell* pDocSh = rViewData.GetDocShell();
+ ScMarkData aMark(rViewData.GetMarkData());
+ const ScAddress& rCurPos = rViewData.GetCurPos();
+ ScClipParam& rClipParam = pClipDoc->GetClipParam();
+ SCCOL nColSize = rClipParam.getPasteColSize();
+ SCROW nRowSize = rClipParam.getPasteRowSize();
+
+ if (bTranspose)
+ {
+ if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
+ {
+ ErrorMessage(STR_PASTE_FULL);
+ return false;
+ }
+
+ ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
+ pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
+ pClipDoc = pTransClip.release();
+ SCCOL nTempColSize = nColSize;
+ nColSize = static_cast<SCCOL>(nRowSize);
+ nRowSize = static_cast<SCROW>(nTempColSize);
+ }
+
+ if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
+ {
+ ErrorMessage(STR_PASTE_FULL);
+ return false;
+ }
+
+ // Determine the first and last selected sheet numbers.
+ SCTAB nTab1 = aMark.GetFirstSelected();
+ SCTAB nTab2 = nTab1;
+ for (SCTAB i = nTab1+1; i <= MAXTAB; ++i)
+ if (aMark.GetTableSelect(i))
+ nTab2 = i;
+
+ ScDocShellModificator aModificator(*pDocSh);
+
+ // For multi-selection paste, we don't support cell duplication for larger
+ // destination range. In case the destination is marked, we reset it to
+ // the clip size.
+ ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
+ rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
+
+ // Extend the marked range to account for filtered rows in the destination
+ // area.
+ if (ScViewUtil::HasFiltered(aMarkedRange, pDoc))
+ {
+ if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize))
+ return false;
+ }
+
+ bool bAskIfNotEmpty =
+ bAllowDialogs && (nFlags & IDF_CONTENTS) &&
+ nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
+
+ if (bAskIfNotEmpty)
+ {
+ if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent()))
+ return false;
+ }
+
+ aMark.SetMarkArea(aMarkedRange);
+ MarkRange(aMarkedRange);
+
+ bool bInsertCells = (eMoveMode != INS_NONE);
+ if (bInsertCells)
+ {
+ if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
+ return false;
+ }
+
+ ::std::auto_ptr<ScDocument> pUndoDoc;
+ if (pDoc->IsUndoEnabled())
+ {
+ pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
+ pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
+ pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true);
+ }
+
+ ::std::auto_ptr<ScDocument> pMixDoc;
+ if ( bSkipEmpty || nFunction )
+ {
+ if ( nFlags & IDF_CONTENTS )
+ {
+ pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
+ pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
+ pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
+ }
+ }
+
+ /* Make draw layer and start drawing undo.
+ - Needed before AdjustBlockHeight to track moved drawing objects.
+ - Needed before pDoc->CopyFromClip to track inserted note caption objects.
+ */
+ if (nFlags & IDF_OBJECTS)
+ pDocSh->MakeDrawLayer();
+ if (pDoc->IsUndoEnabled())
+ pDoc->BeginDrawUndo();
+
+ CursorSwitcher aCursorSwitch(this);
+ sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
+ pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
+ true, bAsLink, false, bSkipEmpty);
+
+ if (pMixDoc.get())
+ pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
+
+ AdjustBlockHeight(); // update row heights before pasting objects
+
+ if (nFlags & IDF_OBJECTS)
+ {
+ // Paste the drawing objects after the row heights have been updated.
+ pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
+ true, false, false, true);
+ }
+
+ pDocSh->PostPaint(
+ aMarkedRange.aStart.Col(), aMarkedRange.aStart.Row(), nTab1,
+ aMarkedRange.aEnd.Col(), aMarkedRange.aEnd.Row(), nTab1, PAINT_GRID);
+
+ if (pDoc->IsUndoEnabled())
+ {
+ ::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,
+ aMarkedRange.aStart.Col(),
+ aMarkedRange.aStart.Row(),
+ aMarkedRange.aStart.Tab(),
+ aMarkedRange.aEnd.Col(),
+ aMarkedRange.aEnd.Row(),
+ aMarkedRange.aEnd.Tab(),
+ aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions);
+
+ if (bInsertCells)
+ pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
+ else
+ pUndoMgr->AddUndoAction(pUndo, false);
+
+ pUndoMgr->LeaveListAction();
+ }
+ aModificator.SetDocumentModified();
+ PostPasteFromClip(aMarkedRange, aMark);
+ return true;
+}
+
+void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark)
+{
+ ScViewData* pViewData = GetViewData();
+ ScDocShell* pDocSh = pViewData->GetDocShell();
+ ScDocument* pDoc = pViewData->GetDocument();
+ pDocSh->UpdateOle(pViewData);
+
+ SelectionChanged();
+
+ // #i97876# Spreadsheet data changes are not notified
+ ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
+ if ( pModelObj && pModelObj->HasChangesListeners() )
+ {
+ ScRangeList aChangeRanges;
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for ( SCTAB i = 0; i < nTabCount; ++i )
+ {
+ if ( rMark.GetTableSelect( i ) )
+ {
+ ScRange aChangeRange(rPasteRange);
+ aChangeRange.aStart.SetTab( i );
+ aChangeRange.aEnd.SetTab( i );
+ aChangeRanges.Append( aChangeRange );
+ }
+ }
+ pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
+ }
+}
+
+
+//----------------------------------------------------------------------------
+// D R A G A N D D R O P
+//
+// innerhalb des Dokuments
+
+sal_Bool ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos,
+ sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
+{
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ HideAllCursors(); // wegen zusammengefassten
+
+ sal_Bool bSuccess = sal_True;
+ SCTAB nDestTab = rDestPos.Tab();
+ const ScMarkData& rMark = GetViewData()->GetMarkData();
+ if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 )
+ {
+ // moving within one table and several tables selected -> apply to all selected tables
+
+ if ( bRecord )
+ {
+ String aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY );
+ pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
+ }
+
+ // collect ranges of consecutive selected tables
+
+ ScRange aLocalSource = rSource;
+ ScAddress aLocalDest = rDestPos;
+ SCTAB nTabCount = pDocSh->GetDocument()->GetTableCount();
+ SCTAB nStartTab = 0;
+ while ( nStartTab < nTabCount && bSuccess )
+ {
+ while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) )
+ ++nStartTab;
+ if ( nStartTab < nTabCount )
+ {
+ SCTAB nEndTab = nStartTab;
+ while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) )
+ ++nEndTab;
+
+ aLocalSource.aStart.SetTab( nStartTab );
+ aLocalSource.aEnd.SetTab( nEndTab );
+ aLocalDest.SetTab( nStartTab );
+
+ bSuccess = pDocSh->GetDocFunc().MoveBlock(
+ aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi );
+
+ nStartTab = nEndTab + 1;
+ }
+ }
+
+ if ( bRecord )
+ pDocSh->GetUndoManager()->LeaveListAction();
+ }
+ else
+ {
+ // move the block as specified
+ bSuccess = pDocSh->GetDocFunc().MoveBlock(
+ rSource, rDestPos, bCut, bRecord, bPaint, bApi );
+ }
+
+ ShowAllCursors();
+ if (bSuccess)
+ {
+ // Zielbereich markieren
+ ScAddress aDestEnd(
+ rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(),
+ rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(),
+ nDestTab );
+
+ sal_Bool bIncludeFiltered = bCut;
+ if ( !bIncludeFiltered )
+ {
+ // find number of non-filtered rows
+ SCROW nPastedCount = pDocSh->GetDocument()->CountNonFilteredRows(
+ rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab());
+
+ if ( nPastedCount == 0 )
+ nPastedCount = 1;
+ aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 );
+ }
+
+ MarkRange( ScRange( rDestPos, aDestEnd ), false ); //! sal_False ???
+
+ pDocSh->UpdateOle(GetViewData());
+ SelectionChanged();
+ }
+ return bSuccess;
+}
+
+// Link innerhalb des Dokuments
+
+sal_Bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, sal_Bool bApi )
+{
+ // Test auf Ueberlappung
+
+ if ( rSource.aStart.Tab() == rDestPos.Tab() )
+ {
+ SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() );
+ SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() );
+
+ if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() &&
+ rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() )
+ {
+ if (!bApi)
+ ErrorMessage( STR_ERR_LINKOVERLAP );
+ return false;
+ }
+ }
+
+ // Ausfuehren per Paste
+
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
+ pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(),
+ rSource.aEnd.Col(), rSource.aEnd.Row(),
+ rSource.aStart.Tab(), pClipDoc );
+
+ // Zielbereich markieren (Cursor setzen, keine Markierung)
+
+ if ( GetViewData()->GetTabNo() != rDestPos.Tab() )
+ SetTabNo( rDestPos.Tab() );
+
+ MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, false, false );
+
+ // Paste
+
+ PasteFromClip( IDF_ALL, pClipDoc, PASTE_NOFUNC, false, false, sal_True ); // als Link
+
+ delete pClipDoc;
+
+ return sal_True;
+}
+
+void ScViewFunc::DataFormPutData( SCROW nCurrentRow ,
+ SCROW nStartRow , SCCOL nStartCol ,
+ SCROW nEndRow , SCCOL nEndCol ,
+ Edit** pEdits ,
+ sal_uInt16 aColLength )
+{
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ ScDocShellModificator aModificator( *pDocSh );
+ ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
+ if ( pDoc )
+ {
+ const sal_Bool bRecord( pDoc->IsUndoEnabled());
+ ScDocument* pUndoDoc = NULL;
+ ScDocument* pRedoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ SCTAB nTab = GetViewData()->GetTabNo();
+ SCTAB nStartTab = nTab;
+ SCTAB nEndTab = nTab;
+
+ {
+ ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
+ if ( pChangeTrack )
+ pChangeTrack->ResetLastCut(); // kein CutMode mehr
+ }
+ ScRange aUserRange( nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab );
+ sal_Bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
+ sal_Bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
+ SCCOL nUndoEndCol = nStartCol+aColLength-1;
+ SCROW nUndoEndRow = nCurrentRow;
+ sal_uInt16 nUndoFlags = IDF_NONE;
+
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndoSelected( pDoc , rMark , bColInfo , bRowInfo );
+ pDoc->CopyToDocument( aUserRange , 1 , false , pUndoDoc );
+ }
+ sal_uInt16 nExtFlags = 0;
+ pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab , nEndCol, nEndRow, nEndTab ); // content before the change
+ pDoc->BeginDrawUndo();
+
+ for(sal_uInt16 i = 0; i < aColLength; i++)
+ {
+ if (pEdits[i])
+ {
+ String aFieldName=pEdits[i]->GetText();
+ pDoc->SetString( nStartCol + i, nCurrentRow, nTab, aFieldName );
+ }
+ }
+ pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab ); // content after the change
+ SfxUndoAction* pUndo = new ScUndoDataForm( pDocSh,
+ nStartCol, nCurrentRow, nStartTab,
+ nUndoEndCol, nUndoEndRow, nEndTab, rMark,
+ pUndoDoc, pRedoDoc, nUndoFlags,
+ pUndoData, NULL, NULL, NULL,
+ false ); // FALSE = Redo data not yet copied
+ pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
+
+ sal_uInt16 nPaint = PAINT_GRID;
+ if (bColInfo)
+ {
+ nPaint |= PAINT_TOP;
+ nUndoEndCol = MAXCOL; // nur zum Zeichnen !
+ }
+ if (bRowInfo)
+ {
+ nPaint |= PAINT_LEFT;
+ nUndoEndRow = MAXROW; // nur zum Zeichnen !
+ }
+
+ pDocSh->PostPaint( nStartCol, nCurrentRow, nStartTab,
+ nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags );
+ pDocSh->UpdateOle(GetViewData());
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */