GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / sc / source / ui / view / viewfun3.cxx
blobf96d913d73a1d49b2f0fc4a53efaf3adb87fa213
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 <vcl/graph.hxx>
33 #include <vcl/virdev.hxx>
34 #include <vcl/msgbox.hxx>
35 #include <tools/urlobj.hxx>
36 #include <sot/exchange.hxx>
37 #include <memory>
39 #include "attrib.hxx"
40 #include "patattr.hxx"
41 #include "dociter.hxx"
42 #include "viewfunc.hxx"
43 #include "tabvwsh.hxx"
44 #include "docsh.hxx"
45 #include "docfunc.hxx"
46 #include "undoblk.hxx"
47 #include "refundo.hxx"
48 #include "globstr.hrc"
49 #include "global.hxx"
50 #include "transobj.hxx"
51 #include "drwtrans.hxx"
52 #include "rangenam.hxx"
53 #include "dbdata.hxx"
54 #include "impex.hxx"
55 #include "chgtrack.hxx"
56 #include "waitoff.hxx"
57 #include "scmod.hxx"
58 #include "sc.hrc"
59 #include "inputopt.hxx"
60 #include "warnbox.hxx"
61 #include "drwlayer.hxx"
62 #include "editable.hxx"
63 #include "docuno.hxx"
64 #include "clipparam.hxx"
65 #include "undodat.hxx"
66 #include "drawview.hxx"
67 #include "cliputil.hxx"
69 using namespace com::sun::star;
71 // STATIC DATA ---------------------------------------------------------------
74 //============================================================================
76 // GlobalName der Writer-DocShell kommt jetzt aus comphelper/classids.hxx
78 //----------------------------------------------------------------------------
79 // C U T
81 void ScViewFunc::CutToClip( ScDocument* pClipDoc, sal_Bool bIncludeObjects )
83 UpdateInputLine();
85 ScEditableTester aTester( this );
86 if (!aTester.IsEditable()) // selection editable?
88 ErrorMessage( aTester.GetMessageId() );
89 return;
92 ScRange aRange; // zu loeschender Bereich
93 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
95 ScDocument* pDoc = GetViewData()->GetDocument();
96 ScDocShell* pDocSh = GetViewData()->GetDocShell();
97 ScMarkData& rMark = GetViewData()->GetMarkData();
98 const sal_Bool bRecord(pDoc->IsUndoEnabled()); // Undo/Redo
100 ScDocShellModificator aModificator( *pDocSh );
102 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) // mark the range if not marked yet
104 DoneBlockMode();
105 InitOwnBlockMode();
106 rMark.SetMarkArea( aRange );
107 MarkDataChanged();
110 CopyToClip( pClipDoc, sal_True, false, bIncludeObjects ); // Ab ins Clipboard
112 ScAddress aOldEnd( aRange.aEnd ); // Zusammengefasste Zellen im Bereich?
113 pDoc->ExtendMerge( aRange, sal_True );
115 ScDocument* pUndoDoc = NULL;
116 if ( bRecord )
118 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
119 pUndoDoc->InitUndoSelected( pDoc, rMark );
120 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
121 ScRange aCopyRange = aRange;
122 aCopyRange.aStart.SetTab(0);
123 aCopyRange.aEnd.SetTab(pDoc->GetTableCount()-1);
124 pDoc->CopyToDocument( aCopyRange, (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS, false, pUndoDoc );
125 pDoc->BeginDrawUndo();
128 sal_uInt16 nExtFlags = 0;
129 pDocSh->UpdatePaintExt( nExtFlags, aRange );
131 rMark.MarkToMulti();
132 pDoc->DeleteSelection( IDF_ALL, rMark );
133 if ( bIncludeObjects )
134 pDoc->DeleteObjectsInSelection( rMark );
135 rMark.MarkToSimple();
137 if ( !AdjustRowHeight( aRange.aStart.Row(), aRange.aEnd.Row() ) )
138 pDocSh->PostPaint( aRange, PAINT_GRID, nExtFlags );
140 if ( bRecord ) // erst jetzt ist Draw-Undo verfuegbar
141 pDocSh->GetUndoManager()->AddUndoAction(
142 new ScUndoCut( pDocSh, aRange, aOldEnd, rMark, pUndoDoc ) );
144 aModificator.SetDocumentModified();
145 pDocSh->UpdateOle(GetViewData());
147 CellContentChanged();
149 else
150 ErrorMessage( STR_NOMULTISELECT );
154 //----------------------------------------------------------------------------
155 // C O P Y
157 sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, sal_Bool bCut, sal_Bool bApi, sal_Bool bIncludeObjects, sal_Bool bStopEdit )
159 ScRange aRange;
160 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange );
161 ScMarkData& rMark = GetViewData()->GetMarkData();
162 sal_Bool bDone = sal_False;
164 if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
166 ScRangeList aRangeList;
167 aRangeList.Append( aRange );
168 bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, sal_False );
170 else if (eMarkType == SC_MARK_MULTI)
172 ScRangeList aRangeList;
173 rMark.MarkToSimple();
174 rMark.FillRangeListWithMarks(&aRangeList, false);
175 bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, sal_False );
177 else
179 if (!bApi)
180 ErrorMessage(STR_NOMULTISELECT);
183 return bDone;
186 // Copy the content of the Range into clipboard.
187 sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRangeList& rRanges, sal_Bool bCut, sal_Bool bApi, sal_Bool bIncludeObjects, sal_Bool bStopEdit, sal_Bool bUseRangeForVBA )
189 if ( rRanges.empty() )
190 return false;
191 sal_Bool bDone = false;
192 if ( bStopEdit )
193 UpdateInputLine();
195 ScRange aRange = *rRanges[0];
196 ScClipParam aClipParam( aRange, bCut );
197 aClipParam.maRanges = rRanges;
199 ScDocument* pDoc = GetViewData()->GetDocument();
200 ScMarkData& rMark = GetViewData()->GetMarkData();
202 if ( !aClipParam.isMultiRange() )
204 if ( pDoc && ( !pDoc->HasSelectedBlockMatrixFragment( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), rMark ) ) )
206 sal_Bool bSysClip = false;
207 if ( !pClipDoc ) // no clip doc specified
209 // Create one (deleted by ScTransferObj).
210 pClipDoc = new ScDocument( SCDOCMODE_CLIP );
211 bSysClip = sal_True; // and copy into system
213 if ( !bCut )
215 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
216 if ( pChangeTrack )
217 pChangeTrack->ResetLastCut();
220 if ( bSysClip && bIncludeObjects )
222 sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange );
223 // Update ScGlobal::pDrawClipDocShellRef.
224 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
227 if ( !bUseRangeForVBA )
228 // is this necessary?, will setting the doc id upset the
229 // following paste operation with range? would be nicer to just set this always
230 // and lose the 'if' above
231 aClipParam.setSourceDocID( pDoc->GetDocumentID() );
233 pDoc->CopyToClip( aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
234 if ( !bUseRangeForVBA && pDoc && pClipDoc )
236 ScDrawLayer* pDrawLayer = pClipDoc->GetDrawLayer();
237 if ( pDrawLayer )
239 ScClipParam& rClipParam = pClipDoc->GetClipParam();
240 ScRangeListVector& rRangesVector = rClipParam.maProtectedChartRangesVector;
241 SCTAB nTabCount = pClipDoc->GetTableCount();
242 for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab )
244 SdrPage* pPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
245 if ( pPage )
247 ScChartHelper::FillProtectedChartRangesVector( rRangesVector, pDoc, pPage );
253 if ( bSysClip )
255 ScDrawLayer::SetGlobalDrawPersist(NULL);
256 ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) );
258 pClipDoc->ExtendMerge( aRange, true );
260 if ( bSysClip )
262 ScDocShell* pDocSh = GetViewData()->GetDocShell();
263 TransferableObjectDescriptor aObjDesc;
264 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
265 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
266 // maSize is set in ScTransferObj ctor
268 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
269 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
270 if ( ScGlobal::pDrawClipDocShellRef )
272 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
273 pTransferObj->SetDrawPersist( aPersistRef );// keep persist for ole objects alive
276 pTransferObj->CopyToClipboard( GetActiveWin() );
277 SC_MOD()->SetClipObject( pTransferObj, NULL );
280 bDone = true;
283 else
285 bool bSuccess = false;
286 aClipParam.mbCutMode = false;
290 if (bCut)
291 // We con't support cutting of multi-selections.
292 break;
294 if (pClipDoc)
295 // TODO: What's this for?
296 break;
298 SAL_WNODEPRECATED_DECLARATIONS_PUSH
299 ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
300 SAL_WNODEPRECATED_DECLARATIONS_POP
302 // Check for geometrical feasibility of the ranges.
303 bool bValidRanges = true;
304 ScRange* p = aClipParam.maRanges.front();
305 SCCOL nPrevColDelta = 0;
306 SCROW nPrevRowDelta = 0;
307 SCCOL nPrevCol = p->aStart.Col();
308 SCROW nPrevRow = p->aStart.Row();
309 SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
310 SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
311 for ( size_t i = 1; i < aClipParam.maRanges.size(); ++i )
313 p = aClipParam.maRanges[i];
314 if ( pDoc->HasSelectedBlockMatrixFragment(
315 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark) )
317 if (!bApi)
318 ErrorMessage(STR_MATRIXFRAGMENTERR);
319 return false;
322 SCCOL nColDelta = p->aStart.Col() - nPrevCol;
323 SCROW nRowDelta = p->aStart.Row() - nPrevRow;
325 if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
327 bValidRanges = false;
328 break;
331 if (aClipParam.meDirection == ScClipParam::Unspecified)
333 if (nColDelta)
334 aClipParam.meDirection = ScClipParam::Column;
335 if (nRowDelta)
336 aClipParam.meDirection = ScClipParam::Row;
339 SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
340 SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
342 if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
344 // column-oriented ranges must have identical row size.
345 bValidRanges = false;
346 break;
348 if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
350 // likewise, row-oriented ranges must have identical
351 // column size.
352 bValidRanges = false;
353 break;
356 nPrevCol = p->aStart.Col();
357 nPrevRow = p->aStart.Row();
358 nPrevColDelta = nColDelta;
359 nPrevRowDelta = nRowDelta;
360 nPrevColSize = nColSize;
361 nPrevRowSize = nRowSize;
363 if (!bValidRanges)
364 break;
365 pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
367 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
368 if ( pChangeTrack )
369 pChangeTrack->ResetLastCut(); // kein CutMode mehr
372 ScDocShell* pDocSh = GetViewData()->GetDocShell();
373 TransferableObjectDescriptor aObjDesc;
374 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
375 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
376 // maSize is set in ScTransferObj ctor
378 ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
379 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
381 if ( ScGlobal::pDrawClipDocShellRef )
383 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
384 pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
387 pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
388 SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
391 bSuccess = true;
393 while (false);
395 if (!bSuccess && !bApi)
396 ErrorMessage(STR_NOMULTISELECT);
398 bDone = bSuccess;
401 return bDone;
404 ScTransferObj* ScViewFunc::CopyToTransferable()
406 ScRange aRange;
407 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
409 ScDocument* pDoc = GetViewData()->GetDocument();
410 ScMarkData& rMark = GetViewData()->GetMarkData();
411 if ( !pDoc->HasSelectedBlockMatrixFragment(
412 aRange.aStart.Col(), aRange.aStart.Row(),
413 aRange.aEnd.Col(), aRange.aEnd.Row(),
414 rMark ) )
416 ScDocument *pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj)
418 sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
419 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
421 ScClipParam aClipParam(aRange, false);
422 pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true);
424 ScDrawLayer::SetGlobalDrawPersist(NULL);
425 pClipDoc->ExtendMerge( aRange, sal_True );
427 ScDocShell* pDocSh = GetViewData()->GetDocShell();
428 TransferableObjectDescriptor aObjDesc;
429 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
430 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
431 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
432 return pTransferObj;
436 return NULL;
439 //----------------------------------------------------------------------------
440 // P A S T E
442 void ScViewFunc::PasteDraw()
444 ScViewData* pViewData = GetViewData();
445 SCCOL nPosX = pViewData->GetCurX();
446 SCROW nPosY = pViewData->GetCurY();
447 Window* pWin = GetActiveWin();
448 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY,
449 pViewData->GetActivePart() ) );
450 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
451 if (pDrawClip)
452 PasteDraw( aPos, pDrawClip->GetModel(), false,
453 pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
456 void ScViewFunc::PasteFromSystem()
458 UpdateInputLine();
460 Window* pWin = GetActiveWin();
461 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
462 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
464 if (pOwnClip)
466 // keep a reference in case the clipboard is changed during PasteFromClip
467 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
468 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
469 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
470 sal_True ); // allow warning dialog
472 else if (pDrawClip)
473 PasteDraw();
474 else
476 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
479 sal_uLong nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
480 sal_uLong nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
482 // als erstes SvDraw-Model, dann Grafik
483 // (Grafik darf nur bei einzelner Grafik drinstehen)
485 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
487 // special case for tables from drawing
488 if( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
490 PasteFromSystem( FORMAT_RTF );
492 else
494 PasteFromSystem( SOT_FORMATSTR_ID_DRAWING );
497 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
498 PasteFromSystem( SOT_FORMATSTR_ID_SVXB );
499 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
501 // If it's a Writer object, insert RTF instead of OLE
503 // Else, if the class id is all-zero, and SYLK is available,
504 // it probably is spreadsheet cells that have been put
505 // on the clipboard by OOo, so use the SYLK. (fdo#31077)
507 sal_Bool bDoRtf = false;
508 TransferableObjectDescriptor aObjDesc;
509 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
511 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
512 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
513 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
515 if ( bDoRtf )
516 PasteFromSystem( FORMAT_RTF );
517 else if ( aObjDesc.maClassName == SvGlobalName( 0,0,0,0,0,0,0,0,0,0,0 )
518 && aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ))
519 PasteFromSystem( SOT_FORMATSTR_ID_SYLK );
520 else
521 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE );
523 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
524 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE );
525 // the following format can not affect scenario from #89579#
526 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
527 PasteFromSystem( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE );
528 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
529 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
530 PasteFromSystem(nBiff8);
531 else if (aDataHelper.HasFormat(nBiff5))
532 PasteFromSystem(nBiff5);
533 else if (aDataHelper.HasFormat(FORMAT_RTF))
534 PasteFromSystem(FORMAT_RTF);
535 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
536 PasteFromSystem(SOT_FORMATSTR_ID_HTML);
537 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
538 PasteFromSystem(SOT_FORMATSTR_ID_HTML_SIMPLE);
539 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
540 PasteFromSystem(SOT_FORMATSTR_ID_SYLK);
541 else if (aDataHelper.HasFormat(FORMAT_STRING))
542 PasteFromSystem(FORMAT_STRING);
543 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
544 PasteFromSystem(FORMAT_GDIMETAFILE);
545 else if (aDataHelper.HasFormat(FORMAT_BITMAP))
546 PasteFromSystem(FORMAT_BITMAP);
547 // xxx_OLE formats come last, like in SotExchange tables
548 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
549 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE );
550 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
551 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE_OLE );
554 // keine Fehlermeldung, weil SID_PASTE in der idl das FastCall-Flag hat,
555 // also auch gerufen wird, wenn nichts im Clipboard steht (#42531#)
558 void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTransferable>& rxTransferable )
560 ScTransferObj *pOwnClip=0;
561 ScDrawTransferObj *pDrawClip=0;
562 uno::Reference<lang::XUnoTunnel> xTunnel( rxTransferable, uno::UNO_QUERY );
563 if ( xTunnel.is() )
565 sal_Int64 nHandle = xTunnel->getSomething( ScTransferObj::getUnoTunnelId() );
566 if ( nHandle )
567 pOwnClip = (ScTransferObj*) (sal_IntPtr) nHandle;
568 else
570 nHandle = xTunnel->getSomething( ScDrawTransferObj::getUnoTunnelId() );
571 if ( nHandle )
572 pDrawClip = (ScDrawTransferObj*) (sal_IntPtr) nHandle;
576 if (pOwnClip)
578 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
579 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
580 sal_True ); // allow warning dialog
582 else if (pDrawClip)
584 ScViewData* pViewData = GetViewData();
585 SCCOL nPosX = pViewData->GetCurX();
586 SCROW nPosY = pViewData->GetCurY();
587 Window* pWin = GetActiveWin();
588 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY, pViewData->GetActivePart() ) );
589 PasteDraw( aPos, pDrawClip->GetModel(), false, pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
591 else
593 TransferableDataHelper aDataHelper( rxTransferable );
595 sal_uLong nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
596 sal_uLong nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
597 sal_uLong nFormatId = 0;
598 // als erstes SvDraw-Model, dann Grafik
599 // (Grafik darf nur bei einzelner Grafik drinstehen)
601 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
602 nFormatId = SOT_FORMATSTR_ID_DRAWING;
603 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
604 nFormatId = SOT_FORMATSTR_ID_SVXB;
605 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
607 // If it's a Writer object, insert RTF instead of OLE
608 sal_Bool bDoRtf = false;
609 TransferableObjectDescriptor aObjDesc;
610 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
612 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
613 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
614 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
616 if ( bDoRtf )
617 nFormatId = FORMAT_RTF;
618 else
619 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
621 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
622 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
623 // the following format can not affect scenario from #89579#
624 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
625 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
626 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
627 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
628 nFormatId = nBiff8;
629 else if (aDataHelper.HasFormat(nBiff5))
630 nFormatId = nBiff5;
631 else if (aDataHelper.HasFormat(FORMAT_RTF))
632 nFormatId = FORMAT_RTF;
633 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
634 nFormatId = SOT_FORMATSTR_ID_HTML;
635 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
636 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
637 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
638 nFormatId = SOT_FORMATSTR_ID_SYLK;
639 else if (aDataHelper.HasFormat(FORMAT_STRING))
640 nFormatId = FORMAT_STRING;
641 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
642 nFormatId = FORMAT_GDIMETAFILE;
643 else if (aDataHelper.HasFormat(FORMAT_BITMAP))
644 nFormatId = FORMAT_BITMAP;
645 // xxx_OLE formats come last, like in SotExchange tables
646 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
647 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
648 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
649 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
650 else
651 return;
653 PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
654 GetViewData()->GetCurX(), GetViewData()->GetCurY(),
655 NULL, false, false );
660 sal_Bool ScViewFunc::PasteFromSystem( sal_uLong nFormatId, sal_Bool bApi )
662 UpdateInputLine();
664 sal_Bool bRet = sal_True;
665 Window* pWin = GetActiveWin();
666 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
667 if ( nFormatId == 0 && pOwnClip )
669 // keep a reference in case the clipboard is changed during PasteFromClip
670 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
671 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
672 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
673 !bApi ); // allow warning dialog
675 else
677 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
678 if ( !aDataHelper.GetTransferable().is() )
679 return false;
681 bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
682 GetViewData()->GetCurX(), GetViewData()->GetCurY(),
683 NULL, false, !bApi ); // allow warning dialog
685 if ( !bRet && !bApi )
686 ErrorMessage(STR_PASTE_ERROR);
688 return bRet;
692 //----------------------------------------------------------------------------
693 // P A S T E
695 sal_Bool ScViewFunc::PasteOnDrawObject( const uno::Reference<datatransfer::XTransferable>& rxTransferable,
696 SdrObject* pHitObj, sal_Bool bLink )
698 sal_Bool bRet = false;
699 if ( bLink )
701 TransferableDataHelper aDataHelper( rxTransferable );
702 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
704 SotStorageStreamRef xStm;
705 if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) )
707 Graphic aGraphic;
708 *xStm >> aGraphic;
709 bRet = ApplyGraphicToObject( pHitObj, aGraphic );
712 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
714 GDIMetaFile aMtf;
715 if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) )
716 bRet = ApplyGraphicToObject( pHitObj, Graphic(aMtf) );
718 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
720 BitmapEx aBmpEx;
721 if( aDataHelper.GetBitmapEx( FORMAT_BITMAP, aBmpEx ) )
722 bRet = ApplyGraphicToObject( pHitObj, Graphic(aBmpEx) );
725 else
727 // ham' wa noch nich
729 return bRet;
732 static sal_Bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
733 const ScMarkData& rTabSelection, sal_uInt16 nMask )
735 ScMarkData::const_iterator itr = rTabSelection.begin(), itrEnd = rTabSelection.end();
736 for (; itr != itrEnd; ++itr)
737 if ( pDoc->HasAttrib( nCol1, nRow1, *itr, nCol2, nRow2, *itr, nMask ) )
738 return sal_True;
739 return false;
743 // Einfuegen auf Tabelle:
746 // internes Paste
748 namespace {
750 bool checkDestRangeForOverwrite(const ScRangeList& rDestRanges, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
752 bool bIsEmpty = true;
753 ScMarkData::const_iterator itrTab = rMark.begin(), itrTabEnd = rMark.end();
754 size_t nRangeSize = rDestRanges.size();
755 for (; itrTab != itrTabEnd && bIsEmpty; ++itrTab)
757 for (size_t i = 0; i < nRangeSize && bIsEmpty; ++i)
759 const ScRange& rRange = *rDestRanges[i];
760 bIsEmpty = pDoc->IsBlockEmpty(
761 *itrTab, rRange.aStart.Col(), rRange.aStart.Row(),
762 rRange.aEnd.Col(), rRange.aEnd.Row());
766 if (!bIsEmpty)
768 ScReplaceWarnBox aBox(pParentWnd);
769 if (aBox.Execute() != RET_YES)
771 // changing the configuration is within the ScReplaceWarnBox
772 return false;
775 return true;
780 bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
781 sal_uInt16 nFunction, bool bSkipEmpty,
782 bool bTranspose, bool bAsLink,
783 InsCellCmd eMoveMode, sal_uInt16 nUndoExtraFlags,
784 bool bAllowDialogs )
786 if (!pClipDoc)
788 OSL_FAIL("PasteFromClip: pClipDoc=0 not allowed");
789 return false;
792 // fuer Undo etc. immer alle oder keine Inhalte sichern
793 sal_uInt16 nContFlags = IDF_NONE;
794 if (nFlags & IDF_CONTENTS)
795 nContFlags |= IDF_CONTENTS;
796 if (nFlags & IDF_ATTRIB)
797 nContFlags |= IDF_ATTRIB;
798 // evtl. Attribute ins Undo ohne sie vom Clip ins Doc zu kopieren
799 sal_uInt16 nUndoFlags = nContFlags;
800 if (nUndoExtraFlags & IDF_ATTRIB)
801 nUndoFlags |= IDF_ATTRIB;
802 // do not copy note captions into undo document
803 nUndoFlags |= IDF_NOCAPTIONS;
805 ScClipParam& rClipParam = pClipDoc->GetClipParam();
806 if (rClipParam.isMultiRange())
808 // Source data is multi-range.
809 return PasteMultiRangesFromClip(
810 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
811 eMoveMode, nUndoFlags);
814 ScMarkData& rMark = GetViewData()->GetMarkData();
815 if (rMark.IsMultiMarked())
817 // Source data is single-range but destination is multi-range.
818 return PasteFromClipToMultiRanges(
819 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
820 eMoveMode, nUndoFlags);
823 bool bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
824 bool bIncludeFiltered = bCutMode;
826 // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions)
827 bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) );
829 ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip
830 ScDocument* pOrigClipDoc = NULL;
831 SAL_WNODEPRECATED_DECLARATIONS_PUSH
832 ::std::auto_ptr< ScDocument > xTransClip;
833 SAL_WNODEPRECATED_DECLARATIONS_POP
834 if ( bTranspose )
836 SCCOL nX;
837 SCROW nY;
838 // include filtered rows until TransposeClip can skip them
839 bIncludeFiltered = true;
840 pClipDoc->GetClipArea( nX, nY, true );
841 if ( nY > static_cast<sal_Int32>(MAXCOL) ) // zuviele Zeilen zum Transponieren
843 ErrorMessage(STR_PASTE_FULL);
844 return false;
846 pOrigClipDoc = pClipDoc; // fuer Referenzen
848 if ( bPasteDraw )
850 aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately
851 aTransShellRef->DoInitNew(NULL);
853 ScDrawLayer::SetGlobalDrawPersist(aTransShellRef);
855 xTransClip.reset( new ScDocument( SCDOCMODE_CLIP ));
856 pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink );
857 pClipDoc = xTransClip.get();
859 ScDrawLayer::SetGlobalDrawPersist(NULL);
862 SCCOL nStartCol;
863 SCROW nStartRow;
864 SCTAB nStartTab;
865 SCCOL nEndCol;
866 SCROW nEndRow;
867 SCTAB nEndTab;
868 SCCOL nClipSizeX;
869 SCROW nClipSizeY;
870 pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, true ); // size in clipboard doc
872 // size in target doc: include filtered rows only if CutMode is set
873 SCCOL nDestSizeX;
874 SCROW nDestSizeY;
875 pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered );
877 ScDocument* pDoc = GetViewData()->GetDocument();
878 ScDocShell* pDocSh = GetViewData()->GetDocShell();
879 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
880 const bool bRecord(pDoc->IsUndoEnabled());
882 ScDocShellModificator aModificator( *pDocSh );
884 ScRange aMarkRange;
885 ScMarkData aFilteredMark( rMark); // local copy for all modifications
886 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange, aFilteredMark);
887 bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED);
888 bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) ||
889 (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink)));
891 if (!bNoPaste)
893 if (!rMark.IsMarked())
895 // Create a selection with clipboard row count and check that for
896 // filtered.
897 nStartCol = GetViewData()->GetCurX();
898 nStartRow = GetViewData()->GetCurY();
899 nStartTab = GetViewData()->GetTabNo();
900 nEndCol = nStartCol + nDestSizeX;
901 nEndRow = nStartRow + nDestSizeY;
902 nEndTab = nStartTab;
903 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
904 if (ScViewUtil::HasFiltered( aMarkRange, pDoc))
906 bMarkIsFiltered = true;
907 // Fit to clipboard's row count unfiltered rows. If there is no
908 // fit assume that pasting is not possible. Note that nDestSizeY is
909 // size-1 (difference).
910 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
911 bNoPaste = true;
913 aFilteredMark.SetMarkArea( aMarkRange);
915 else
917 // Expand the marked area when the destination area is larger than the
918 // current selection, to get the undo do the right thing. (i#106711)
919 ScRange aRange;
920 aFilteredMark.GetMarkArea( aRange );
921 if( (aRange.aEnd.Col() - aRange.aStart.Col()) < nDestSizeX )
923 aRange.aEnd.SetCol(aRange.aStart.Col() + nDestSizeX);
924 aFilteredMark.SetMarkArea(aRange);
929 if (bNoPaste)
931 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
932 return false;
935 SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1;
936 ScRangeList aRangeList;
937 if (bMarkIsFiltered)
939 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
940 aFilteredMark.FillRangeListWithMarks( &aRangeList, false);
941 nUnfilteredRows = 0;
942 size_t ListSize = aRangeList.size();
943 for ( size_t i = 0; i < ListSize; ++i )
945 ScRange* p = aRangeList[i];
946 nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1;
948 #if 0
949 /* This isn't needed but could be a desired restriction. */
950 // For filtered, destination rows have to be an exact multiple of
951 // source rows. Note that nDestSizeY is size-1 (difference), so
952 // nDestSizeY==0 fits always.
953 if ((nUnfilteredRows % (nDestSizeY+1)) != 0)
955 /* FIXME: this should be a more descriptive error message then. */
956 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
957 return false;
959 #endif
962 // Also for a filtered selection the area is used, for undo et al.
963 if ( aFilteredMark.IsMarked() || bMarkIsFiltered )
965 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
966 SCCOL nBlockAddX = nEndCol-nStartCol;
967 SCROW nBlockAddY = nEndRow-nStartRow;
969 // Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner
970 // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt)
972 // ClipSize is not size, but difference
973 if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) ||
974 ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) ||
975 ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) )
977 ScWaitCursorOff aWaitOff( GetFrameWin() );
978 OUString aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER );
979 QueryBox aBox( GetViewData()->GetDialogParent(),
980 WinBits(WB_YES_NO | WB_DEF_NO), aMessage );
981 if ( aBox.Execute() != RET_YES )
983 return false;
987 if (nBlockAddX <= nDestSizeX)
988 nEndCol = nStartCol + nDestSizeX;
990 if (nBlockAddY <= nDestSizeY)
992 nEndRow = nStartRow + nDestSizeY;
993 if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row())
995 // Same as above if nothing was marked: re-fit selection to
996 // unfiltered rows. Extending the selection actually may
997 // introduce filtered rows where there weren't any before, so
998 // we also need to test for that.
999 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1000 if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc))
1002 bMarkIsFiltered = true;
1003 // Worst case: all rows up to the end of the sheet are filtered.
1004 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
1006 ErrorMessage(STR_PASTE_FULL);
1007 return false;
1010 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1011 aFilteredMark.SetMarkArea( aMarkRange);
1012 if (bMarkIsFiltered)
1014 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1015 aFilteredMark.FillRangeListWithMarks( &aRangeList, true);
1020 else
1022 nStartCol = GetViewData()->GetCurX();
1023 nStartRow = GetViewData()->GetCurY();
1024 nStartTab = GetViewData()->GetTabNo();
1025 nEndCol = nStartCol + nDestSizeX;
1026 nEndRow = nStartRow + nDestSizeY;
1027 nEndTab = nStartTab;
1030 bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow);
1032 // Zielbereich, wie er angezeigt wird:
1033 ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1035 // Sollen Zellen eingefuegt werden?
1036 // (zu grosse nEndCol/nEndRow werden weiter unten erkannt)
1037 bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits );
1038 if ( bInsertCells )
1040 // Instead of EnterListAction, the paste undo action is merged into the
1041 // insert action, so Repeat can insert the right cells
1043 MarkRange( aUserRange ); // wird vor CopyFromClip sowieso gesetzt
1045 // CutMode is reset on insertion of cols/rows but needed again on cell move
1046 bool bCut = pClipDoc->IsCutMode();
1047 if (!InsertCells( eMoveMode, bRecord, true )) // is inserting possible?
1049 return false;
1050 // #i21036# EnterListAction isn't used, and InsertCells doesn't insert
1051 // its undo action on failure, so no undo handling is needed here
1053 if ( bCut )
1054 pClipDoc->SetCutMode( bCut );
1056 else if (!bOffLimits)
1058 bool bAskIfNotEmpty = bAllowDialogs &&
1059 ( nFlags & IDF_CONTENTS ) &&
1060 nFunction == PASTE_NOFUNC &&
1061 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1062 if ( bAskIfNotEmpty )
1064 ScRangeList aTestRanges;
1065 aTestRanges.Append(aUserRange);
1066 if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
1067 return false;
1071 SCCOL nClipStartX; // Clipboard-Bereich erweitern
1072 SCROW nClipStartY;
1073 pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1074 SCCOL nUndoEndCol = nClipStartX + nClipSizeX;
1075 SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document
1076 bool bClipOver = false;
1077 // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers.
1078 // The same end column/row can be used for all calls because the clip doc doesn't contain
1079 // content outside the clip area.
1080 for (SCTAB nClipTab=0; nClipTab < pClipDoc->GetTableCount(); nClipTab++)
1081 if ( pClipDoc->HasTable(nClipTab) )
1082 if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, false ) )
1083 bClipOver = true;
1084 nUndoEndCol -= nClipStartX + nClipSizeX;
1085 nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge
1086 nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol );
1087 nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells
1089 if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW)
1091 ErrorMessage(STR_PASTE_FULL);
1092 return false;
1095 pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, false );
1097 // Test auf Zellschutz
1099 ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow );
1100 if (!aTester.IsEditable())
1102 ErrorMessage(aTester.GetMessageId());
1103 return false;
1106 //! Test auf Ueberlappung
1107 //! nur wirkliche Schnittmenge testen !!!!!!!
1109 ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
1110 if ( bRecord )
1112 OUString aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY );
1113 pUndoMgr->EnterListAction( aUndo, aUndo );
1116 if (bClipOver)
1117 if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED ))
1118 { // "Cell merge not possible if cells already merged"
1119 ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow );
1120 const ScPatternAttr* pPattern = NULL;
1121 const ScMergeAttr* pMergeFlag = NULL;
1122 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1123 SCCOL nCol = -1;
1124 SCROW nRow1 = -1;
1125 SCROW nRow2 = -1;
1126 while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL )
1128 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1129 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1130 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) )
1132 ScRange aRange(nCol, nRow1, nStartTab);
1133 pDoc->ExtendOverlapped(aRange);
1134 pDoc->ExtendMerge(aRange, true);
1135 rDocFunc.UnmergeCells(aRange, bRecord);
1140 if ( !bCutMode )
1142 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1143 if ( pChangeTrack )
1144 pChangeTrack->ResetLastCut(); // kein CutMode mehr
1147 bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1148 bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1150 ScDocument* pUndoDoc = NULL;
1151 ScDocument* pRefUndoDoc = NULL;
1152 ScRefUndoData* pUndoData = NULL;
1154 if ( bRecord )
1156 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1157 pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo );
1159 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
1160 SCTAB nTabCount = pDoc->GetTableCount();
1161 pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1,
1162 nUndoFlags, false, pUndoDoc );
1164 if ( bCutMode )
1166 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1167 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
1169 pUndoData = new ScRefUndoData( pDoc );
1173 sal_uInt16 nExtFlags = 0;
1174 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1175 nEndCol, nEndRow, nEndTab ); // content before the change
1177 if (GetViewData()->IsActive())
1179 DoneBlockMode();
1180 InitOwnBlockMode();
1182 rMark.SetMarkArea( aUserRange );
1183 MarkDataChanged();
1186 // Aus Clipboard kopieren,
1187 // wenn gerechnet werden soll, Originaldaten merken
1190 ScDocument* pMixDoc = NULL;
1191 if ( bSkipEmpty || nFunction )
1193 if ( nFlags & IDF_CONTENTS )
1195 pMixDoc = new ScDocument( SCDOCMODE_UNDO );
1196 pMixDoc->InitUndo( pDoc, nStartTab, nEndTab );
1197 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1198 IDF_CONTENTS, false, pMixDoc );
1202 /* Make draw layer and start drawing undo.
1203 - Needed before AdjustBlockHeight to track moved drawing objects.
1204 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1206 if ( bPasteDraw )
1207 pDocSh->MakeDrawLayer();
1208 if ( bRecord )
1209 pDoc->BeginDrawUndo();
1211 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1212 if (!bAsLink)
1214 // copy normally (original range)
1215 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags,
1216 pRefUndoDoc, pClipDoc, true, false, bIncludeFiltered,
1217 bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) );
1219 // bei Transpose Referenzen per Hand anpassen
1220 if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) )
1221 pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc );
1223 else if (!bTranspose)
1225 // copy with bAsLink=TRUE
1226 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc,
1227 true, true, bIncludeFiltered, bSkipEmpty );
1229 else
1231 // alle Inhalte kopieren (im TransClipDoc stehen nur Formeln)
1232 pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc );
1235 // skipped rows and merged cells don't mix
1236 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
1237 rDocFunc.UnmergeCells( aUserRange, false );
1239 pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, true ); // Refresh
1240 // und Bereich neu
1242 if ( pMixDoc ) // Rechenfunktionen mit Original-Daten auszufuehren ?
1244 pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc );
1246 delete pMixDoc;
1248 AdjustBlockHeight(); // update row heights before pasting objects
1250 ::std::vector< OUString > aExcludedChartNames;
1251 SdrPage* pPage = NULL;
1253 if ( nFlags & IDF_OBJECTS )
1255 ScDrawView* pScDrawView = GetScDrawView();
1256 SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL );
1257 pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL );
1258 if ( pPage )
1260 ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
1263 // Paste the drawing objects after the row heights have been updated.
1265 pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc,
1266 true, false, bIncludeFiltered );
1269 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1270 nEndCol, nEndRow, nEndTab ); // content after the change
1272 // ggf. Autofilter-Koepfe loeschen
1273 if (bCutMode)
1274 if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX,
1275 nClipStartY+nClipSizeY, nStartTab ))
1277 pDocSh->PostPaint(
1278 ScRange(nClipStartX, nClipStartY, nStartTab, nClipStartX+nClipSizeX, nClipStartY, nStartTab),
1279 PAINT_GRID );
1282 //! Block-Bereich bei RefUndoDoc weglassen !!!
1284 if ( bRecord )
1286 ScDocument* pRedoDoc = NULL;
1287 // Redo-Daten werden erst beim ersten Undo kopiert
1288 // ohne RefUndoDoc muss das Redo-Doc noch nicht angelegt werden
1290 if (pRefUndoDoc)
1292 pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
1293 pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo );
1295 // angepasste Referenzen ins Redo-Doc
1297 SCTAB nTabCount = pDoc->GetTableCount();
1298 pRedoDoc->AddUndoTab( 0, nTabCount-1 );
1299 pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc );
1301 // alte Referenzen ins Undo-Doc
1303 //! Tabellen selektieren ?
1304 pUndoDoc->AddUndoTab( 0, nTabCount-1 );
1305 pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL );
1306 pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
1307 IDF_FORMULA, false, pUndoDoc );
1308 delete pRefUndoDoc;
1311 // DeleteUnchanged for pUndoData is in ScUndoPaste ctor,
1312 // UndoData for redo is made during first undo
1314 ScUndoPasteOptions aOptions; // store options for repeat
1315 aOptions.nFunction = nFunction;
1316 aOptions.bSkipEmpty = bSkipEmpty;
1317 aOptions.bTranspose = bTranspose;
1318 aOptions.bAsLink = bAsLink;
1319 aOptions.eMoveMode = eMoveMode;
1321 SfxUndoAction* pUndo = new ScUndoPaste(
1322 pDocSh, ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1323 aFilteredMark, pUndoDoc, pRedoDoc, nFlags | nUndoFlags, pUndoData,
1324 false, &aOptions ); // false = Redo data not yet copied
1326 if ( bInsertCells )
1328 // Merge the paste undo action into the insert action.
1329 // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action.
1331 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1333 else
1334 pUndoMgr->AddUndoAction( pUndo );
1335 pUndoMgr->LeaveListAction();
1338 sal_uInt16 nPaint = PAINT_GRID;
1339 if (bColInfo)
1341 nPaint |= PAINT_TOP;
1342 nUndoEndCol = MAXCOL; // nur zum Zeichnen !
1344 if (bRowInfo)
1346 nPaint |= PAINT_LEFT;
1347 nUndoEndRow = MAXROW; // nur zum Zeichnen !
1349 pDocSh->PostPaint(
1350 ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1351 nPaint, nExtFlags);
1352 // AdjustBlockHeight has already been called above
1354 ResetAutoSpell();
1355 aModificator.SetDocumentModified();
1356 PostPasteFromClip(aUserRange, rMark);
1358 if ( nFlags & IDF_OBJECTS )
1360 ScModelObj* pModelObj = ( pDocSh ? ScModelObj::getImplementation( pDocSh->GetModel() ) : NULL );
1361 if ( pDoc && pPage && pModelObj )
1363 bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() );
1364 const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector );
1365 ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab,
1366 rProtectedChartRangesVector, aExcludedChartNames, bSameDoc );
1370 return true;
1373 bool ScViewFunc::PasteMultiRangesFromClip(
1374 sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1375 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1376 InsCellCmd eMoveMode, sal_uInt16 nUndoFlags)
1378 ScViewData& rViewData = *GetViewData();
1379 ScDocument* pDoc = rViewData.GetDocument();
1380 ScDocShell* pDocSh = rViewData.GetDocShell();
1381 ScMarkData aMark(rViewData.GetMarkData());
1382 const ScAddress& rCurPos = rViewData.GetCurPos();
1383 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1384 SCCOL nColSize = rClipParam.getPasteColSize();
1385 SCROW nRowSize = rClipParam.getPasteRowSize();
1387 if (bTranspose)
1389 if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
1391 ErrorMessage(STR_PASTE_FULL);
1392 return false;
1395 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1396 ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
1397 SAL_WNODEPRECATED_DECLARATIONS_POP
1398 pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
1399 pClipDoc = pTransClip.release();
1400 SCCOL nTempColSize = nColSize;
1401 nColSize = static_cast<SCCOL>(nRowSize);
1402 nRowSize = static_cast<SCROW>(nTempColSize);
1405 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1407 ErrorMessage(STR_PASTE_FULL);
1408 return false;
1411 // Determine the first and last selected sheet numbers.
1412 SCTAB nTab1 = aMark.GetFirstSelected();
1413 SCTAB nTab2 = aMark.GetLastSelected();
1415 ScDocShellModificator aModificator(*pDocSh);
1417 // For multi-selection paste, we don't support cell duplication for larger
1418 // destination range. In case the destination is marked, we reset it to
1419 // the clip size.
1420 ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
1421 rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
1423 // Extend the marked range to account for filtered rows in the destination
1424 // area.
1425 if (ScViewUtil::HasFiltered(aMarkedRange, pDoc))
1427 if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize))
1428 return false;
1431 bool bAskIfNotEmpty =
1432 bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1433 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1435 if (bAskIfNotEmpty)
1437 ScRangeList aTestRanges;
1438 aTestRanges.Append(aMarkedRange);
1439 if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aMark, rViewData.GetDialogParent()))
1440 return false;
1443 aMark.SetMarkArea(aMarkedRange);
1444 MarkRange(aMarkedRange);
1446 bool bInsertCells = (eMoveMode != INS_NONE);
1447 if (bInsertCells)
1449 if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
1450 return false;
1453 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1454 ::std::auto_ptr<ScDocument> pUndoDoc;
1455 SAL_WNODEPRECATED_DECLARATIONS_POP
1456 if (pDoc->IsUndoEnabled())
1458 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1459 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1460 pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1463 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1464 ::std::auto_ptr<ScDocument> pMixDoc;
1465 SAL_WNODEPRECATED_DECLARATIONS_POP
1466 if ( bSkipEmpty || nFunction )
1468 if ( nFlags & IDF_CONTENTS )
1470 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1471 pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1472 pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1476 /* Make draw layer and start drawing undo.
1477 - Needed before AdjustBlockHeight to track moved drawing objects.
1478 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1480 if (nFlags & IDF_OBJECTS)
1481 pDocSh->MakeDrawLayer();
1482 if (pDoc->IsUndoEnabled())
1483 pDoc->BeginDrawUndo();
1485 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1486 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
1487 true, bAsLink, false, bSkipEmpty);
1489 if (pMixDoc.get())
1490 pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
1492 AdjustBlockHeight(); // update row heights before pasting objects
1494 if (nFlags & IDF_OBJECTS)
1496 // Paste the drawing objects after the row heights have been updated.
1497 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
1498 true, false, false, true);
1501 ScRange aTmp = aMarkedRange;
1502 aTmp.aStart.SetTab(nTab1);
1503 aTmp.aEnd.SetTab(nTab1);
1504 pDocSh->PostPaint(aTmp, PAINT_GRID);
1506 if (pDoc->IsUndoEnabled())
1508 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1509 OUString aUndo = ScGlobal::GetRscString(
1510 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1511 pUndoMgr->EnterListAction(aUndo, aUndo);
1513 ScUndoPasteOptions aOptions; // store options for repeat
1514 aOptions.nFunction = nFunction;
1515 aOptions.bSkipEmpty = bSkipEmpty;
1516 aOptions.bTranspose = bTranspose;
1517 aOptions.bAsLink = bAsLink;
1518 aOptions.eMoveMode = eMoveMode;
1520 ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
1521 aMarkedRange, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1523 if (bInsertCells)
1524 pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
1525 else
1526 pUndoMgr->AddUndoAction(pUndo, false);
1528 pUndoMgr->LeaveListAction();
1531 ResetAutoSpell();
1532 aModificator.SetDocumentModified();
1533 PostPasteFromClip(aMarkedRange, aMark);
1534 return true;
1537 bool ScViewFunc::PasteFromClipToMultiRanges(
1538 sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1539 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1540 InsCellCmd eMoveMode, sal_uInt16 nUndoFlags )
1542 if (bTranspose)
1544 // We don't allow transpose for this yet.
1545 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1546 return false;
1549 if (eMoveMode != INS_NONE)
1551 // We don't allow insertion mode either. Too complicated.
1552 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1553 return false;
1556 ScViewData& rViewData = *GetViewData();
1557 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1558 if (rClipParam.mbCutMode)
1560 // No cut and paste with this, please.
1561 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1562 return false;
1565 const ScAddress& rCurPos = rViewData.GetCurPos();
1566 ScDocument* pDoc = rViewData.GetDocument();
1568 ScRange aSrcRange = rClipParam.getWholeRange();
1569 SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
1570 SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
1572 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1574 ErrorMessage(STR_PASTE_FULL);
1575 return false;
1578 ScMarkData aMark(rViewData.GetMarkData());
1580 ScRangeList aRanges;
1581 aMark.MarkToSimple();
1582 aMark.FillRangeListWithMarks(&aRanges, false);
1583 if (!ScClipUtil::CheckDestRanges(pDoc, nColSize, nRowSize, aMark, aRanges))
1585 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1586 return false;
1589 ScDocShell* pDocSh = rViewData.GetDocShell();
1591 ScDocShellModificator aModificator(*pDocSh);
1593 bool bAskIfNotEmpty =
1594 bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1595 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1597 if (bAskIfNotEmpty)
1599 if (!checkDestRangeForOverwrite(aRanges, pDoc, aMark, rViewData.GetDialogParent()))
1600 return false;
1603 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1604 std::auto_ptr<ScDocument> pUndoDoc;
1605 SAL_WNODEPRECATED_DECLARATIONS_POP
1606 if (pDoc->IsUndoEnabled())
1608 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1609 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1610 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1612 pDoc->CopyToDocument(
1613 *aRanges[i], nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1617 boost::scoped_ptr<ScDocument> pMixDoc;
1618 if (bSkipEmpty || nFunction)
1620 if (nFlags & IDF_CONTENTS)
1622 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1623 pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1624 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1626 pDoc->CopyToDocument(
1627 *aRanges[i], IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1632 if (nFlags & IDF_OBJECTS)
1633 pDocSh->MakeDrawLayer();
1634 if (pDoc->IsUndoEnabled())
1635 pDoc->BeginDrawUndo();
1637 // First, paste everything but the drawing objects.
1638 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1640 pDoc->CopyFromClip(
1641 *aRanges[i], aMark, (nFlags & ~IDF_OBJECTS), NULL, pClipDoc,
1642 false, false, true, bSkipEmpty, NULL);
1645 if (pMixDoc.get())
1647 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1648 pDoc->MixDocument(*aRanges[i], nFunction, bSkipEmpty, pMixDoc.get());
1651 AdjustBlockHeight(); // update row heights before pasting objects
1653 // Then paste the objects.
1654 if (nFlags & IDF_OBJECTS)
1656 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1658 pDoc->CopyFromClip(
1659 *aRanges[i], aMark, IDF_OBJECTS, NULL, pClipDoc,
1660 false, false, true, bSkipEmpty, NULL);
1664 // Refresh the range that includes all pasted ranges. We only need to
1665 // refresh the current sheet.
1666 pDocSh->PostPaint(aRanges, PAINT_GRID);
1668 if (pDoc->IsUndoEnabled())
1670 svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1671 OUString aUndo = ScGlobal::GetRscString(
1672 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1673 pUndoMgr->EnterListAction(aUndo, aUndo);
1675 ScUndoPasteOptions aOptions; // store options for repeat
1676 aOptions.nFunction = nFunction;
1677 aOptions.bSkipEmpty = bSkipEmpty;
1678 aOptions.bTranspose = bTranspose;
1679 aOptions.bAsLink = bAsLink;
1680 aOptions.eMoveMode = eMoveMode;
1682 ScUndoPaste* pUndo = new ScUndoPaste(
1683 pDocSh, aRanges, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1685 pUndoMgr->AddUndoAction(pUndo, false);
1686 pUndoMgr->LeaveListAction();
1689 ResetAutoSpell();
1690 aModificator.SetDocumentModified();
1691 PostPasteFromClip(aRanges, aMark);
1693 return false;
1696 void ScViewFunc::PostPasteFromClip(const ScRangeList& rPasteRanges, const ScMarkData& rMark)
1698 ScViewData* pViewData = GetViewData();
1699 ScDocShell* pDocSh = pViewData->GetDocShell();
1700 pDocSh->UpdateOle(pViewData);
1702 SelectionChanged();
1704 ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
1705 if (!pModelObj)
1706 return;
1708 ScRangeList aChangeRanges;
1709 for (size_t i = 0, n = rPasteRanges.size(); i < n; ++i)
1711 const ScRange& r = *rPasteRanges[i];
1712 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1713 for (; itr != itrEnd; ++itr)
1715 ScRange aChangeRange(r);
1716 aChangeRange.aStart.SetTab(*itr);
1717 aChangeRange.aEnd.SetTab(*itr);
1718 aChangeRanges.Append(aChangeRange);
1721 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
1725 //----------------------------------------------------------------------------
1726 // D R A G A N D D R O P
1728 // innerhalb des Dokuments
1730 sal_Bool ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos,
1731 sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
1733 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1734 HideAllCursors(); // wegen zusammengefassten
1736 sal_Bool bSuccess = sal_True;
1737 SCTAB nDestTab = rDestPos.Tab();
1738 const ScMarkData& rMark = GetViewData()->GetMarkData();
1739 if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 )
1741 // moving within one table and several tables selected -> apply to all selected tables
1743 if ( bRecord )
1745 OUString aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY );
1746 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
1749 // collect ranges of consecutive selected tables
1751 ScRange aLocalSource = rSource;
1752 ScAddress aLocalDest = rDestPos;
1753 SCTAB nTabCount = pDocSh->GetDocument()->GetTableCount();
1754 SCTAB nStartTab = 0;
1755 while ( nStartTab < nTabCount && bSuccess )
1757 while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) )
1758 ++nStartTab;
1759 if ( nStartTab < nTabCount )
1761 SCTAB nEndTab = nStartTab;
1762 while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) )
1763 ++nEndTab;
1765 aLocalSource.aStart.SetTab( nStartTab );
1766 aLocalSource.aEnd.SetTab( nEndTab );
1767 aLocalDest.SetTab( nStartTab );
1769 bSuccess = pDocSh->GetDocFunc().MoveBlock(
1770 aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi );
1772 nStartTab = nEndTab + 1;
1776 if ( bRecord )
1777 pDocSh->GetUndoManager()->LeaveListAction();
1779 else
1781 // move the block as specified
1782 bSuccess = pDocSh->GetDocFunc().MoveBlock(
1783 rSource, rDestPos, bCut, bRecord, bPaint, bApi );
1786 ShowAllCursors();
1787 if (bSuccess)
1789 // Zielbereich markieren
1790 ScAddress aDestEnd(
1791 rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(),
1792 rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(),
1793 nDestTab );
1795 sal_Bool bIncludeFiltered = bCut;
1796 if ( !bIncludeFiltered )
1798 // find number of non-filtered rows
1799 SCROW nPastedCount = pDocSh->GetDocument()->CountNonFilteredRows(
1800 rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab());
1802 if ( nPastedCount == 0 )
1803 nPastedCount = 1;
1804 aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 );
1807 MarkRange( ScRange( rDestPos, aDestEnd ), false ); //! sal_False ???
1809 pDocSh->UpdateOle(GetViewData());
1810 SelectionChanged();
1811 ResetAutoSpell();
1813 return bSuccess;
1816 // Link innerhalb des Dokuments
1818 sal_Bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, sal_Bool bApi )
1820 // Test auf Ueberlappung
1822 if ( rSource.aStart.Tab() == rDestPos.Tab() )
1824 SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() );
1825 SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() );
1827 if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() &&
1828 rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() )
1830 if (!bApi)
1831 ErrorMessage( STR_ERR_LINKOVERLAP );
1832 return false;
1836 // Ausfuehren per Paste
1838 ScDocument* pDoc = GetViewData()->GetDocument();
1839 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
1840 pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(),
1841 rSource.aEnd.Col(), rSource.aEnd.Row(),
1842 rSource.aStart.Tab(), pClipDoc );
1844 // Zielbereich markieren (Cursor setzen, keine Markierung)
1846 if ( GetViewData()->GetTabNo() != rDestPos.Tab() )
1847 SetTabNo( rDestPos.Tab() );
1849 MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, false, false );
1851 // Paste
1853 PasteFromClip( IDF_ALL, pClipDoc, PASTE_NOFUNC, false, false, sal_True ); // als Link
1855 delete pClipDoc;
1857 return sal_True;
1860 void ScViewFunc::DataFormPutData( SCROW nCurrentRow ,
1861 SCROW nStartRow , SCCOL nStartCol ,
1862 SCROW nEndRow , SCCOL nEndCol ,
1863 boost::ptr_vector<boost::nullable<Edit> >& aEdits,
1864 sal_uInt16 aColLength )
1866 ScDocument* pDoc = GetViewData()->GetDocument();
1867 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1868 ScMarkData& rMark = GetViewData()->GetMarkData();
1869 ScDocShellModificator aModificator( *pDocSh );
1870 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1871 if ( pDoc )
1873 const sal_Bool bRecord( pDoc->IsUndoEnabled());
1874 ScDocument* pUndoDoc = NULL;
1875 ScDocument* pRedoDoc = NULL;
1876 ScRefUndoData* pUndoData = NULL;
1877 SCTAB nTab = GetViewData()->GetTabNo();
1878 SCTAB nStartTab = nTab;
1879 SCTAB nEndTab = nTab;
1882 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1883 if ( pChangeTrack )
1884 pChangeTrack->ResetLastCut(); // kein CutMode mehr
1886 ScRange aUserRange( nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab );
1887 sal_Bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1888 sal_Bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1889 SCCOL nUndoEndCol = nStartCol+aColLength-1;
1890 SCROW nUndoEndRow = nCurrentRow;
1891 sal_uInt16 nUndoFlags = IDF_NONE;
1893 if ( bRecord )
1895 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1896 pUndoDoc->InitUndoSelected( pDoc , rMark , bColInfo , bRowInfo );
1897 pDoc->CopyToDocument( aUserRange , 1 , false , pUndoDoc );
1899 sal_uInt16 nExtFlags = 0;
1900 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab , nEndCol, nEndRow, nEndTab ); // content before the change
1901 pDoc->BeginDrawUndo();
1903 for(sal_uInt16 i = 0; i < aColLength; i++)
1905 if (!aEdits.is_null(i))
1907 OUString aFieldName=aEdits[i].GetText();
1908 pDoc->SetString( nStartCol + i, nCurrentRow, nTab, aFieldName );
1911 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab ); // content after the change
1912 SfxUndoAction* pUndo = new ScUndoDataForm( pDocSh,
1913 nStartCol, nCurrentRow, nStartTab,
1914 nUndoEndCol, nUndoEndRow, nEndTab, rMark,
1915 pUndoDoc, pRedoDoc, nUndoFlags,
1916 pUndoData, NULL, NULL, NULL,
1917 false ); // FALSE = Redo data not yet copied
1918 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1920 sal_uInt16 nPaint = PAINT_GRID;
1921 if (bColInfo)
1923 nPaint |= PAINT_TOP;
1924 nUndoEndCol = MAXCOL; // nur zum Zeichnen !
1926 if (bRowInfo)
1928 nPaint |= PAINT_LEFT;
1929 nUndoEndRow = MAXROW; // nur zum Zeichnen !
1932 pDocSh->PostPaint(
1933 ScRange(nStartCol, nCurrentRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1934 nPaint, nExtFlags);
1935 pDocSh->UpdateOle(GetViewData());
1940 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */