fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / view / viewfun3.cxx
blob4091230f9cc09a59f4b9817b5fc0a939c65de839
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <svx/svdetc.hxx>
22 #include <svx/svditer.hxx>
23 #include <svx/svdoole2.hxx>
24 #include <svx/svdpage.hxx>
25 #include <sfx2/dispatch.hxx>
26 #include <sfx2/docfile.hxx>
27 #include <svl/stritem.hxx>
28 #include <svl/ptitem.hxx>
29 #include <svl/urlbmk.hxx>
30 #include <comphelper/classids.hxx>
31 #include <sot/formats.hxx>
32 #include <sot/storage.hxx>
33 #include <vcl/graph.hxx>
34 #include <vcl/virdev.hxx>
35 #include <vcl/msgbox.hxx>
36 #include <tools/urlobj.hxx>
37 #include <sot/exchange.hxx>
38 #include <memory>
40 #include "attrib.hxx"
41 #include "patattr.hxx"
42 #include "dociter.hxx"
43 #include "viewfunc.hxx"
44 #include "tabvwsh.hxx"
45 #include "docsh.hxx"
46 #include "docfunc.hxx"
47 #include "undoblk.hxx"
48 #include "refundo.hxx"
49 #include "globstr.hrc"
50 #include "global.hxx"
51 #include "transobj.hxx"
52 #include "drwtrans.hxx"
53 #include "rangenam.hxx"
54 #include "dbdata.hxx"
55 #include "impex.hxx"
56 #include "chgtrack.hxx"
57 #include "waitoff.hxx"
58 #include "scmod.hxx"
59 #include "sc.hrc"
60 #include "inputopt.hxx"
61 #include "warnbox.hxx"
62 #include "drwlayer.hxx"
63 #include "editable.hxx"
64 #include "docuno.hxx"
65 #include "clipparam.hxx"
66 #include "undodat.hxx"
67 #include "drawview.hxx"
68 #include "cliputil.hxx"
69 #include <gridwin.hxx>
70 #include <boost/scoped_ptr.hpp>
72 using namespace com::sun::star;
74 // STATIC DATA ---------------------------------------------------------------
76 // GlobalName of writer-DocShell from comphelper/classids.hxx
78 // C U T
80 void ScViewFunc::CutToClip( ScDocument* pClipDoc, bool bIncludeObjects )
82 UpdateInputLine();
84 ScEditableTester aTester( this );
85 if (!aTester.IsEditable()) // selection editable?
87 ErrorMessage( aTester.GetMessageId() );
88 return;
91 ScRange aRange; // delete this range
92 if ( GetViewData().GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
94 ScDocument* pDoc = GetViewData().GetDocument();
95 ScDocShell* pDocSh = GetViewData().GetDocShell();
96 ScMarkData& rMark = GetViewData().GetMarkData();
97 const bool bRecord(pDoc->IsUndoEnabled()); // Undo/Redo
99 ScDocShellModificator aModificator( *pDocSh );
101 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) // mark the range if not marked yet
103 DoneBlockMode();
104 InitOwnBlockMode();
105 rMark.SetMarkArea( aRange );
106 MarkDataChanged();
109 CopyToClip( pClipDoc, true, false, bIncludeObjects ); // copy to clipboard
111 ScAddress aOldEnd( aRange.aEnd ); // combined cells in this range?
112 pDoc->ExtendMerge( aRange, true );
114 ScDocument* pUndoDoc = NULL;
115 if ( bRecord )
117 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
118 pUndoDoc->InitUndoSelected( pDoc, rMark );
119 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
120 ScRange aCopyRange = aRange;
121 aCopyRange.aStart.SetTab(0);
122 aCopyRange.aEnd.SetTab(pDoc->GetTableCount()-1);
123 pDoc->CopyToDocument( aCopyRange, (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS, false, pUndoDoc );
124 pDoc->BeginDrawUndo();
127 sal_uInt16 nExtFlags = 0;
128 pDocSh->UpdatePaintExt( nExtFlags, aRange );
130 rMark.MarkToMulti();
131 pDoc->DeleteSelection( IDF_ALL, rMark );
132 if ( bIncludeObjects )
133 pDoc->DeleteObjectsInSelection( rMark );
134 rMark.MarkToSimple();
136 if ( !AdjustRowHeight( aRange.aStart.Row(), aRange.aEnd.Row() ) )
137 pDocSh->PostPaint( aRange, PAINT_GRID, nExtFlags );
139 if ( bRecord ) // Draw-Undo now available
140 pDocSh->GetUndoManager()->AddUndoAction(
141 new ScUndoCut( pDocSh, aRange, aOldEnd, rMark, pUndoDoc ) );
143 aModificator.SetDocumentModified();
144 pDocSh->UpdateOle(&GetViewData());
146 CellContentChanged();
148 else
149 ErrorMessage( STR_NOMULTISELECT );
152 // C O P Y
154 bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, bool bCut, bool bApi, bool bIncludeObjects, bool bStopEdit )
156 ScRange aRange;
157 ScMarkType eMarkType = GetViewData().GetSimpleArea( aRange );
158 ScMarkData& rMark = GetViewData().GetMarkData();
159 bool bDone = false;
161 if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
163 ScRangeList aRangeList;
164 aRangeList.Append( aRange );
165 bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, false );
167 else if (eMarkType == SC_MARK_MULTI)
169 ScRangeList aRangeList;
170 rMark.MarkToSimple();
171 rMark.FillRangeListWithMarks(&aRangeList, false);
172 bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, false );
174 else
176 if (!bApi)
177 ErrorMessage(STR_NOMULTISELECT);
180 return bDone;
183 // Copy the content of the Range into clipboard.
184 bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRangeList& rRanges, bool bCut, bool bApi, bool bIncludeObjects, bool bStopEdit, bool bUseRangeForVBA )
186 if ( rRanges.empty() )
187 return false;
188 bool bDone = false;
189 if ( bStopEdit )
190 UpdateInputLine();
192 ScRange aRange = *rRanges[0];
193 ScClipParam aClipParam( aRange, bCut );
194 aClipParam.maRanges = rRanges;
196 ScDocument* pDoc = GetViewData().GetDocument();
197 ScMarkData& rMark = GetViewData().GetMarkData();
199 if ( !aClipParam.isMultiRange() )
201 if ( pDoc && ( !pDoc->HasSelectedBlockMatrixFragment( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), rMark ) ) )
203 bool bSysClip = false;
204 if ( !pClipDoc ) // no clip doc specified
206 // Create one (deleted by ScTransferObj).
207 pClipDoc = new ScDocument( SCDOCMODE_CLIP );
208 bSysClip = true; // and copy into system
210 if ( !bCut )
212 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
213 if ( pChangeTrack )
214 pChangeTrack->ResetLastCut();
217 if ( bSysClip && bIncludeObjects )
219 bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange );
220 // Update ScGlobal::pDrawClipDocShellRef.
221 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
224 if ( !bUseRangeForVBA )
225 // is this necessary?, will setting the doc id upset the
226 // following paste operation with range? would be nicer to just set this always
227 // and lose the 'if' above
228 aClipParam.setSourceDocID( pDoc->GetDocumentID() );
230 pDoc->CopyToClip( aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
231 if ( !bUseRangeForVBA && pDoc && pClipDoc )
233 ScDrawLayer* pDrawLayer = pClipDoc->GetDrawLayer();
234 if ( pDrawLayer )
236 ScClipParam& rClipParam = pClipDoc->GetClipParam();
237 ScRangeListVector& rRangesVector = rClipParam.maProtectedChartRangesVector;
238 SCTAB nTabCount = pClipDoc->GetTableCount();
239 for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab )
241 SdrPage* pPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
242 if ( pPage )
244 ScChartHelper::FillProtectedChartRangesVector( rRangesVector, pDoc, pPage );
250 if ( bSysClip )
252 ScDrawLayer::SetGlobalDrawPersist(NULL);
253 ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) );
255 pClipDoc->ExtendMerge( aRange, true );
257 if ( bSysClip )
259 ScDocShell* pDocSh = GetViewData().GetDocShell();
260 TransferableObjectDescriptor aObjDesc;
261 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
262 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
263 // maSize is set in ScTransferObj ctor
265 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
266 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
267 if ( ScGlobal::pDrawClipDocShellRef )
269 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
270 pTransferObj->SetDrawPersist( aPersistRef );// keep persist for ole objects alive
273 pTransferObj->CopyToClipboard( GetActiveWin() );
274 SC_MOD()->SetClipObject( pTransferObj, NULL );
277 bDone = true;
280 else
282 bool bSuccess = false;
283 aClipParam.mbCutMode = false;
287 if (bCut)
288 // We con't support cutting of multi-selections.
289 break;
291 if (pClipDoc)
292 // TODO: What's this for?
293 break;
295 ::std::unique_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
297 // Check for geometrical feasibility of the ranges.
298 bool bValidRanges = true;
299 ScRange* p = aClipParam.maRanges.front();
300 SCCOL nPrevColDelta = 0;
301 SCROW nPrevRowDelta = 0;
302 SCCOL nPrevCol = p->aStart.Col();
303 SCROW nPrevRow = p->aStart.Row();
304 SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
305 SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
306 for ( size_t i = 1; i < aClipParam.maRanges.size(); ++i )
308 p = aClipParam.maRanges[i];
309 if ( pDoc->HasSelectedBlockMatrixFragment(
310 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark) )
312 if (!bApi)
313 ErrorMessage(STR_MATRIXFRAGMENTERR);
314 return false;
317 SCCOL nColDelta = p->aStart.Col() - nPrevCol;
318 SCROW nRowDelta = p->aStart.Row() - nPrevRow;
320 if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
322 bValidRanges = false;
323 break;
326 if (aClipParam.meDirection == ScClipParam::Unspecified)
328 if (nColDelta)
329 aClipParam.meDirection = ScClipParam::Column;
330 if (nRowDelta)
331 aClipParam.meDirection = ScClipParam::Row;
334 SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
335 SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
337 if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
339 // column-oriented ranges must have identical row size.
340 bValidRanges = false;
341 break;
343 if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
345 // likewise, row-oriented ranges must have identical
346 // column size.
347 bValidRanges = false;
348 break;
351 nPrevCol = p->aStart.Col();
352 nPrevRow = p->aStart.Row();
353 nPrevColDelta = nColDelta;
354 nPrevRowDelta = nRowDelta;
355 nPrevColSize = nColSize;
356 nPrevRowSize = nRowSize;
358 if (!bValidRanges)
359 break;
360 pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
362 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
363 if ( pChangeTrack )
364 pChangeTrack->ResetLastCut(); // no more cut-mode
367 ScDocShell* pDocSh = GetViewData().GetDocShell();
368 TransferableObjectDescriptor aObjDesc;
369 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
370 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
371 // maSize is set in ScTransferObj ctor
373 ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
374 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
376 if ( ScGlobal::pDrawClipDocShellRef )
378 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
379 pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
382 pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
383 SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
386 bSuccess = true;
388 while (false);
390 if (!bSuccess && !bApi)
391 ErrorMessage(STR_NOMULTISELECT);
393 bDone = bSuccess;
396 return bDone;
399 ScTransferObj* ScViewFunc::CopyToTransferable()
401 ScRange aRange;
402 if ( GetViewData().GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
404 ScDocument* pDoc = GetViewData().GetDocument();
405 ScMarkData& rMark = GetViewData().GetMarkData();
406 if ( !pDoc->HasSelectedBlockMatrixFragment(
407 aRange.aStart.Col(), aRange.aStart.Row(),
408 aRange.aEnd.Col(), aRange.aEnd.Row(),
409 rMark ) )
411 ScDocument *pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj)
413 bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
414 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
416 ScClipParam aClipParam(aRange, false);
417 pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true);
419 ScDrawLayer::SetGlobalDrawPersist(NULL);
420 pClipDoc->ExtendMerge( aRange, true );
422 ScDocShell* pDocSh = GetViewData().GetDocShell();
423 TransferableObjectDescriptor aObjDesc;
424 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
425 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
426 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
427 return pTransferObj;
431 return NULL;
434 // P A S T E
436 void ScViewFunc::PasteDraw()
438 ScViewData& rViewData = GetViewData();
439 SCCOL nPosX = rViewData.GetCurX();
440 SCROW nPosY = rViewData.GetCurY();
441 vcl::Window* pWin = GetActiveWin();
442 Point aPos = pWin->PixelToLogic( rViewData.GetScrPos( nPosX, nPosY,
443 rViewData.GetActivePart() ) );
444 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
445 if (pDrawClip)
447 OUString aSrcShellID = pDrawClip->GetShellID();
448 OUString aDestShellID = SfxObjectShell::CreateShellID(rViewData.GetDocShell());
449 PasteDraw(aPos, pDrawClip->GetModel(), false, aSrcShellID, aDestShellID);
453 void ScViewFunc::PasteFromSystem()
455 UpdateInputLine();
457 vcl::Window* pWin = GetActiveWin();
458 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
459 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
461 if (pOwnClip)
463 // keep a reference in case the clipboard is changed during PasteFromClip
464 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
465 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
466 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
467 true ); // allow warning dialog
469 else if (pDrawClip)
470 PasteDraw();
471 else
473 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
476 SotClipboardFormatId nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
477 SotClipboardFormatId nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
479 SotExchangeDest nDestination = SotExchangeDest::SCDOC_FREE_AREA;
480 sal_uInt16 nSourceOptions = EXCHG_IN_ACTION_COPY;
481 SotClipboardFormatId nFormat; // output param for GetExchangeAction
482 sal_uInt16 nEventAction; // output param for GetExchangeAction
484 uno::Reference<com::sun::star::datatransfer::XTransferable> xTransferable( aDataHelper.GetXTransferable() );
485 sal_uInt16 nAction = SotExchange::GetExchangeAction(
486 aDataHelper.GetDataFlavorExVector(),
487 nDestination,
488 nSourceOptions,
489 EXCHG_IN_ACTION_DEFAULT,
490 nFormat, nEventAction, SotClipboardFormatId::NONE,
491 &xTransferable );
493 if ( nAction != EXCHG_INOUT_ACTION_NONE )
495 nAction = ( nAction & EXCHG_ACTION_MASK );
497 switch( nAction )
499 case EXCHG_OUT_ACTION_INSERT_SVXB:
500 case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE:
501 case EXCHG_OUT_ACTION_INSERT_BITMAP:
502 case EXCHG_OUT_ACTION_INSERT_GRAPH:
503 // SotClipboardFormatId::BITMAP
504 // SotClipboardFormatId::PNG
505 // SotClipboardFormatId::GDIMETAFILE
506 // SotClipboardFormatId::SVXB
507 PasteFromSystem(nFormat);
508 break;
509 default:
510 nAction = EXCHG_INOUT_ACTION_NONE;
514 if ( nAction == EXCHG_INOUT_ACTION_NONE )
516 // first SvDraw-model, then drawing
517 // (only one drawing is allowed)
519 if (aDataHelper.HasFormat( SotClipboardFormatId::DRAWING ))
521 // special case for tables from drawing
522 if( aDataHelper.HasFormat( SotClipboardFormatId::RTF ) )
524 PasteFromSystem( SotClipboardFormatId::RTF );
526 else
528 PasteFromSystem( SotClipboardFormatId::DRAWING );
531 else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBED_SOURCE ))
533 // If it's a Writer object, insert RTF instead of OLE
535 // Else, if the class id is all-zero, and SYLK is available,
536 // it probably is spreadsheet cells that have been put
537 // on the clipboard by OOo, so use the SYLK. (fdo#31077)
539 bool bDoRtf = false;
540 TransferableObjectDescriptor aObjDesc;
541 if( aDataHelper.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc ) )
543 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
544 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
545 && aDataHelper.HasFormat( SotClipboardFormatId::RTF ) );
547 if ( bDoRtf )
548 PasteFromSystem( SotClipboardFormatId::RTF );
549 else if ( aObjDesc.maClassName == SvGlobalName( 0,0,0,0,0,0,0,0,0,0,0 )
550 && aDataHelper.HasFormat( SotClipboardFormatId::SYLK ))
551 PasteFromSystem( SotClipboardFormatId::SYLK );
552 else
553 PasteFromSystem( SotClipboardFormatId::EMBED_SOURCE );
555 else if (aDataHelper.HasFormat( SotClipboardFormatId::LINK_SOURCE ))
556 PasteFromSystem( SotClipboardFormatId::LINK_SOURCE );
557 // the following format can not affect scenario from #89579#
558 else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE ))
559 PasteFromSystem( SotClipboardFormatId::EMBEDDED_OBJ_OLE );
560 // SotClipboardFormatId::PRIVATE no longer here (can't work if pOwnClip is NULL)
561 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
562 PasteFromSystem(nBiff8);
563 else if (aDataHelper.HasFormat(nBiff5))
564 PasteFromSystem(nBiff5);
565 else if (aDataHelper.HasFormat(SotClipboardFormatId::RTF))
566 PasteFromSystem(SotClipboardFormatId::RTF);
567 else if (aDataHelper.HasFormat(SotClipboardFormatId::HTML))
568 PasteFromSystem(SotClipboardFormatId::HTML);
569 else if (aDataHelper.HasFormat(SotClipboardFormatId::HTML_SIMPLE))
570 PasteFromSystem(SotClipboardFormatId::HTML_SIMPLE);
571 else if (aDataHelper.HasFormat(SotClipboardFormatId::SYLK))
572 PasteFromSystem(SotClipboardFormatId::SYLK);
573 else if (aDataHelper.HasFormat(SotClipboardFormatId::STRING))
574 PasteFromSystem(SotClipboardFormatId::STRING);
575 // xxx_OLE formats come last, like in SotExchange tables
576 else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBED_SOURCE_OLE ))
577 PasteFromSystem( SotClipboardFormatId::EMBED_SOURCE_OLE );
578 else if (aDataHelper.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE ))
579 PasteFromSystem( SotClipboardFormatId::LINK_SOURCE_OLE );
583 // no exception-> SID_PASTE has FastCall-flag from idl
584 // will be called in case of empty clipboard (#42531#)
587 void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTransferable>& rxTransferable )
589 ScTransferObj *pOwnClip=0;
590 ScDrawTransferObj *pDrawClip=0;
591 uno::Reference<lang::XUnoTunnel> xTunnel( rxTransferable, uno::UNO_QUERY );
592 if ( xTunnel.is() )
594 sal_Int64 nHandle = xTunnel->getSomething( ScTransferObj::getUnoTunnelId() );
595 if ( nHandle )
596 pOwnClip = reinterpret_cast<ScTransferObj*>( (sal_IntPtr) nHandle);
597 else
599 nHandle = xTunnel->getSomething( ScDrawTransferObj::getUnoTunnelId() );
600 if ( nHandle )
601 pDrawClip = reinterpret_cast<ScDrawTransferObj*>( (sal_IntPtr) nHandle );
605 if (pOwnClip)
607 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
608 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
609 true ); // allow warning dialog
611 else if (pDrawClip)
613 ScViewData& rViewData = GetViewData();
614 SCCOL nPosX = rViewData.GetCurX();
615 SCROW nPosY = rViewData.GetCurY();
616 vcl::Window* pWin = GetActiveWin();
617 Point aPos = pWin->PixelToLogic( rViewData.GetScrPos( nPosX, nPosY, rViewData.GetActivePart() ) );
618 PasteDraw(
619 aPos, pDrawClip->GetModel(), false,
620 pDrawClip->GetShellID(), SfxObjectShell::CreateShellID(rViewData.GetDocShell()));
622 else
624 TransferableDataHelper aDataHelper( rxTransferable );
626 SotClipboardFormatId nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
627 SotClipboardFormatId nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
628 SotClipboardFormatId nFormatId = SotClipboardFormatId::NONE;
629 // first SvDraw-model, then drawing
630 // (only one drawing is allowed)
632 if (aDataHelper.HasFormat( SotClipboardFormatId::DRAWING ))
633 nFormatId = SotClipboardFormatId::DRAWING;
634 else if (aDataHelper.HasFormat( SotClipboardFormatId::SVXB ))
635 nFormatId = SotClipboardFormatId::SVXB;
636 else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBED_SOURCE ))
638 // If it's a Writer object, insert RTF instead of OLE
639 bool bDoRtf = false;
640 TransferableObjectDescriptor aObjDesc;
641 if( aDataHelper.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc ) )
643 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
644 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
645 && aDataHelper.HasFormat( SotClipboardFormatId::RTF ) );
647 if ( bDoRtf )
648 nFormatId = SotClipboardFormatId::RTF;
649 else
650 nFormatId = SotClipboardFormatId::EMBED_SOURCE;
652 else if (aDataHelper.HasFormat( SotClipboardFormatId::LINK_SOURCE ))
653 nFormatId = SotClipboardFormatId::LINK_SOURCE;
654 // the following format can not affect scenario from #89579#
655 else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE ))
656 nFormatId = SotClipboardFormatId::EMBEDDED_OBJ_OLE;
657 // SotClipboardFormatId::PRIVATE no longer here (can't work if pOwnClip is NULL)
658 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
659 nFormatId = nBiff8;
660 else if (aDataHelper.HasFormat(nBiff5))
661 nFormatId = nBiff5;
662 else if (aDataHelper.HasFormat(SotClipboardFormatId::RTF))
663 nFormatId = SotClipboardFormatId::RTF;
664 else if (aDataHelper.HasFormat(SotClipboardFormatId::HTML))
665 nFormatId = SotClipboardFormatId::HTML;
666 else if (aDataHelper.HasFormat(SotClipboardFormatId::HTML_SIMPLE))
667 nFormatId = SotClipboardFormatId::HTML_SIMPLE;
668 else if (aDataHelper.HasFormat(SotClipboardFormatId::SYLK))
669 nFormatId = SotClipboardFormatId::SYLK;
670 else if (aDataHelper.HasFormat(SotClipboardFormatId::STRING))
671 nFormatId = SotClipboardFormatId::STRING;
672 else if (aDataHelper.HasFormat(SotClipboardFormatId::GDIMETAFILE))
673 nFormatId = SotClipboardFormatId::GDIMETAFILE;
674 else if (aDataHelper.HasFormat(SotClipboardFormatId::BITMAP))
675 nFormatId = SotClipboardFormatId::BITMAP;
676 // xxx_OLE formats come last, like in SotExchange tables
677 else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBED_SOURCE_OLE ))
678 nFormatId = SotClipboardFormatId::EMBED_SOURCE_OLE;
679 else if (aDataHelper.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE ))
680 nFormatId = SotClipboardFormatId::LINK_SOURCE_OLE;
681 else
682 return;
684 PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
685 GetViewData().GetCurX(), GetViewData().GetCurY(),
686 NULL, false, false );
691 bool ScViewFunc::PasteFromSystem( SotClipboardFormatId nFormatId, bool bApi )
693 UpdateInputLine();
695 bool bRet = true;
696 vcl::Window* pWin = GetActiveWin();
697 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
698 if ( nFormatId == SotClipboardFormatId::NONE && pOwnClip )
700 // keep a reference in case the clipboard is changed during PasteFromClip
701 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
702 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
703 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
704 !bApi ); // allow warning dialog
706 else
708 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
709 if ( !aDataHelper.GetTransferable().is() )
710 return false;
712 SCCOL nPosX = 0;
713 SCROW nPosY = 0;
715 ScViewData& rViewData = GetViewData();
716 ScRange aRange;
717 if ( rViewData.GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
719 nPosX = aRange.aStart.Col();
720 nPosY = aRange.aStart.Row();
722 else
724 nPosX = rViewData.GetCurX();
725 nPosY = rViewData.GetCurY();
728 bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
729 nPosX, nPosY,
730 NULL, false, !bApi ); // allow warning dialog
732 if ( !bRet && !bApi )
733 ErrorMessage(STR_PASTE_ERROR);
735 return bRet;
738 // P A S T E
740 bool ScViewFunc::PasteOnDrawObjectLinked(
741 const uno::Reference<datatransfer::XTransferable>& rxTransferable,
742 SdrObject& rHitObj)
744 TransferableDataHelper aDataHelper( rxTransferable );
746 if ( aDataHelper.HasFormat( SotClipboardFormatId::SVXB ) )
748 tools::SvRef<SotStorageStream> xStm;
749 ScDrawView* pScDrawView = GetScDrawView();
751 if( pScDrawView && aDataHelper.GetSotStorageStream( SotClipboardFormatId::SVXB, xStm ) )
753 Graphic aGraphic;
755 ReadGraphic( *xStm, aGraphic );
757 const OUString aEmpty;
758 const OUString aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
760 if(pScDrawView->ApplyGraphicToObject( rHitObj, aGraphic, aBeginUndo, aEmpty, aEmpty ))
762 return true;
766 else if ( aDataHelper.HasFormat( SotClipboardFormatId::GDIMETAFILE ) )
768 GDIMetaFile aMtf;
769 ScDrawView* pScDrawView = GetScDrawView();
771 if( pScDrawView && aDataHelper.GetGDIMetaFile( SotClipboardFormatId::GDIMETAFILE, aMtf ) )
773 const OUString aEmpty;
774 const OUString aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
776 if(pScDrawView->ApplyGraphicToObject( rHitObj, Graphic(aMtf), aBeginUndo, aEmpty, aEmpty ))
778 return true;
782 else if ( aDataHelper.HasFormat( SotClipboardFormatId::BITMAP ) || aDataHelper.HasFormat( SotClipboardFormatId::PNG ) )
784 BitmapEx aBmpEx;
785 ScDrawView* pScDrawView = GetScDrawView();
787 if( pScDrawView && aDataHelper.GetBitmapEx( SotClipboardFormatId::BITMAP, aBmpEx ) )
789 const OUString aEmpty;
790 const OUString aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
792 if(pScDrawView->ApplyGraphicToObject( rHitObj, Graphic(aBmpEx), aBeginUndo, aEmpty, aEmpty ))
794 return true;
799 return false;
802 static bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
803 const ScMarkData& rTabSelection, sal_uInt16 nMask )
805 ScMarkData::const_iterator itr = rTabSelection.begin(), itrEnd = rTabSelection.end();
806 for (; itr != itrEnd; ++itr)
807 if ( pDoc->HasAttrib( nCol1, nRow1, *itr, nCol2, nRow2, *itr, nMask ) )
808 return true;
809 return false;
812 // paste into sheet:
814 // internal paste
816 namespace {
818 bool checkDestRangeForOverwrite(const ScRangeList& rDestRanges, const ScDocument* pDoc, const ScMarkData& rMark, vcl::Window* pParentWnd)
820 bool bIsEmpty = true;
821 ScMarkData::const_iterator itrTab = rMark.begin(), itrTabEnd = rMark.end();
822 size_t nRangeSize = rDestRanges.size();
823 for (; itrTab != itrTabEnd && bIsEmpty; ++itrTab)
825 for (size_t i = 0; i < nRangeSize && bIsEmpty; ++i)
827 const ScRange& rRange = *rDestRanges[i];
828 bIsEmpty = pDoc->IsBlockEmpty(
829 *itrTab, rRange.aStart.Col(), rRange.aStart.Row(),
830 rRange.aEnd.Col(), rRange.aEnd.Row());
834 if (!bIsEmpty)
836 ScopedVclPtrInstance< ScReplaceWarnBox > aBox(pParentWnd);
837 if (aBox->Execute() != RET_YES)
839 // changing the configuration is within the ScReplaceWarnBox
840 return false;
843 return true;
848 bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc,
849 sal_uInt16 nFunction, bool bSkipEmpty,
850 bool bTranspose, bool bAsLink,
851 InsCellCmd eMoveMode, InsertDeleteFlags nUndoExtraFlags,
852 bool bAllowDialogs )
854 if (!pClipDoc)
856 OSL_FAIL("PasteFromClip: pClipDoc=0 not allowed");
857 return false;
860 // undo: save all or no content
861 InsertDeleteFlags nContFlags = IDF_NONE;
862 if (nFlags & IDF_CONTENTS)
863 nContFlags |= IDF_CONTENTS;
864 if (nFlags & IDF_ATTRIB)
865 nContFlags |= IDF_ATTRIB;
866 // move attributes to undo without copying them from clip to doc
867 InsertDeleteFlags nUndoFlags = nContFlags;
868 if (nUndoExtraFlags & IDF_ATTRIB)
869 nUndoFlags |= IDF_ATTRIB;
870 // do not copy note captions into undo document
871 nUndoFlags |= IDF_NOCAPTIONS;
873 ScClipParam& rClipParam = pClipDoc->GetClipParam();
874 if (rClipParam.isMultiRange())
876 // Source data is multi-range.
877 return PasteMultiRangesFromClip(
878 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
879 eMoveMode, nUndoFlags);
882 ScMarkData& rMark = GetViewData().GetMarkData();
883 if (rMark.IsMultiMarked())
885 // Source data is single-range but destination is multi-range.
886 return PasteFromClipToMultiRanges(
887 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
888 eMoveMode, nUndoFlags);
891 bool bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
892 bool bIncludeFiltered = bCutMode;
894 // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions)
895 bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) );
897 ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip
898 ScDocument* pOrigClipDoc = NULL;
899 ::std::unique_ptr< ScDocument > xTransClip;
900 if ( bTranspose )
902 SCCOL nX;
903 SCROW nY;
904 // include filtered rows until TransposeClip can skip them
905 bIncludeFiltered = true;
906 pClipDoc->GetClipArea( nX, nY, true );
907 if ( nY > static_cast<sal_Int32>(MAXCOL) ) // to many lines for transpose
909 ErrorMessage(STR_PASTE_FULL);
910 return false;
912 pOrigClipDoc = pClipDoc; // refs
914 if ( bPasteDraw )
916 aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately
917 aTransShellRef->DoInitNew(NULL);
919 ScDrawLayer::SetGlobalDrawPersist(aTransShellRef);
921 xTransClip.reset( new ScDocument( SCDOCMODE_CLIP ));
922 pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink );
923 pClipDoc = xTransClip.get();
925 ScDrawLayer::SetGlobalDrawPersist(NULL);
928 SCCOL nStartCol;
929 SCROW nStartRow;
930 SCTAB nStartTab;
931 SCCOL nEndCol;
932 SCROW nEndRow;
933 SCTAB nEndTab;
934 SCCOL nClipSizeX;
935 SCROW nClipSizeY;
936 pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, true ); // size in clipboard doc
938 // size in target doc: include filtered rows only if CutMode is set
939 SCCOL nDestSizeX;
940 SCROW nDestSizeY;
941 pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered );
943 ScDocument* pDoc = GetViewData().GetDocument();
944 ScDocShell* pDocSh = GetViewData().GetDocShell();
945 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
946 const bool bRecord(pDoc->IsUndoEnabled());
948 ScDocShellModificator aModificator( *pDocSh );
950 ScRange aMarkRange;
951 ScMarkData aFilteredMark( rMark); // local copy for all modifications
952 ScMarkType eMarkType = GetViewData().GetSimpleArea( aMarkRange, aFilteredMark);
953 bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED);
954 bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) ||
955 (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink)));
957 if (!bNoPaste)
959 if (!rMark.IsMarked())
961 // Create a selection with clipboard row count and check that for
962 // filtered.
963 nStartCol = GetViewData().GetCurX();
964 nStartRow = GetViewData().GetCurY();
965 nStartTab = GetViewData().GetTabNo();
966 nEndCol = nStartCol + nDestSizeX;
967 nEndRow = nStartRow + nDestSizeY;
968 nEndTab = nStartTab;
969 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
970 if (ScViewUtil::HasFiltered( aMarkRange, pDoc))
972 bMarkIsFiltered = true;
973 // Fit to clipboard's row count unfiltered rows. If there is no
974 // fit assume that pasting is not possible. Note that nDestSizeY is
975 // size-1 (difference).
976 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
977 bNoPaste = true;
979 aFilteredMark.SetMarkArea( aMarkRange);
981 else
983 // Expand the marked area when the destination area is larger than the
984 // current selection, to get the undo do the right thing. (i#106711)
985 ScRange aRange;
986 aFilteredMark.GetMarkArea( aRange );
987 if( (aRange.aEnd.Col() - aRange.aStart.Col()) < nDestSizeX )
989 aRange.aEnd.SetCol(aRange.aStart.Col() + nDestSizeX);
990 aFilteredMark.SetMarkArea(aRange);
995 if (bNoPaste)
997 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
998 return false;
1001 SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1;
1002 ScRangeList aRangeList;
1003 if (bMarkIsFiltered)
1005 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1006 aFilteredMark.FillRangeListWithMarks( &aRangeList, false);
1007 nUnfilteredRows = 0;
1008 size_t ListSize = aRangeList.size();
1009 for ( size_t i = 0; i < ListSize; ++i )
1011 ScRange* p = aRangeList[i];
1012 nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1;
1014 #if 0
1015 /* This isn't needed but could be a desired restriction. */
1016 // For filtered, destination rows have to be an exact multiple of
1017 // source rows. Note that nDestSizeY is size-1 (difference), so
1018 // nDestSizeY==0 fits always.
1019 if ((nUnfilteredRows % (nDestSizeY+1)) != 0)
1021 /* FIXME: this should be a more descriptive error message then. */
1022 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1023 return false;
1025 #endif
1028 // Also for a filtered selection the area is used, for undo et al.
1029 if ( aFilteredMark.IsMarked() || bMarkIsFiltered )
1031 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1032 SCCOL nBlockAddX = nEndCol-nStartCol;
1033 SCROW nBlockAddY = nEndRow-nStartRow;
1035 // Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner
1036 // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt)
1038 // ClipSize is not size, but difference
1039 if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) ||
1040 ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) ||
1041 ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) )
1043 ScWaitCursorOff aWaitOff( GetFrameWin() );
1044 OUString aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER );
1045 ScopedVclPtrInstance<QueryBox> aBox( GetViewData().GetDialogParent(),
1046 WinBits(WB_YES_NO | WB_DEF_NO), aMessage );
1047 if ( aBox->Execute() != RET_YES )
1049 return false;
1053 if (nBlockAddX <= nDestSizeX)
1054 nEndCol = nStartCol + nDestSizeX;
1056 if (nBlockAddY <= nDestSizeY)
1058 nEndRow = nStartRow + nDestSizeY;
1059 if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row())
1061 // Same as above if nothing was marked: re-fit selection to
1062 // unfiltered rows. Extending the selection actually may
1063 // introduce filtered rows where there weren't any before, so
1064 // we also need to test for that.
1065 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1066 if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc))
1068 bMarkIsFiltered = true;
1069 // Worst case: all rows up to the end of the sheet are filtered.
1070 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
1072 ErrorMessage(STR_PASTE_FULL);
1073 return false;
1076 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1077 aFilteredMark.SetMarkArea( aMarkRange);
1078 if (bMarkIsFiltered)
1080 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1081 aFilteredMark.FillRangeListWithMarks( &aRangeList, true);
1086 else
1088 nStartCol = GetViewData().GetCurX();
1089 nStartRow = GetViewData().GetCurY();
1090 nStartTab = GetViewData().GetTabNo();
1091 nEndCol = nStartCol + nDestSizeX;
1092 nEndRow = nStartRow + nDestSizeY;
1093 nEndTab = nStartTab;
1096 bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow);
1098 // target-range, as displayed:
1099 ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1101 // should lines be inserted?
1102 // ( too large nEndCol/nEndRow are detected below)
1103 bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits );
1104 if ( bInsertCells )
1106 // Instead of EnterListAction, the paste undo action is merged into the
1107 // insert action, so Repeat can insert the right cells
1109 MarkRange( aUserRange ); // set through CopyFromClip
1111 // CutMode is reset on insertion of cols/rows but needed again on cell move
1112 bool bCut = pClipDoc->IsCutMode();
1113 if (!InsertCells( eMoveMode, bRecord, true )) // is inserting possible?
1115 return false;
1116 // #i21036# EnterListAction isn't used, and InsertCells doesn't insert
1117 // its undo action on failure, so no undo handling is needed here
1119 if ( bCut )
1120 pClipDoc->SetCutMode( bCut );
1122 else if (!bOffLimits)
1124 bool bAskIfNotEmpty = bAllowDialogs &&
1125 ( nFlags & IDF_CONTENTS ) &&
1126 nFunction == PASTE_NOFUNC &&
1127 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1128 if ( bAskIfNotEmpty )
1130 ScRangeList aTestRanges;
1131 aTestRanges.Append(aUserRange);
1132 if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aFilteredMark, GetViewData().GetDialogParent()))
1133 return false;
1137 SCCOL nClipStartX; // enlarge clipboard-range
1138 SCROW nClipStartY;
1139 pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1140 SCCOL nUndoEndCol = nClipStartX + nClipSizeX;
1141 SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document
1142 bool bClipOver = false;
1143 // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers.
1144 // The same end column/row can be used for all calls because the clip doc doesn't contain
1145 // content outside the clip area.
1146 for (SCTAB nClipTab=0; nClipTab < pClipDoc->GetTableCount(); nClipTab++)
1147 if ( pClipDoc->HasTable(nClipTab) )
1148 if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, false ) )
1149 bClipOver = true;
1150 nUndoEndCol -= nClipStartX + nClipSizeX;
1151 nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge
1152 nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol );
1153 nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells
1155 if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW)
1157 ErrorMessage(STR_PASTE_FULL);
1158 return false;
1161 pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, false );
1163 // check cell-protection
1165 ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow );
1166 if (!aTester.IsEditable())
1168 ErrorMessage(aTester.GetMessageId());
1169 return false;
1172 //! check overlapping
1173 //! just check truly intersection !!!!!!!
1175 ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
1176 if ( bRecord )
1178 OUString aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY );
1179 pUndoMgr->EnterListAction( aUndo, aUndo );
1182 if (bClipOver)
1183 if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED ))
1184 { // "Cell merge not possible if cells already merged"
1185 ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow );
1186 const ScPatternAttr* pPattern = NULL;
1187 SCCOL nCol = -1;
1188 SCROW nRow1 = -1;
1189 SCROW nRow2 = -1;
1190 while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL )
1192 const ScMergeAttr* pMergeFlag = static_cast<const ScMergeAttr*>( &pPattern->GetItem(ATTR_MERGE) );
1193 const ScMergeFlagAttr* pMergeFlagAttr = static_cast<const ScMergeFlagAttr*>( &pPattern->GetItem(ATTR_MERGE_FLAG) );
1194 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) )
1196 ScRange aRange(nCol, nRow1, nStartTab);
1197 pDoc->ExtendOverlapped(aRange);
1198 pDoc->ExtendMerge(aRange, true);
1199 rDocFunc.UnmergeCells(aRange, bRecord);
1204 if ( !bCutMode )
1206 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1207 if ( pChangeTrack )
1208 pChangeTrack->ResetLastCut(); // no more cut-mode
1211 bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1212 bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1214 ScDocument* pUndoDoc = NULL;
1215 ScDocument* pRefUndoDoc = NULL;
1216 ScRefUndoData* pUndoData = NULL;
1218 if ( bRecord )
1220 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1221 pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo );
1223 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
1224 SCTAB nTabCount = pDoc->GetTableCount();
1225 pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1,
1226 nUndoFlags, false, pUndoDoc );
1228 if ( bCutMode )
1230 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1231 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
1233 pUndoData = new ScRefUndoData( pDoc );
1237 sal_uInt16 nExtFlags = 0;
1238 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1239 nEndCol, nEndRow, nEndTab ); // content before the change
1241 if (GetViewData().IsActive())
1243 DoneBlockMode();
1244 InitOwnBlockMode();
1246 rMark.SetMarkArea( aUserRange );
1247 MarkDataChanged();
1249 // copy from clipboard
1250 // save original data in case of calculation
1252 boost::scoped_ptr<ScDocument> pMixDoc;
1253 if (nFunction)
1255 bSkipEmpty = false;
1256 if ( nFlags & IDF_CONTENTS )
1258 pMixDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1259 pMixDoc->InitUndo( pDoc, nStartTab, nEndTab );
1260 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1261 IDF_CONTENTS, false, pMixDoc.get() );
1265 /* Make draw layer and start drawing undo.
1266 - Needed before AdjustBlockHeight to track moved drawing objects.
1267 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1269 if ( bPasteDraw )
1270 pDocSh->MakeDrawLayer();
1271 if ( bRecord )
1272 pDoc->BeginDrawUndo();
1274 InsertDeleteFlags nNoObjFlags = nFlags & ~IDF_OBJECTS;
1275 if (!bAsLink)
1277 // copy normally (original range)
1278 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags,
1279 pRefUndoDoc, pClipDoc, true, false, bIncludeFiltered,
1280 bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) );
1282 // adapt refs manually in case of transpose
1283 if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) )
1284 pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc );
1286 else if (!bTranspose)
1288 // copy with bAsLink=TRUE
1289 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc,
1290 true, true, bIncludeFiltered, bSkipEmpty );
1292 else
1294 // copy all content (TransClipDoc contains only formula)
1295 pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc );
1298 // skipped rows and merged cells don't mix
1299 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
1300 rDocFunc.UnmergeCells( aUserRange, false );
1302 pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, true ); // refresh
1303 // new range
1305 if ( pMixDoc ) // calculate with originial data ?
1307 pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc.get() );
1309 pMixDoc.reset();
1311 AdjustBlockHeight(); // update row heights before pasting objects
1313 ::std::vector< OUString > aExcludedChartNames;
1314 SdrPage* pPage = NULL;
1316 if ( nFlags & IDF_OBJECTS )
1318 ScDrawView* pScDrawView = GetScDrawView();
1319 SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL );
1320 pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL );
1321 if ( pPage )
1323 ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
1326 // Paste the drawing objects after the row heights have been updated.
1328 pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc,
1329 true, false, bIncludeFiltered );
1332 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1333 nEndCol, nEndRow, nEndTab ); // content after the change
1335 // if necessary, delete autofilter-heads
1336 if (bCutMode)
1337 if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX,
1338 nClipStartY+nClipSizeY, nStartTab ))
1340 pDocSh->PostPaint(
1341 ScRange(nClipStartX, nClipStartY, nStartTab, nClipStartX+nClipSizeX, nClipStartY, nStartTab),
1342 PAINT_GRID );
1345 //! remove block-range on RefUndoDoc !!!
1347 if ( bRecord )
1349 ScDocument* pRedoDoc = NULL;
1350 // copy redo data after appearance of the first undo
1351 // don't create Redo-Doc without RefUndoDoc
1353 if (pRefUndoDoc)
1355 pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
1356 pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo );
1358 // move adapted refs to Redo-Doc
1360 SCTAB nTabCount = pDoc->GetTableCount();
1361 pRedoDoc->AddUndoTab( 0, nTabCount-1 );
1362 pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc );
1364 // move old refs to Undo-Doc
1366 // not charts?
1367 pUndoDoc->AddUndoTab( 0, nTabCount-1 );
1368 pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL );
1369 pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
1370 IDF_FORMULA, false, pUndoDoc );
1371 delete pRefUndoDoc;
1374 // DeleteUnchanged for pUndoData is in ScUndoPaste ctor,
1375 // UndoData for redo is made during first undo
1377 ScUndoPasteOptions aOptions; // store options for repeat
1378 aOptions.nFunction = nFunction;
1379 aOptions.bSkipEmpty = bSkipEmpty;
1380 aOptions.bTranspose = bTranspose;
1381 aOptions.bAsLink = bAsLink;
1382 aOptions.eMoveMode = eMoveMode;
1384 SfxUndoAction* pUndo = new ScUndoPaste(
1385 pDocSh, ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1386 aFilteredMark, pUndoDoc, pRedoDoc, nFlags | nUndoFlags, pUndoData,
1387 false, &aOptions ); // false = Redo data not yet copied
1389 if ( bInsertCells )
1391 // Merge the paste undo action into the insert action.
1392 // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action.
1394 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1396 else
1397 pUndoMgr->AddUndoAction( pUndo );
1398 pUndoMgr->LeaveListAction();
1401 sal_uInt16 nPaint = PAINT_GRID;
1402 if (bColInfo)
1404 nPaint |= PAINT_TOP;
1405 nUndoEndCol = MAXCOL; // just for drawing !
1407 if (bRowInfo)
1409 nPaint |= PAINT_LEFT;
1410 nUndoEndRow = MAXROW; // just for drawing !
1412 pDocSh->PostPaint(
1413 ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1414 nPaint, nExtFlags);
1415 // AdjustBlockHeight has already been called above
1417 ResetAutoSpell();
1418 aModificator.SetDocumentModified();
1419 PostPasteFromClip(aUserRange, rMark);
1421 if ( nFlags & IDF_OBJECTS )
1423 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1424 if ( pPage && pModelObj )
1426 bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() );
1427 const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector );
1428 ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab,
1429 rProtectedChartRangesVector, aExcludedChartNames, bSameDoc );
1433 return true;
1436 bool ScViewFunc::PasteMultiRangesFromClip(
1437 InsertDeleteFlags nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1438 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1439 InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags)
1441 ScViewData& rViewData = GetViewData();
1442 ScDocument* pDoc = rViewData.GetDocument();
1443 ScDocShell* pDocSh = rViewData.GetDocShell();
1444 ScMarkData aMark(rViewData.GetMarkData());
1445 const ScAddress& rCurPos = rViewData.GetCurPos();
1446 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1447 SCCOL nColSize = rClipParam.getPasteColSize();
1448 SCROW nRowSize = rClipParam.getPasteRowSize();
1450 if (bTranspose)
1452 if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
1454 ErrorMessage(STR_PASTE_FULL);
1455 return false;
1458 ::std::unique_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
1459 pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
1460 pClipDoc = pTransClip.release();
1461 SCCOL nTempColSize = nColSize;
1462 nColSize = static_cast<SCCOL>(nRowSize);
1463 nRowSize = static_cast<SCROW>(nTempColSize);
1466 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1468 ErrorMessage(STR_PASTE_FULL);
1469 return false;
1472 // Determine the first and last selected sheet numbers.
1473 SCTAB nTab1 = aMark.GetFirstSelected();
1474 SCTAB nTab2 = aMark.GetLastSelected();
1476 ScDocShellModificator aModificator(*pDocSh);
1478 // For multi-selection paste, we don't support cell duplication for larger
1479 // destination range. In case the destination is marked, we reset it to
1480 // the clip size.
1481 ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
1482 rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
1484 // Extend the marked range to account for filtered rows in the destination
1485 // area.
1486 if (ScViewUtil::HasFiltered(aMarkedRange, pDoc))
1488 if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize))
1489 return false;
1492 bool bAskIfNotEmpty =
1493 bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1494 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1496 if (bAskIfNotEmpty)
1498 ScRangeList aTestRanges;
1499 aTestRanges.Append(aMarkedRange);
1500 if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aMark, rViewData.GetDialogParent()))
1501 return false;
1504 aMark.SetMarkArea(aMarkedRange);
1505 MarkRange(aMarkedRange);
1507 bool bInsertCells = (eMoveMode != INS_NONE);
1508 if (bInsertCells)
1510 if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
1511 return false;
1514 ::std::unique_ptr<ScDocument> pUndoDoc;
1515 if (pDoc->IsUndoEnabled())
1517 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1518 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1519 pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1522 ::std::unique_ptr<ScDocument> pMixDoc;
1523 if ( bSkipEmpty || nFunction )
1525 if ( nFlags & IDF_CONTENTS )
1527 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1528 pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1529 pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1533 /* Make draw layer and start drawing undo.
1534 - Needed before AdjustBlockHeight to track moved drawing objects.
1535 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1537 if (nFlags & IDF_OBJECTS)
1538 pDocSh->MakeDrawLayer();
1539 if (pDoc->IsUndoEnabled())
1540 pDoc->BeginDrawUndo();
1542 InsertDeleteFlags nNoObjFlags = nFlags & ~IDF_OBJECTS;
1543 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
1544 true, bAsLink, false, bSkipEmpty);
1546 if (pMixDoc.get())
1547 pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
1549 AdjustBlockHeight(); // update row heights before pasting objects
1551 if (nFlags & IDF_OBJECTS)
1553 // Paste the drawing objects after the row heights have been updated.
1554 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
1555 true, false, false, true);
1558 ScRange aTmp = aMarkedRange;
1559 aTmp.aStart.SetTab(nTab1);
1560 aTmp.aEnd.SetTab(nTab1);
1561 pDocSh->PostPaint(aTmp, PAINT_GRID);
1563 if (pDoc->IsUndoEnabled())
1565 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1566 OUString aUndo = ScGlobal::GetRscString(
1567 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1568 pUndoMgr->EnterListAction(aUndo, aUndo);
1570 ScUndoPasteOptions aOptions; // store options for repeat
1571 aOptions.nFunction = nFunction;
1572 aOptions.bSkipEmpty = bSkipEmpty;
1573 aOptions.bTranspose = bTranspose;
1574 aOptions.bAsLink = bAsLink;
1575 aOptions.eMoveMode = eMoveMode;
1577 ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
1578 aMarkedRange, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1580 if (bInsertCells)
1581 pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
1582 else
1583 pUndoMgr->AddUndoAction(pUndo, false);
1585 pUndoMgr->LeaveListAction();
1588 ResetAutoSpell();
1589 aModificator.SetDocumentModified();
1590 PostPasteFromClip(aMarkedRange, aMark);
1591 return true;
1594 bool ScViewFunc::PasteFromClipToMultiRanges(
1595 InsertDeleteFlags nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1596 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1597 InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags )
1599 if (bTranspose)
1601 // We don't allow transpose for this yet.
1602 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1603 return false;
1606 if (eMoveMode != INS_NONE)
1608 // We don't allow insertion mode either. Too complicated.
1609 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1610 return false;
1613 ScViewData& rViewData = GetViewData();
1614 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1615 if (rClipParam.mbCutMode)
1617 // No cut and paste with this, please.
1618 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1619 return false;
1622 const ScAddress& rCurPos = rViewData.GetCurPos();
1623 ScDocument* pDoc = rViewData.GetDocument();
1625 ScRange aSrcRange = rClipParam.getWholeRange();
1626 SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
1627 SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
1629 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1631 ErrorMessage(STR_PASTE_FULL);
1632 return false;
1635 ScMarkData aMark(rViewData.GetMarkData());
1637 ScRangeList aRanges;
1638 aMark.MarkToSimple();
1639 aMark.FillRangeListWithMarks(&aRanges, false);
1640 if (!ScClipUtil::CheckDestRanges(pDoc, nColSize, nRowSize, aMark, aRanges))
1642 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1643 return false;
1646 ScDocShell* pDocSh = rViewData.GetDocShell();
1648 ScDocShellModificator aModificator(*pDocSh);
1650 bool bAskIfNotEmpty =
1651 bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1652 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1654 if (bAskIfNotEmpty)
1656 if (!checkDestRangeForOverwrite(aRanges, pDoc, aMark, rViewData.GetDialogParent()))
1657 return false;
1660 std::unique_ptr<ScDocument> pUndoDoc;
1661 if (pDoc->IsUndoEnabled())
1663 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1664 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1665 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1667 pDoc->CopyToDocument(
1668 *aRanges[i], nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1672 boost::scoped_ptr<ScDocument> pMixDoc;
1673 if (bSkipEmpty || nFunction)
1675 if (nFlags & IDF_CONTENTS)
1677 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1678 pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1679 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1681 pDoc->CopyToDocument(
1682 *aRanges[i], IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1687 if (nFlags & IDF_OBJECTS)
1688 pDocSh->MakeDrawLayer();
1689 if (pDoc->IsUndoEnabled())
1690 pDoc->BeginDrawUndo();
1692 // First, paste everything but the drawing objects.
1693 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1695 pDoc->CopyFromClip(
1696 *aRanges[i], aMark, (nFlags & ~IDF_OBJECTS), NULL, pClipDoc,
1697 false, false, true, bSkipEmpty, NULL);
1700 if (pMixDoc.get())
1702 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1703 pDoc->MixDocument(*aRanges[i], nFunction, bSkipEmpty, pMixDoc.get());
1706 AdjustBlockHeight(); // update row heights before pasting objects
1708 // Then paste the objects.
1709 if (nFlags & IDF_OBJECTS)
1711 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1713 pDoc->CopyFromClip(
1714 *aRanges[i], aMark, IDF_OBJECTS, NULL, pClipDoc,
1715 false, false, true, bSkipEmpty, NULL);
1719 // Refresh the range that includes all pasted ranges. We only need to
1720 // refresh the current sheet.
1721 pDocSh->PostPaint(aRanges, PAINT_GRID);
1723 if (pDoc->IsUndoEnabled())
1725 svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1726 OUString aUndo = ScGlobal::GetRscString(
1727 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1728 pUndoMgr->EnterListAction(aUndo, aUndo);
1730 ScUndoPasteOptions aOptions; // store options for repeat
1731 aOptions.nFunction = nFunction;
1732 aOptions.bSkipEmpty = bSkipEmpty;
1733 aOptions.bTranspose = bTranspose;
1734 aOptions.bAsLink = bAsLink;
1735 aOptions.eMoveMode = eMoveMode;
1737 ScUndoPaste* pUndo = new ScUndoPaste(
1738 pDocSh, aRanges, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1740 pUndoMgr->AddUndoAction(pUndo, false);
1741 pUndoMgr->LeaveListAction();
1744 ResetAutoSpell();
1745 aModificator.SetDocumentModified();
1746 PostPasteFromClip(aRanges, aMark);
1748 return false;
1751 void ScViewFunc::PostPasteFromClip(const ScRangeList& rPasteRanges, const ScMarkData& rMark)
1753 ScViewData& rViewData = GetViewData();
1754 ScDocShell* pDocSh = rViewData.GetDocShell();
1755 pDocSh->UpdateOle(&rViewData);
1757 SelectionChanged();
1759 ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
1760 if (!pModelObj)
1761 return;
1763 ScRangeList aChangeRanges;
1764 for (size_t i = 0, n = rPasteRanges.size(); i < n; ++i)
1766 const ScRange& r = *rPasteRanges[i];
1767 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1768 for (; itr != itrEnd; ++itr)
1770 ScRange aChangeRange(r);
1771 aChangeRange.aStart.SetTab(*itr);
1772 aChangeRange.aEnd.SetTab(*itr);
1773 aChangeRanges.Append(aChangeRange);
1776 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
1779 // D R A G A N D D R O P
1781 // inside the doc
1783 bool ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos,
1784 bool bCut, bool bRecord, bool bPaint, bool bApi )
1786 ScDocShell* pDocSh = GetViewData().GetDocShell();
1787 HideAllCursors();
1789 bool bSuccess = true;
1790 SCTAB nDestTab = rDestPos.Tab();
1791 const ScMarkData& rMark = GetViewData().GetMarkData();
1792 if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 )
1794 // moving within one table and several tables selected -> apply to all selected tables
1796 if ( bRecord )
1798 OUString aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY );
1799 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
1802 // collect ranges of consecutive selected tables
1804 ScRange aLocalSource = rSource;
1805 ScAddress aLocalDest = rDestPos;
1806 SCTAB nTabCount = pDocSh->GetDocument().GetTableCount();
1807 SCTAB nStartTab = 0;
1808 while ( nStartTab < nTabCount && bSuccess )
1810 while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) )
1811 ++nStartTab;
1812 if ( nStartTab < nTabCount )
1814 SCTAB nEndTab = nStartTab;
1815 while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) )
1816 ++nEndTab;
1818 aLocalSource.aStart.SetTab( nStartTab );
1819 aLocalSource.aEnd.SetTab( nEndTab );
1820 aLocalDest.SetTab( nStartTab );
1822 bSuccess = pDocSh->GetDocFunc().MoveBlock(
1823 aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi );
1825 nStartTab = nEndTab + 1;
1829 if ( bRecord )
1830 pDocSh->GetUndoManager()->LeaveListAction();
1832 else
1834 // move the block as specified
1835 bSuccess = pDocSh->GetDocFunc().MoveBlock(
1836 rSource, rDestPos, bCut, bRecord, bPaint, bApi );
1839 ShowAllCursors();
1840 if (bSuccess)
1842 // mark destination range
1843 ScAddress aDestEnd(
1844 rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(),
1845 rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(),
1846 nDestTab );
1848 bool bIncludeFiltered = bCut;
1849 if ( !bIncludeFiltered )
1851 // find number of non-filtered rows
1852 SCROW nPastedCount = pDocSh->GetDocument().CountNonFilteredRows(
1853 rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab());
1855 if ( nPastedCount == 0 )
1856 nPastedCount = 1;
1857 aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 );
1860 MarkRange( ScRange( rDestPos, aDestEnd ), false ); //! sal_False ???
1862 pDocSh->UpdateOle(&GetViewData());
1863 SelectionChanged();
1864 ResetAutoSpell();
1866 return bSuccess;
1869 // link inside the doc
1871 bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, bool bApi )
1873 // check overlapping
1875 if ( rSource.aStart.Tab() == rDestPos.Tab() )
1877 SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() );
1878 SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() );
1880 if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() &&
1881 rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() )
1883 if (!bApi)
1884 ErrorMessage( STR_ERR_LINKOVERLAP );
1885 return false;
1889 // run with paste
1891 ScDocument* pDoc = GetViewData().GetDocument();
1892 boost::scoped_ptr<ScDocument> pClipDoc(new ScDocument( SCDOCMODE_CLIP ));
1893 pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(),
1894 rSource.aEnd.Col(), rSource.aEnd.Row(),
1895 rSource.aStart.Tab(), pClipDoc.get() );
1897 // mark destination area (set cursor, no marks)
1899 if ( GetViewData().GetTabNo() != rDestPos.Tab() )
1900 SetTabNo( rDestPos.Tab() );
1902 MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, false, false );
1904 // Paste
1906 PasteFromClip( IDF_ALL, pClipDoc.get(), PASTE_NOFUNC, false, false, true ); // as a link
1908 return true;
1911 void ScViewFunc::DataFormPutData( SCROW nCurrentRow ,
1912 SCROW nStartRow , SCCOL nStartCol ,
1913 SCROW nEndRow , SCCOL nEndCol ,
1914 std::vector<VclPtr<Edit> >& aEdits,
1915 sal_uInt16 aColLength )
1917 ScDocument* pDoc = GetViewData().GetDocument();
1918 ScDocShell* pDocSh = GetViewData().GetDocShell();
1919 ScMarkData& rMark = GetViewData().GetMarkData();
1920 ScDocShellModificator aModificator( *pDocSh );
1921 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1922 if ( pDoc )
1924 const bool bRecord( pDoc->IsUndoEnabled());
1925 ScDocument* pUndoDoc = NULL;
1926 ScDocument* pRedoDoc = NULL;
1927 ScRefUndoData* pUndoData = NULL;
1928 SCTAB nTab = GetViewData().GetTabNo();
1929 SCTAB nStartTab = nTab;
1930 SCTAB nEndTab = nTab;
1933 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1934 if ( pChangeTrack )
1935 pChangeTrack->ResetLastCut(); // no more cut-mode
1937 ScRange aUserRange( nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab );
1938 bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1939 bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1940 SCCOL nUndoEndCol = nStartCol+aColLength-1;
1941 SCROW nUndoEndRow = nCurrentRow;
1942 InsertDeleteFlags nUndoFlags = IDF_NONE;
1944 if ( bRecord )
1946 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1947 pUndoDoc->InitUndoSelected( pDoc , rMark , bColInfo , bRowInfo );
1948 pDoc->CopyToDocument( aUserRange , IDF_VALUE , false , pUndoDoc );
1950 sal_uInt16 nExtFlags = 0;
1951 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab , nEndCol, nEndRow, nEndTab ); // content before the change
1952 pDoc->BeginDrawUndo();
1954 for(sal_uInt16 i = 0; i < aColLength; i++)
1956 if (aEdits[i] != nullptr)
1958 OUString aFieldName=aEdits[i]->GetText();
1959 pDoc->SetString( nStartCol + i, nCurrentRow, nTab, aFieldName );
1962 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab ); // content after the change
1963 SfxUndoAction* pUndo = new ScUndoDataForm( pDocSh,
1964 nStartCol, nCurrentRow, nStartTab,
1965 nUndoEndCol, nUndoEndRow, nEndTab, rMark,
1966 pUndoDoc, pRedoDoc, nUndoFlags,
1967 pUndoData, NULL, NULL, NULL,
1968 false ); // FALSE = Redo data not yet copied
1969 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1971 sal_uInt16 nPaint = PAINT_GRID;
1972 if (bColInfo)
1974 nPaint |= PAINT_TOP;
1975 nUndoEndCol = MAXCOL; // just for drawing !
1977 if (bRowInfo)
1979 nPaint |= PAINT_LEFT;
1980 nUndoEndRow = MAXROW; // just for drawing !
1983 pDocSh->PostPaint(
1984 ScRange(nStartCol, nCurrentRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1985 nPaint, nExtFlags);
1986 pDocSh->UpdateOle(&GetViewData());
1990 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */