| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 _PRNDLG_HXX |
| //#define _POLY_HXX |
| #define _PVRWIN_HXX |
| //#define _QUEUE_HXX |
| #define _RULER_HXX |
| #define _SCRWIN_HXX |
| #define _SETBRW_HXX |
| //#define _STACK_HXX |
| //#define _STATUS_HXX *** |
| #define _STDCTRL_HXX |
| #define _STDMENU_HXX |
| //#define _TAB_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 _SELENG_HXX |
| //#define _SOUND_HXX |
| //#define _SYSDLG_HXX |
| |
| |
| |
| |
| #define _PASSWD_HXX |
| |
| #define _SFX_DOCFILE_HXX |
| //#define _SFX_DOCFILT_HXX |
| #define _SFX_DOCINF_HXX |
| #define _SFX_DOCSH_HXX |
| //#define _SFXDOCFILT_HXX |
| //#define _SFXDOCINF_HXX |
| //#define _SFXDOCSH_HXX |
| #define _SFX_PRNMON_HXX |
| #define _SFX_RESMGR_HXX |
| #define _SFX_TEMPLDLG_HXX |
| //#define _SFXAPPWIN_HXX |
| #define _SFXBASIC_HXX |
| #define _SFXCTRLITEM |
| #define _SFXDLGCFG_HXX |
| //#define _SFXDISPATCH_HXX |
| #define _SFXFILEDLG_HXX |
| //#define _SFXIMGMGR_HXX |
| #define _SFXIPFRM_HXX |
| #define _SFX_MACRO_HXX |
| #define _SFXMNUITEM_HXX |
| #define _SFXMNUMGR_HXX |
| #define _SFXMULTISEL_HXX |
| //#define _SFXMSG_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 _SI_DLL_HXX |
| //#define _SIDLL_HXX |
| //#define _SI_NOITEMS |
| //#define _SI_NOOTHERFORMS |
| //#define _SI_NOSBXCONTROLS |
| //#define _SINOSBXCONTROLS |
| //#define _SI_NODRW |
| //#define _SI_NOCONTROL |
| |
| #define _SVBOXITM_HXX |
| #define _SVCONTNR_HXX // |
| |
| #define _SDR_NOTRANSFORM |
| |
| #define _SVDRAG_HXX |
| #define _SVINCVW_HXX |
| //#define _SV_MULTISEL_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 "drawview.hxx" |
| #include "chartlis.hxx" |
| #include "charthelper.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, sal_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, sal_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 = sal_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 = sal_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; |
| ScRangePtr p = aClipParam.maRanges.First(); |
| SCCOL nPrevColDelta = 0; |
| SCROW nPrevRowDelta = 0; |
| SCCOL nPrevCol = p->aStart.Col(); |
| SCROW nPrevRow = p->aStart.Row(); |
| SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1; |
| SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1; |
| for (p = aClipParam.maRanges.Next(); p; p = aClipParam.maRanges.Next()) |
| { |
| if (pDoc->HasSelectedBlockMatrixFragment( |
| p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark)) |
| { |
| if (!bApi) |
| ErrorMessage(STR_MATRIXFRAGMENTERR); |
| return false; |
| } |
| |
| SCCOL nColDelta = p->aStart.Col() - nPrevCol; |
| SCROW nRowDelta = p->aStart.Row() - nPrevRow; |
| |
| if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta)) |
| { |
| bValidRanges = false; |
| break; |
| } |
| |
| if (aClipParam.meDirection == ScClipParam::Unspecified) |
| { |
| if (nColDelta) |
| aClipParam.meDirection = ScClipParam::Column; |
| if (nRowDelta) |
| aClipParam.meDirection = ScClipParam::Row; |
| } |
| |
| SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1; |
| SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1; |
| |
| if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize) |
| { |
| // column-oriented ranges must have identical row size. |
| bValidRanges = false; |
| break; |
| } |
| if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize) |
| { |
| // likewise, row-oriented ranges must have identical |
| // column size. |
| bValidRanges = false; |
| break; |
| } |
| |
| nPrevCol = p->aStart.Col(); |
| nPrevRow = p->aStart.Row(); |
| nPrevColDelta = nColDelta; |
| nPrevRowDelta = nRowDelta; |
| nPrevColSize = nColSize; |
| nPrevRowSize = nRowSize; |
| } |
| if (!bValidRanges) |
| break; |
| |
| pDoc->CopyToClip(aClipParam, pDocClip.get(), &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; |
| } |
| |
| 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(), sal_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) |
| { |
| // #129384# keep a reference in case the clipboard is changed during PasteFromClip |
| uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip ); |
| PasteFromClip( IDF_ALL, pOwnClip->GetDocument(), |
| PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, |
| sal_True ); // allow warning dialog |
| } |
| else if (pDrawClip) |
| PasteDraw(); |
| else |
| { |
| TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); |
| |
| // if (pClipObj.Is()) |
| { |
| 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 |
| |
| sal_Bool bDoRtf = sal_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 |
| 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); |
| // #89579# 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 ); |
| // else |
| // ErrorMessage(STR_PASTE_ERROR); |
| } |
| // else |
| // ErrorMessage(STR_PASTE_ERROR); |
| } |
| |
| // 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, sal_False, sal_False, sal_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(), sal_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 = sal_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; |
| // #89579# 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, sal_False, sal_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 ) |
| { |
| // #129384# keep a reference in case the clipboard is changed during PasteFromClip |
| uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip ); |
| PasteFromClip( IDF_ALL, pOwnClip->GetDocument(), |
| PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, |
| !bApi ); // allow warning dialog |
| } |
| else |
| { |
| TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); |
| if ( !aDataHelper.GetTransferable().is() ) |
| return sal_False; |
| |
| bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(), |
| GetViewData()->GetCurX(), GetViewData()->GetCurY(), |
| NULL, sal_False, !bApi ); // allow warning dialog |
| |
| if ( !bRet && !bApi ) |
| ErrorMessage(STR_PASTE_ERROR); |
| } |
| return bRet; |
| } |
| |
| |
| //---------------------------------------------------------------------------- |
| // P A S T E |
| |
| sal_Bool ScViewFunc::PasteOnDrawObjectLinked( |
| const uno::Reference<datatransfer::XTransferable>& rxTransferable, |
| SdrObject& rHitObj) |
| { |
| TransferableDataHelper aDataHelper( rxTransferable ); |
| |
| if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) ) |
| { |
| SotStorageStreamRef xStm; |
| ScDrawView* pScDrawView = GetScDrawView(); |
| |
| if( pScDrawView && aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) ) |
| { |
| Graphic aGraphic; |
| |
| *xStm >> aGraphic; |
| |
| const String aEmpty; |
| const String aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP)); |
| |
| if(pScDrawView->ApplyGraphicToObject( rHitObj, aGraphic, aBeginUndo, aEmpty, aEmpty )) |
| { |
| return sal_True; |
| } |
| } |
| } |
| else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) ) |
| { |
| GDIMetaFile aMtf; |
| ScDrawView* pScDrawView = GetScDrawView(); |
| |
| if( pScDrawView && aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) ) |
| { |
| const String aEmpty; |
| const String aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP)); |
| |
| if(pScDrawView->ApplyGraphicToObject( rHitObj, Graphic(aMtf), aBeginUndo, aEmpty, aEmpty )) |
| { |
| return sal_True; |
| } |
| } |
| } |
| else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) || aDataHelper.HasFormat( SOT_FORMATSTR_ID_PNG ) ) |
| { |
| BitmapEx aBmpEx; |
| ScDrawView* pScDrawView = GetScDrawView(); |
| |
| if( pScDrawView && aDataHelper.GetBitmapEx( FORMAT_BITMAP, aBmpEx ) ) |
| { |
| const String aEmpty; |
| const String aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP)); |
| |
| if(pScDrawView->ApplyGraphicToObject( rHitObj, Graphic(aBmpEx), aBeginUndo, aEmpty, aEmpty )) |
| { |
| return sal_True; |
| } |
| } |
| } |
| |
| return sal_False; |
| } |
| |
| 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 sal_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) |
| { |
| DBG_ERROR("PasteFromClip: pClipDoc=0 not allowed"); |
| return sal_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 sal_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 && !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); |
| } |
| if (bNoPaste) |
| { |
| ErrorMessage(STR_MSSG_PASTEFROMCLIP_0); |
| return sal_False; |
| } |
| |
| SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1; |
| ScRangeList aRangeList; |
| if (bMarkIsFiltered) |
| { |
| ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc); |
| aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_False); |
| nUnfilteredRows = 0; |
| for (ScRange* p = aRangeList.First(); p; p = aRangeList.Next()) |
| { |
| 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 sal_False; |
| } |
| #endif |
| } |
| |
| SCCOL nMarkAddX = 0; |
| SCROW nMarkAddY = 0; |
| |
| // 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; |
| |
| // #58422# 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 sal_False; |
| } |
| } |
| |
| if (nBlockAddX > nDestSizeX) |
| nMarkAddX = nBlockAddX - nDestSizeX; // fuer Merge-Test |
| else |
| { |
| nEndCol = nStartCol + nDestSizeX; |
| if (nEndCol > aMarkRange.aEnd.Col()) |
| { |
| // #i113553# larger range has to be included in aFilteredMark (for undo), but extending columns can't changed the filtered status |
| aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); |
| aFilteredMark.SetMarkArea( aMarkRange ); |
| if (bMarkIsFiltered) |
| { |
| ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc ); |
| aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True ); |
| } |
| } |
| } |
| |
| if (nBlockAddY > nDestSizeY) |
| nMarkAddY = nBlockAddY - nDestSizeY; // fuer Merge-Test |
| else |
| { |
| 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 sal_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 ) |
| { |
| // #94115# 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 |
| |
| // #72930# CutMode is reset on insertion of cols/rows but needed again on cell move |
| sal_Bool bCut = pClipDoc->IsCutMode(); |
| if (!InsertCells( eMoveMode, bRecord, sal_True )) // is inserting possible? |
| { |
| return sal_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 = sal_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, sal_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 < nEndCol) nUndoEndCol = nEndCol; |
| // if (nUndoEndRow < nEndRow) nUndoEndRow = nEndRow; |
| |
| // nUndoEndCol += nMarkAddX; |
| // nUndoEndRow += nMarkAddY; |
| |
| if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW) |
| { |
| ErrorMessage(STR_PASTE_FULL); |
| return sal_False; |
| } |
| |
| pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, sal_False ); |
| |
| // Test auf Zellschutz |
| |
| ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow ); |
| if (!aTester.IsEditable()) |
| { |
| ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| //! Test auf Ueberlappung |
| //! nur wirkliche Schnittmenge testen !!!!!!! |
| |
| // pDoc->HasCommonAttr( StartCol,nStartRow, nUndoEndCol,nUndoEndRow, nStartTab, |
| // pClipDoc, nClipStartX, nClipStartY ); |
| |
| 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, sal_False, pUndoDoc ); |
| |
| if ( bCutMode ) |
| { |
| pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_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, sal_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, sal_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, sal_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, sal_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, sal_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, |
| sal_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 ), sal_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 sal_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, sal_False, sal_False ); |
| |
| // Paste |
| |
| PasteFromClip( IDF_ALL, pClipDoc, PASTE_NOFUNC, sal_False, sal_False, sal_True ); // als Link |
| |
| delete pClipDoc; |
| |
| return sal_True; |
| } |
| |
| |
| |
| |