bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / ui / view / viewfun3.cxx
blobef6b07c4e43e646cfc03ef6b81c8f4c2b058fe1b
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 #define _OUTLINER_HXX
22 #include "scitems.hxx"
23 #include <svx/svdetc.hxx>
24 #include <svx/svditer.hxx>
25 #include <svx/svdoole2.hxx>
26 #include <svx/svdpage.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <sfx2/docfile.hxx>
29 #include <svl/stritem.hxx>
30 #include <svl/ptitem.hxx>
31 #include <svl/urlbmk.hxx>
32 #include <comphelper/classids.hxx>
33 #include <sot/formats.hxx>
34 #include <vcl/graph.hxx>
35 #include <vcl/virdev.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <tools/urlobj.hxx>
38 #include <sot/exchange.hxx>
39 #include <memory>
41 #include "attrib.hxx"
42 #include "patattr.hxx"
43 #include "dociter.hxx"
44 #include "viewfunc.hxx"
45 #include "tabvwsh.hxx"
46 #include "docsh.hxx"
47 #include "docfunc.hxx"
48 #include "undoblk.hxx"
49 #include "refundo.hxx"
50 #include "globstr.hrc"
51 #include "global.hxx"
52 #include "transobj.hxx"
53 #include "drwtrans.hxx"
54 #include "rangenam.hxx"
55 #include "dbdata.hxx"
56 #include "impex.hxx" // Sylk-ID fuer CB
57 #include "chgtrack.hxx"
58 #include "waitoff.hxx"
59 #include "scmod.hxx"
60 #include "sc.hrc"
61 #include "inputopt.hxx"
62 #include "warnbox.hxx"
63 #include "drwlayer.hxx"
64 #include "editable.hxx"
65 #include "docuno.hxx"
66 #include "clipparam.hxx"
67 #include "undodat.hxx"
68 #include "drawview.hxx"
69 #include "cliputil.hxx"
71 using namespace com::sun::star;
73 // STATIC DATA ---------------------------------------------------------------
76 //============================================================================
78 // GlobalName der Writer-DocShell kommt jetzt aus comphelper/classids.hxx
80 //----------------------------------------------------------------------------
81 // C U T
83 void ScViewFunc::CutToClip( ScDocument* pClipDoc, sal_Bool bIncludeObjects )
85 UpdateInputLine();
87 ScEditableTester aTester( this );
88 if (!aTester.IsEditable()) // selection editable?
90 ErrorMessage( aTester.GetMessageId() );
91 return;
94 ScRange aRange; // zu loeschender Bereich
95 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
97 ScDocument* pDoc = GetViewData()->GetDocument();
98 ScDocShell* pDocSh = GetViewData()->GetDocShell();
99 ScMarkData& rMark = GetViewData()->GetMarkData();
100 const sal_Bool bRecord(pDoc->IsUndoEnabled()); // Undo/Redo
102 ScDocShellModificator aModificator( *pDocSh );
104 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) // mark the range if not marked yet
106 DoneBlockMode();
107 InitOwnBlockMode();
108 rMark.SetMarkArea( aRange );
109 MarkDataChanged();
112 CopyToClip( pClipDoc, sal_True, false, bIncludeObjects ); // Ab ins Clipboard
114 ScAddress aOldEnd( aRange.aEnd ); // Zusammengefasste Zellen im Bereich?
115 pDoc->ExtendMerge( aRange, sal_True );
117 ScDocument* pUndoDoc = NULL;
118 if ( bRecord )
120 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
121 pUndoDoc->InitUndoSelected( pDoc, rMark );
122 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
123 ScRange aCopyRange = aRange;
124 aCopyRange.aStart.SetTab(0);
125 aCopyRange.aEnd.SetTab(pDoc->GetTableCount()-1);
126 pDoc->CopyToDocument( aCopyRange, (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS, false, pUndoDoc );
127 pDoc->BeginDrawUndo();
130 sal_uInt16 nExtFlags = 0;
131 pDocSh->UpdatePaintExt( nExtFlags, aRange );
133 rMark.MarkToMulti();
134 pDoc->DeleteSelection( IDF_ALL, rMark );
135 if ( bIncludeObjects )
136 pDoc->DeleteObjectsInSelection( rMark );
137 rMark.MarkToSimple();
139 if ( !AdjustRowHeight( aRange.aStart.Row(), aRange.aEnd.Row() ) )
140 pDocSh->PostPaint( aRange, PAINT_GRID, nExtFlags );
142 if ( bRecord ) // erst jetzt ist Draw-Undo verfuegbar
143 pDocSh->GetUndoManager()->AddUndoAction(
144 new ScUndoCut( pDocSh, aRange, aOldEnd, rMark, pUndoDoc ) );
146 aModificator.SetDocumentModified();
147 pDocSh->UpdateOle(GetViewData());
149 CellContentChanged();
151 else
152 ErrorMessage( STR_NOMULTISELECT );
156 //----------------------------------------------------------------------------
157 // C O P Y
159 sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, sal_Bool bCut, sal_Bool bApi, sal_Bool bIncludeObjects, sal_Bool bStopEdit )
161 ScRange aRange;
162 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange );
163 ScMarkData& rMark = GetViewData()->GetMarkData();
164 sal_Bool bDone = sal_False;
166 if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
168 ScRangeList aRangeList;
169 aRangeList.Append( aRange );
170 bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, sal_False );
172 else if (eMarkType == SC_MARK_MULTI)
174 ScRangeList aRangeList;
175 rMark.MarkToSimple();
176 rMark.FillRangeListWithMarks(&aRangeList, false);
177 bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, sal_False );
179 else
181 if (!bApi)
182 ErrorMessage(STR_NOMULTISELECT);
185 return bDone;
188 // Copy the content of the Range into clipboard.
189 sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRangeList& rRanges, sal_Bool bCut, sal_Bool bApi, sal_Bool bIncludeObjects, sal_Bool bStopEdit, sal_Bool bUseRangeForVBA )
191 if ( rRanges.empty() )
192 return false;
193 sal_Bool bDone = false;
194 if ( bStopEdit )
195 UpdateInputLine();
197 ScRange aRange = *rRanges[0];
198 ScClipParam aClipParam( aRange, bCut );
199 aClipParam.maRanges = rRanges;
201 ScDocument* pDoc = GetViewData()->GetDocument();
202 ScMarkData& rMark = GetViewData()->GetMarkData();
204 if ( !aClipParam.isMultiRange() )
206 if ( pDoc && ( !pDoc->HasSelectedBlockMatrixFragment( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), rMark ) ) )
208 sal_Bool bSysClip = false;
209 if ( !pClipDoc ) // no clip doc specified
211 // Create one (deleted by ScTransferObj).
212 pClipDoc = new ScDocument( SCDOCMODE_CLIP );
213 bSysClip = sal_True; // and copy into system
215 if ( !bCut )
217 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
218 if ( pChangeTrack )
219 pChangeTrack->ResetLastCut();
222 if ( bSysClip && bIncludeObjects )
224 sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange );
225 // Update ScGlobal::pDrawClipDocShellRef.
226 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
229 if ( !bUseRangeForVBA )
230 // is this necessary?, will setting the doc id upset the
231 // following paste operation with range? would be nicer to just set this always
232 // and lose the 'if' above
233 aClipParam.setSourceDocID( pDoc->GetDocumentID() );
235 pDoc->CopyToClip( aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
236 if ( !bUseRangeForVBA && pDoc && pClipDoc )
238 ScDrawLayer* pDrawLayer = pClipDoc->GetDrawLayer();
239 if ( pDrawLayer )
241 ScClipParam& rClipParam = pClipDoc->GetClipParam();
242 ScRangeListVector& rRangesVector = rClipParam.maProtectedChartRangesVector;
243 SCTAB nTabCount = pClipDoc->GetTableCount();
244 for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab )
246 SdrPage* pPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
247 if ( pPage )
249 ScChartHelper::FillProtectedChartRangesVector( rRangesVector, pDoc, pPage );
255 if ( bSysClip )
257 ScDrawLayer::SetGlobalDrawPersist(NULL);
258 ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) );
260 pClipDoc->ExtendMerge( aRange, true );
262 if ( bSysClip )
264 ScDocShell* pDocSh = GetViewData()->GetDocShell();
265 TransferableObjectDescriptor aObjDesc;
266 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
267 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
268 // maSize is set in ScTransferObj ctor
270 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
271 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
272 if ( ScGlobal::pDrawClipDocShellRef )
274 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
275 pTransferObj->SetDrawPersist( aPersistRef );// keep persist for ole objects alive
278 pTransferObj->CopyToClipboard( GetActiveWin() );
279 SC_MOD()->SetClipObject( pTransferObj, NULL );
282 bDone = true;
285 else
287 bool bSuccess = false;
288 aClipParam.mbCutMode = false;
292 if (bCut)
293 // We con't support cutting of multi-selections.
294 break;
296 if (pClipDoc)
297 // TODO: What's this for?
298 break;
300 SAL_WNODEPRECATED_DECLARATIONS_PUSH
301 ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
302 SAL_WNODEPRECATED_DECLARATIONS_POP
304 // Check for geometrical feasibility of the ranges.
305 bool bValidRanges = true;
306 ScRange* p = aClipParam.maRanges.front();
307 SCCOL nPrevColDelta = 0;
308 SCROW nPrevRowDelta = 0;
309 SCCOL nPrevCol = p->aStart.Col();
310 SCROW nPrevRow = p->aStart.Row();
311 SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
312 SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
313 for ( size_t i = 1; i < aClipParam.maRanges.size(); ++i )
315 p = aClipParam.maRanges[i];
316 if ( pDoc->HasSelectedBlockMatrixFragment(
317 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark) )
319 if (!bApi)
320 ErrorMessage(STR_MATRIXFRAGMENTERR);
321 return false;
324 SCCOL nColDelta = p->aStart.Col() - nPrevCol;
325 SCROW nRowDelta = p->aStart.Row() - nPrevRow;
327 if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
329 bValidRanges = false;
330 break;
333 if (aClipParam.meDirection == ScClipParam::Unspecified)
335 if (nColDelta)
336 aClipParam.meDirection = ScClipParam::Column;
337 if (nRowDelta)
338 aClipParam.meDirection = ScClipParam::Row;
341 SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
342 SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
344 if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
346 // column-oriented ranges must have identical row size.
347 bValidRanges = false;
348 break;
350 if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
352 // likewise, row-oriented ranges must have identical
353 // column size.
354 bValidRanges = false;
355 break;
358 nPrevCol = p->aStart.Col();
359 nPrevRow = p->aStart.Row();
360 nPrevColDelta = nColDelta;
361 nPrevRowDelta = nRowDelta;
362 nPrevColSize = nColSize;
363 nPrevRowSize = nRowSize;
365 if (!bValidRanges)
366 break;
367 pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
369 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
370 if ( pChangeTrack )
371 pChangeTrack->ResetLastCut(); // kein CutMode mehr
374 ScDocShell* pDocSh = GetViewData()->GetDocShell();
375 TransferableObjectDescriptor aObjDesc;
376 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
377 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
378 // maSize is set in ScTransferObj ctor
380 ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
381 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
383 if ( ScGlobal::pDrawClipDocShellRef )
385 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
386 pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
389 pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
390 SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
393 bSuccess = true;
395 while (false);
397 if (!bSuccess && !bApi)
398 ErrorMessage(STR_NOMULTISELECT);
400 bDone = bSuccess;
403 return bDone;
406 ScTransferObj* ScViewFunc::CopyToTransferable()
408 ScRange aRange;
409 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
411 ScDocument* pDoc = GetViewData()->GetDocument();
412 ScMarkData& rMark = GetViewData()->GetMarkData();
413 if ( !pDoc->HasSelectedBlockMatrixFragment(
414 aRange.aStart.Col(), aRange.aStart.Row(),
415 aRange.aEnd.Col(), aRange.aEnd.Row(),
416 rMark ) )
418 ScDocument *pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj)
420 sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
421 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
423 ScClipParam aClipParam(aRange, false);
424 pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true);
426 ScDrawLayer::SetGlobalDrawPersist(NULL);
427 pClipDoc->ExtendMerge( aRange, sal_True );
429 ScDocShell* pDocSh = GetViewData()->GetDocShell();
430 TransferableObjectDescriptor aObjDesc;
431 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
432 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
433 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
434 return pTransferObj;
438 return NULL;
441 //----------------------------------------------------------------------------
442 // P A S T E
444 void ScViewFunc::PasteDraw()
446 ScViewData* pViewData = GetViewData();
447 SCCOL nPosX = pViewData->GetCurX();
448 SCROW nPosY = pViewData->GetCurY();
449 Window* pWin = GetActiveWin();
450 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY,
451 pViewData->GetActivePart() ) );
452 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
453 if (pDrawClip)
454 PasteDraw( aPos, pDrawClip->GetModel(), false,
455 pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
458 void ScViewFunc::PasteFromSystem()
460 UpdateInputLine();
462 Window* pWin = GetActiveWin();
463 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
464 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
466 if (pOwnClip)
468 // keep a reference in case the clipboard is changed during PasteFromClip
469 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
470 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
471 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
472 sal_True ); // allow warning dialog
474 else if (pDrawClip)
475 PasteDraw();
476 else
478 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
481 sal_uLong nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
482 sal_uLong nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
484 // als erstes SvDraw-Model, dann Grafik
485 // (Grafik darf nur bei einzelner Grafik drinstehen)
487 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
489 // special case for tables from drawing
490 if( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
492 PasteFromSystem( FORMAT_RTF );
494 else
496 PasteFromSystem( SOT_FORMATSTR_ID_DRAWING );
499 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
500 PasteFromSystem( SOT_FORMATSTR_ID_SVXB );
501 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
503 // If it's a Writer object, insert RTF instead of OLE
505 // Else, if the class id is all-zero, and SYLK is available,
506 // it probably is spreadsheet cells that have been put
507 // on the clipboard by OOo, so use the SYLK. (fdo#31077)
509 sal_Bool bDoRtf = false;
510 TransferableObjectDescriptor aObjDesc;
511 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
513 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
514 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
515 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
517 if ( bDoRtf )
518 PasteFromSystem( FORMAT_RTF );
519 else if ( aObjDesc.maClassName == SvGlobalName( 0,0,0,0,0,0,0,0,0,0,0 )
520 && aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ))
521 PasteFromSystem( SOT_FORMATSTR_ID_SYLK );
522 else
523 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE );
525 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
526 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE );
527 // the following format can not affect scenario from #89579#
528 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
529 PasteFromSystem( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE );
530 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
531 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
532 PasteFromSystem(nBiff8);
533 else if (aDataHelper.HasFormat(nBiff5))
534 PasteFromSystem(nBiff5);
535 else if (aDataHelper.HasFormat(FORMAT_RTF))
536 PasteFromSystem(FORMAT_RTF);
537 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
538 PasteFromSystem(SOT_FORMATSTR_ID_HTML);
539 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
540 PasteFromSystem(SOT_FORMATSTR_ID_HTML_SIMPLE);
541 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
542 PasteFromSystem(SOT_FORMATSTR_ID_SYLK);
543 else if (aDataHelper.HasFormat(FORMAT_STRING))
544 PasteFromSystem(FORMAT_STRING);
545 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
546 PasteFromSystem(FORMAT_GDIMETAFILE);
547 else if (aDataHelper.HasFormat(FORMAT_BITMAP))
548 PasteFromSystem(FORMAT_BITMAP);
549 // xxx_OLE formats come last, like in SotExchange tables
550 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
551 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE );
552 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
553 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE_OLE );
556 // keine Fehlermeldung, weil SID_PASTE in der idl das FastCall-Flag hat,
557 // also auch gerufen wird, wenn nichts im Clipboard steht (#42531#)
560 void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTransferable>& rxTransferable )
562 ScTransferObj *pOwnClip=0;
563 ScDrawTransferObj *pDrawClip=0;
564 uno::Reference<lang::XUnoTunnel> xTunnel( rxTransferable, uno::UNO_QUERY );
565 if ( xTunnel.is() )
567 sal_Int64 nHandle = xTunnel->getSomething( ScTransferObj::getUnoTunnelId() );
568 if ( nHandle )
569 pOwnClip = (ScTransferObj*) (sal_IntPtr) nHandle;
570 else
572 nHandle = xTunnel->getSomething( ScDrawTransferObj::getUnoTunnelId() );
573 if ( nHandle )
574 pDrawClip = (ScDrawTransferObj*) (sal_IntPtr) nHandle;
578 if (pOwnClip)
580 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
581 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
582 sal_True ); // allow warning dialog
584 else if (pDrawClip)
586 ScViewData* pViewData = GetViewData();
587 SCCOL nPosX = pViewData->GetCurX();
588 SCROW nPosY = pViewData->GetCurY();
589 Window* pWin = GetActiveWin();
590 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY, pViewData->GetActivePart() ) );
591 PasteDraw( aPos, pDrawClip->GetModel(), false, pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
593 else
595 TransferableDataHelper aDataHelper( rxTransferable );
597 sal_uLong nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
598 sal_uLong nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
599 sal_uLong nFormatId = 0;
600 // als erstes SvDraw-Model, dann Grafik
601 // (Grafik darf nur bei einzelner Grafik drinstehen)
603 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
604 nFormatId = SOT_FORMATSTR_ID_DRAWING;
605 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
606 nFormatId = SOT_FORMATSTR_ID_SVXB;
607 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
609 // If it's a Writer object, insert RTF instead of OLE
610 sal_Bool bDoRtf = false;
611 TransferableObjectDescriptor aObjDesc;
612 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
614 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
615 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
616 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
618 if ( bDoRtf )
619 nFormatId = FORMAT_RTF;
620 else
621 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
623 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
624 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
625 // the following format can not affect scenario from #89579#
626 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
627 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
628 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
629 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
630 nFormatId = nBiff8;
631 else if (aDataHelper.HasFormat(nBiff5))
632 nFormatId = nBiff5;
633 else if (aDataHelper.HasFormat(FORMAT_RTF))
634 nFormatId = FORMAT_RTF;
635 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
636 nFormatId = SOT_FORMATSTR_ID_HTML;
637 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
638 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
639 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
640 nFormatId = SOT_FORMATSTR_ID_SYLK;
641 else if (aDataHelper.HasFormat(FORMAT_STRING))
642 nFormatId = FORMAT_STRING;
643 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
644 nFormatId = FORMAT_GDIMETAFILE;
645 else if (aDataHelper.HasFormat(FORMAT_BITMAP))
646 nFormatId = FORMAT_BITMAP;
647 // xxx_OLE formats come last, like in SotExchange tables
648 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
649 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
650 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
651 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
652 else
653 return;
655 PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
656 GetViewData()->GetCurX(), GetViewData()->GetCurY(),
657 NULL, false, false );
662 sal_Bool ScViewFunc::PasteFromSystem( sal_uLong nFormatId, sal_Bool bApi )
664 UpdateInputLine();
666 sal_Bool bRet = sal_True;
667 Window* pWin = GetActiveWin();
668 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
669 if ( nFormatId == 0 && pOwnClip )
671 // keep a reference in case the clipboard is changed during PasteFromClip
672 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
673 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
674 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
675 !bApi ); // allow warning dialog
677 else
679 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
680 if ( !aDataHelper.GetTransferable().is() )
681 return false;
683 bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
684 GetViewData()->GetCurX(), GetViewData()->GetCurY(),
685 NULL, false, !bApi ); // allow warning dialog
687 if ( !bRet && !bApi )
688 ErrorMessage(STR_PASTE_ERROR);
690 return bRet;
694 //----------------------------------------------------------------------------
695 // P A S T E
697 sal_Bool ScViewFunc::PasteOnDrawObject( const uno::Reference<datatransfer::XTransferable>& rxTransferable,
698 SdrObject* pHitObj, sal_Bool bLink )
700 sal_Bool bRet = false;
701 if ( bLink )
703 TransferableDataHelper aDataHelper( rxTransferable );
704 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
706 SotStorageStreamRef xStm;
707 if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) )
709 Graphic aGraphic;
710 *xStm >> aGraphic;
711 bRet = ApplyGraphicToObject( pHitObj, aGraphic );
714 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
716 GDIMetaFile aMtf;
717 if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) )
718 bRet = ApplyGraphicToObject( pHitObj, Graphic(aMtf) );
720 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
722 Bitmap aBmp;
723 if( aDataHelper.GetBitmap( FORMAT_BITMAP, aBmp ) )
724 bRet = ApplyGraphicToObject( pHitObj, Graphic(aBmp) );
727 else
729 // ham' wa noch nich
731 return bRet;
734 static sal_Bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
735 const ScMarkData& rTabSelection, sal_uInt16 nMask )
737 ScMarkData::const_iterator itr = rTabSelection.begin(), itrEnd = rTabSelection.end();
738 for (; itr != itrEnd; ++itr)
739 if ( pDoc->HasAttrib( nCol1, nRow1, *itr, nCol2, nRow2, *itr, nMask ) )
740 return sal_True;
741 return false;
745 // Einfuegen auf Tabelle:
748 // internes Paste
750 namespace {
752 bool checkDestRangeForOverwrite(const ScRangeList& rDestRanges, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
754 bool bIsEmpty = true;
755 ScMarkData::const_iterator itrTab = rMark.begin(), itrTabEnd = rMark.end();
756 size_t nRangeSize = rDestRanges.size();
757 for (; itrTab != itrTabEnd && bIsEmpty; ++itrTab)
759 for (size_t i = 0; i < nRangeSize && bIsEmpty; ++i)
761 const ScRange& rRange = *rDestRanges[i];
762 bIsEmpty = pDoc->IsBlockEmpty(
763 *itrTab, rRange.aStart.Col(), rRange.aStart.Row(),
764 rRange.aEnd.Col(), rRange.aEnd.Row());
768 if (!bIsEmpty)
770 ScReplaceWarnBox aBox(pParentWnd);
771 if (aBox.Execute() != RET_YES)
773 // changing the configuration is within the ScReplaceWarnBox
774 return false;
777 return true;
782 bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
783 sal_uInt16 nFunction, bool bSkipEmpty,
784 bool bTranspose, bool bAsLink,
785 InsCellCmd eMoveMode, sal_uInt16 nUndoExtraFlags,
786 bool bAllowDialogs )
788 if (!pClipDoc)
790 OSL_FAIL("PasteFromClip: pClipDoc=0 not allowed");
791 return false;
794 // fuer Undo etc. immer alle oder keine Inhalte sichern
795 sal_uInt16 nContFlags = IDF_NONE;
796 if (nFlags & IDF_CONTENTS)
797 nContFlags |= IDF_CONTENTS;
798 if (nFlags & IDF_ATTRIB)
799 nContFlags |= IDF_ATTRIB;
800 // evtl. Attribute ins Undo ohne sie vom Clip ins Doc zu kopieren
801 sal_uInt16 nUndoFlags = nContFlags;
802 if (nUndoExtraFlags & IDF_ATTRIB)
803 nUndoFlags |= IDF_ATTRIB;
804 // do not copy note captions into undo document
805 nUndoFlags |= IDF_NOCAPTIONS;
807 ScClipParam& rClipParam = pClipDoc->GetClipParam();
808 if (rClipParam.isMultiRange())
810 // Source data is multi-range.
811 return PasteMultiRangesFromClip(
812 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
813 eMoveMode, nUndoFlags);
816 ScMarkData& rMark = GetViewData()->GetMarkData();
817 if (rMark.IsMultiMarked())
819 // Source data is single-range but destination is multi-range.
820 return PasteFromClipToMultiRanges(
821 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
822 eMoveMode, nUndoFlags);
825 bool bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
826 bool bIncludeFiltered = bCutMode;
828 // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions)
829 bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) );
831 ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip
832 ScDocument* pOrigClipDoc = NULL;
833 SAL_WNODEPRECATED_DECLARATIONS_PUSH
834 ::std::auto_ptr< ScDocument > xTransClip;
835 SAL_WNODEPRECATED_DECLARATIONS_POP
836 if ( bTranspose )
838 SCCOL nX;
839 SCROW nY;
840 // include filtered rows until TransposeClip can skip them
841 bIncludeFiltered = true;
842 pClipDoc->GetClipArea( nX, nY, true );
843 if ( nY > static_cast<sal_Int32>(MAXCOL) ) // zuviele Zeilen zum Transponieren
845 ErrorMessage(STR_PASTE_FULL);
846 return false;
848 pOrigClipDoc = pClipDoc; // fuer Referenzen
850 if ( bPasteDraw )
852 aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately
853 aTransShellRef->DoInitNew(NULL);
855 ScDrawLayer::SetGlobalDrawPersist(aTransShellRef);
857 xTransClip.reset( new ScDocument( SCDOCMODE_CLIP ));
858 pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink );
859 pClipDoc = xTransClip.get();
861 ScDrawLayer::SetGlobalDrawPersist(NULL);
864 SCCOL nStartCol;
865 SCROW nStartRow;
866 SCTAB nStartTab;
867 SCCOL nEndCol;
868 SCROW nEndRow;
869 SCTAB nEndTab;
870 SCCOL nClipSizeX;
871 SCROW nClipSizeY;
872 pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, true ); // size in clipboard doc
874 // size in target doc: include filtered rows only if CutMode is set
875 SCCOL nDestSizeX;
876 SCROW nDestSizeY;
877 pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered );
879 ScDocument* pDoc = GetViewData()->GetDocument();
880 ScDocShell* pDocSh = GetViewData()->GetDocShell();
881 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
882 const bool bRecord(pDoc->IsUndoEnabled());
884 ScDocShellModificator aModificator( *pDocSh );
886 ScRange aMarkRange;
887 ScMarkData aFilteredMark( rMark); // local copy for all modifications
888 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange, aFilteredMark);
889 bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED);
890 bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) ||
891 (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink)));
893 if (!bNoPaste)
895 if (!rMark.IsMarked())
897 // Create a selection with clipboard row count and check that for
898 // filtered.
899 nStartCol = GetViewData()->GetCurX();
900 nStartRow = GetViewData()->GetCurY();
901 nStartTab = GetViewData()->GetTabNo();
902 nEndCol = nStartCol + nDestSizeX;
903 nEndRow = nStartRow + nDestSizeY;
904 nEndTab = nStartTab;
905 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
906 if (ScViewUtil::HasFiltered( aMarkRange, pDoc))
908 bMarkIsFiltered = true;
909 // Fit to clipboard's row count unfiltered rows. If there is no
910 // fit assume that pasting is not possible. Note that nDestSizeY is
911 // size-1 (difference).
912 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
913 bNoPaste = true;
915 aFilteredMark.SetMarkArea( aMarkRange);
917 else
919 // Expand the marked area when the destination area is larger than the
920 // current selection, to get the undo do the right thing. (i#106711)
921 ScRange aRange;
922 aFilteredMark.GetMarkArea( aRange );
923 if( (aRange.aEnd.Col() - aRange.aStart.Col()) < nDestSizeX )
925 aRange.aEnd.SetCol(aRange.aStart.Col() + nDestSizeX);
926 aFilteredMark.SetMarkArea(aRange);
931 if (bNoPaste)
933 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
934 return false;
937 SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1;
938 ScRangeList aRangeList;
939 if (bMarkIsFiltered)
941 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
942 aFilteredMark.FillRangeListWithMarks( &aRangeList, false);
943 nUnfilteredRows = 0;
944 size_t ListSize = aRangeList.size();
945 for ( size_t i = 0; i < ListSize; ++i )
947 ScRange* p = aRangeList[i];
948 nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1;
950 #if 0
951 /* This isn't needed but could be a desired restriction. */
952 // For filtered, destination rows have to be an exact multiple of
953 // source rows. Note that nDestSizeY is size-1 (difference), so
954 // nDestSizeY==0 fits always.
955 if ((nUnfilteredRows % (nDestSizeY+1)) != 0)
957 /* FIXME: this should be a more descriptive error message then. */
958 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
959 return false;
961 #endif
964 // Also for a filtered selection the area is used, for undo et al.
965 if ( aFilteredMark.IsMarked() || bMarkIsFiltered )
967 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
968 SCCOL nBlockAddX = nEndCol-nStartCol;
969 SCROW nBlockAddY = nEndRow-nStartRow;
971 // Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner
972 // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt)
974 // ClipSize is not size, but difference
975 if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) ||
976 ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) ||
977 ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) )
979 ScWaitCursorOff aWaitOff( GetFrameWin() );
980 String aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER );
981 QueryBox aBox( GetViewData()->GetDialogParent(),
982 WinBits(WB_YES_NO | WB_DEF_NO), aMessage );
983 if ( aBox.Execute() != RET_YES )
985 return false;
989 if (nBlockAddX <= nDestSizeX)
990 nEndCol = nStartCol + nDestSizeX;
992 if (nBlockAddY <= nDestSizeY)
994 nEndRow = nStartRow + nDestSizeY;
995 if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row())
997 // Same as above if nothing was marked: re-fit selection to
998 // unfiltered rows. Extending the selection actually may
999 // introduce filtered rows where there weren't any before, so
1000 // we also need to test for that.
1001 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1002 if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc))
1004 bMarkIsFiltered = true;
1005 // Worst case: all rows up to the end of the sheet are filtered.
1006 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
1008 ErrorMessage(STR_PASTE_FULL);
1009 return false;
1012 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1013 aFilteredMark.SetMarkArea( aMarkRange);
1014 if (bMarkIsFiltered)
1016 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1017 aFilteredMark.FillRangeListWithMarks( &aRangeList, true);
1022 else
1024 nStartCol = GetViewData()->GetCurX();
1025 nStartRow = GetViewData()->GetCurY();
1026 nStartTab = GetViewData()->GetTabNo();
1027 nEndCol = nStartCol + nDestSizeX;
1028 nEndRow = nStartRow + nDestSizeY;
1029 nEndTab = nStartTab;
1032 bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow);
1034 // Zielbereich, wie er angezeigt wird:
1035 ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1037 // Sollen Zellen eingefuegt werden?
1038 // (zu grosse nEndCol/nEndRow werden weiter unten erkannt)
1039 bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits );
1040 if ( bInsertCells )
1042 // Instead of EnterListAction, the paste undo action is merged into the
1043 // insert action, so Repeat can insert the right cells
1045 MarkRange( aUserRange ); // wird vor CopyFromClip sowieso gesetzt
1047 // CutMode is reset on insertion of cols/rows but needed again on cell move
1048 bool bCut = pClipDoc->IsCutMode();
1049 if (!InsertCells( eMoveMode, bRecord, true )) // is inserting possible?
1051 return false;
1052 // #i21036# EnterListAction isn't used, and InsertCells doesn't insert
1053 // its undo action on failure, so no undo handling is needed here
1055 if ( bCut )
1056 pClipDoc->SetCutMode( bCut );
1058 else if (!bOffLimits)
1060 bool bAskIfNotEmpty = bAllowDialogs &&
1061 ( nFlags & IDF_CONTENTS ) &&
1062 nFunction == PASTE_NOFUNC &&
1063 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1064 if ( bAskIfNotEmpty )
1066 ScRangeList aTestRanges;
1067 aTestRanges.Append(aUserRange);
1068 if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
1069 return false;
1073 SCCOL nClipStartX; // Clipboard-Bereich erweitern
1074 SCROW nClipStartY;
1075 pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1076 SCCOL nUndoEndCol = nClipStartX + nClipSizeX;
1077 SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document
1078 bool bClipOver = false;
1079 // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers.
1080 // The same end column/row can be used for all calls because the clip doc doesn't contain
1081 // content outside the clip area.
1082 for (SCTAB nClipTab=0; nClipTab < pClipDoc->GetTableCount(); nClipTab++)
1083 if ( pClipDoc->HasTable(nClipTab) )
1084 if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, false ) )
1085 bClipOver = true;
1086 nUndoEndCol -= nClipStartX + nClipSizeX;
1087 nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge
1088 nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol );
1089 nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells
1091 if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW)
1093 ErrorMessage(STR_PASTE_FULL);
1094 return false;
1097 pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, false );
1099 // Test auf Zellschutz
1101 ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow );
1102 if (!aTester.IsEditable())
1104 ErrorMessage(aTester.GetMessageId());
1105 return false;
1108 //! Test auf Ueberlappung
1109 //! nur wirkliche Schnittmenge testen !!!!!!!
1111 ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
1112 if ( bRecord )
1114 String aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY );
1115 pUndoMgr->EnterListAction( aUndo, aUndo );
1118 if (bClipOver)
1119 if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED ))
1120 { // "Cell merge not possible if cells already merged"
1121 ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow );
1122 const ScPatternAttr* pPattern = NULL;
1123 const ScMergeAttr* pMergeFlag = NULL;
1124 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1125 SCCOL nCol = -1;
1126 SCROW nRow1 = -1;
1127 SCROW nRow2 = -1;
1128 while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL )
1130 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1131 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1132 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) )
1134 ScRange aRange(nCol, nRow1, nStartTab);
1135 pDoc->ExtendOverlapped(aRange);
1136 pDoc->ExtendMerge(aRange, true);
1137 rDocFunc.UnmergeCells(aRange, bRecord);
1142 if ( !bCutMode )
1144 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1145 if ( pChangeTrack )
1146 pChangeTrack->ResetLastCut(); // kein CutMode mehr
1149 bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1150 bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1152 ScDocument* pUndoDoc = NULL;
1153 ScDocument* pRefUndoDoc = NULL;
1154 ScRefUndoData* pUndoData = NULL;
1156 if ( bRecord )
1158 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1159 pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo );
1161 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
1162 SCTAB nTabCount = pDoc->GetTableCount();
1163 pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1,
1164 nUndoFlags, false, pUndoDoc );
1166 if ( bCutMode )
1168 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1169 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
1171 pUndoData = new ScRefUndoData( pDoc );
1175 sal_uInt16 nExtFlags = 0;
1176 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1177 nEndCol, nEndRow, nEndTab ); // content before the change
1179 if (GetViewData()->IsActive())
1181 DoneBlockMode();
1182 InitOwnBlockMode();
1184 rMark.SetMarkArea( aUserRange );
1185 MarkDataChanged();
1188 // Aus Clipboard kopieren,
1189 // wenn gerechnet werden soll, Originaldaten merken
1192 ScDocument* pMixDoc = NULL;
1193 if ( bSkipEmpty || nFunction )
1195 if ( nFlags & IDF_CONTENTS )
1197 pMixDoc = new ScDocument( SCDOCMODE_UNDO );
1198 pMixDoc->InitUndo( pDoc, nStartTab, nEndTab );
1199 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1200 IDF_CONTENTS, false, pMixDoc );
1204 /* Make draw layer and start drawing undo.
1205 - Needed before AdjustBlockHeight to track moved drawing objects.
1206 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1208 if ( bPasteDraw )
1209 pDocSh->MakeDrawLayer();
1210 if ( bRecord )
1211 pDoc->BeginDrawUndo();
1213 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1214 if (!bAsLink)
1216 // copy normally (original range)
1217 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags,
1218 pRefUndoDoc, pClipDoc, true, false, bIncludeFiltered,
1219 bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) );
1221 // bei Transpose Referenzen per Hand anpassen
1222 if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) )
1223 pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc );
1225 else if (!bTranspose)
1227 // copy with bAsLink=TRUE
1228 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc,
1229 true, true, bIncludeFiltered, bSkipEmpty );
1231 else
1233 // alle Inhalte kopieren (im TransClipDoc stehen nur Formeln)
1234 pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc );
1237 // skipped rows and merged cells don't mix
1238 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
1239 rDocFunc.UnmergeCells( aUserRange, false );
1241 pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, true ); // Refresh
1242 // und Bereich neu
1244 if ( pMixDoc ) // Rechenfunktionen mit Original-Daten auszufuehren ?
1246 pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc );
1248 delete pMixDoc;
1250 AdjustBlockHeight(); // update row heights before pasting objects
1252 ::std::vector< OUString > aExcludedChartNames;
1253 SdrPage* pPage = NULL;
1255 if ( nFlags & IDF_OBJECTS )
1257 ScDrawView* pScDrawView = GetScDrawView();
1258 SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL );
1259 pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL );
1260 if ( pPage )
1262 ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
1265 // Paste the drawing objects after the row heights have been updated.
1267 pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc,
1268 true, false, bIncludeFiltered );
1272 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1273 nEndCol, nEndRow, nEndTab ); // content after the change
1276 // ggf. Autofilter-Koepfe loeschen
1277 if (bCutMode)
1278 if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX,
1279 nClipStartY+nClipSizeY, nStartTab ))
1281 pDocSh->PostPaint(
1282 ScRange(nClipStartX, nClipStartY, nStartTab, nClipStartX+nClipSizeX, nClipStartY, nStartTab),
1283 PAINT_GRID );
1286 //! Block-Bereich bei RefUndoDoc weglassen !!!
1288 if ( bRecord )
1290 ScDocument* pRedoDoc = NULL;
1291 // Redo-Daten werden erst beim ersten Undo kopiert
1292 // ohne RefUndoDoc muss das Redo-Doc noch nicht angelegt werden
1294 if (pRefUndoDoc)
1296 pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
1297 pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo );
1299 // angepasste Referenzen ins Redo-Doc
1301 SCTAB nTabCount = pDoc->GetTableCount();
1302 pRedoDoc->AddUndoTab( 0, nTabCount-1 );
1303 pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc );
1305 // alte Referenzen ins Undo-Doc
1307 //! Tabellen selektieren ?
1308 pUndoDoc->AddUndoTab( 0, nTabCount-1 );
1309 pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL );
1310 pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
1311 IDF_FORMULA, false, pUndoDoc );
1312 delete pRefUndoDoc;
1315 // DeleteUnchanged for pUndoData is in ScUndoPaste ctor,
1316 // UndoData for redo is made during first undo
1318 ScUndoPasteOptions aOptions; // store options for repeat
1319 aOptions.nFunction = nFunction;
1320 aOptions.bSkipEmpty = bSkipEmpty;
1321 aOptions.bTranspose = bTranspose;
1322 aOptions.bAsLink = bAsLink;
1323 aOptions.eMoveMode = eMoveMode;
1325 SfxUndoAction* pUndo = new ScUndoPaste(
1326 pDocSh, ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1327 aFilteredMark, pUndoDoc, pRedoDoc, nFlags | nUndoFlags, pUndoData,
1328 false, &aOptions ); // false = Redo data not yet copied
1330 if ( bInsertCells )
1332 // Merge the paste undo action into the insert action.
1333 // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action.
1335 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1337 else
1338 pUndoMgr->AddUndoAction( pUndo );
1339 pUndoMgr->LeaveListAction();
1342 sal_uInt16 nPaint = PAINT_GRID;
1343 if (bColInfo)
1345 nPaint |= PAINT_TOP;
1346 nUndoEndCol = MAXCOL; // nur zum Zeichnen !
1348 if (bRowInfo)
1350 nPaint |= PAINT_LEFT;
1351 nUndoEndRow = MAXROW; // nur zum Zeichnen !
1353 pDocSh->PostPaint(
1354 ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1355 nPaint, nExtFlags);
1356 // AdjustBlockHeight has already been called above
1358 aModificator.SetDocumentModified();
1359 PostPasteFromClip(aUserRange, rMark);
1361 if ( nFlags & IDF_OBJECTS )
1363 ScModelObj* pModelObj = ( pDocSh ? ScModelObj::getImplementation( pDocSh->GetModel() ) : NULL );
1364 if ( pDoc && pPage && pModelObj )
1366 bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() );
1367 const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector );
1368 ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab,
1369 rProtectedChartRangesVector, aExcludedChartNames, bSameDoc );
1373 return true;
1376 bool ScViewFunc::PasteMultiRangesFromClip(
1377 sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1378 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1379 InsCellCmd eMoveMode, sal_uInt16 nUndoFlags)
1381 ScViewData& rViewData = *GetViewData();
1382 ScDocument* pDoc = rViewData.GetDocument();
1383 ScDocShell* pDocSh = rViewData.GetDocShell();
1384 ScMarkData aMark(rViewData.GetMarkData());
1385 const ScAddress& rCurPos = rViewData.GetCurPos();
1386 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1387 SCCOL nColSize = rClipParam.getPasteColSize();
1388 SCROW nRowSize = rClipParam.getPasteRowSize();
1390 if (bTranspose)
1392 if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
1394 ErrorMessage(STR_PASTE_FULL);
1395 return false;
1398 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1399 ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
1400 SAL_WNODEPRECATED_DECLARATIONS_POP
1401 pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
1402 pClipDoc = pTransClip.release();
1403 SCCOL nTempColSize = nColSize;
1404 nColSize = static_cast<SCCOL>(nRowSize);
1405 nRowSize = static_cast<SCROW>(nTempColSize);
1408 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1410 ErrorMessage(STR_PASTE_FULL);
1411 return false;
1414 // Determine the first and last selected sheet numbers.
1415 SCTAB nTab1 = aMark.GetFirstSelected();
1416 SCTAB nTab2 = aMark.GetLastSelected();
1418 ScDocShellModificator aModificator(*pDocSh);
1420 // For multi-selection paste, we don't support cell duplication for larger
1421 // destination range. In case the destination is marked, we reset it to
1422 // the clip size.
1423 ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
1424 rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
1426 // Extend the marked range to account for filtered rows in the destination
1427 // area.
1428 if (ScViewUtil::HasFiltered(aMarkedRange, pDoc))
1430 if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize))
1431 return false;
1434 bool bAskIfNotEmpty =
1435 bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1436 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1438 if (bAskIfNotEmpty)
1440 ScRangeList aTestRanges;
1441 aTestRanges.Append(aMarkedRange);
1442 if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aMark, rViewData.GetDialogParent()))
1443 return false;
1446 aMark.SetMarkArea(aMarkedRange);
1447 MarkRange(aMarkedRange);
1449 bool bInsertCells = (eMoveMode != INS_NONE);
1450 if (bInsertCells)
1452 if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
1453 return false;
1456 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1457 ::std::auto_ptr<ScDocument> pUndoDoc;
1458 SAL_WNODEPRECATED_DECLARATIONS_POP
1459 if (pDoc->IsUndoEnabled())
1461 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1462 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1463 pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1466 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1467 ::std::auto_ptr<ScDocument> pMixDoc;
1468 SAL_WNODEPRECATED_DECLARATIONS_POP
1469 if ( bSkipEmpty || nFunction )
1471 if ( nFlags & IDF_CONTENTS )
1473 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1474 pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1475 pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1479 /* Make draw layer and start drawing undo.
1480 - Needed before AdjustBlockHeight to track moved drawing objects.
1481 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1483 if (nFlags & IDF_OBJECTS)
1484 pDocSh->MakeDrawLayer();
1485 if (pDoc->IsUndoEnabled())
1486 pDoc->BeginDrawUndo();
1488 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1489 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
1490 true, bAsLink, false, bSkipEmpty);
1492 if (pMixDoc.get())
1493 pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
1495 AdjustBlockHeight(); // update row heights before pasting objects
1497 if (nFlags & IDF_OBJECTS)
1499 // Paste the drawing objects after the row heights have been updated.
1500 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
1501 true, false, false, true);
1504 ScRange aTmp = aMarkedRange;
1505 aTmp.aStart.SetTab(nTab1);
1506 aTmp.aEnd.SetTab(nTab1);
1507 pDocSh->PostPaint(aTmp, PAINT_GRID);
1509 if (pDoc->IsUndoEnabled())
1511 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1512 String aUndo = ScGlobal::GetRscString(
1513 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1514 pUndoMgr->EnterListAction(aUndo, aUndo);
1516 ScUndoPasteOptions aOptions; // store options for repeat
1517 aOptions.nFunction = nFunction;
1518 aOptions.bSkipEmpty = bSkipEmpty;
1519 aOptions.bTranspose = bTranspose;
1520 aOptions.bAsLink = bAsLink;
1521 aOptions.eMoveMode = eMoveMode;
1523 ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
1524 aMarkedRange, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1526 if (bInsertCells)
1527 pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
1528 else
1529 pUndoMgr->AddUndoAction(pUndo, false);
1531 pUndoMgr->LeaveListAction();
1533 aModificator.SetDocumentModified();
1534 PostPasteFromClip(aMarkedRange, aMark);
1535 return true;
1538 bool ScViewFunc::PasteFromClipToMultiRanges(
1539 sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1540 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1541 InsCellCmd eMoveMode, sal_uInt16 nUndoFlags )
1543 if (bTranspose)
1545 // We don't allow transpose for this yet.
1546 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1547 return false;
1550 if (eMoveMode != INS_NONE)
1552 // We don't allow insertion mode either. Too complicated.
1553 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1554 return false;
1557 ScViewData& rViewData = *GetViewData();
1558 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1559 if (rClipParam.mbCutMode)
1561 // No cut and paste with this, please.
1562 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1563 return false;
1566 const ScAddress& rCurPos = rViewData.GetCurPos();
1567 ScDocument* pDoc = rViewData.GetDocument();
1569 ScRange aSrcRange = rClipParam.getWholeRange();
1570 SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
1571 SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
1573 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1575 ErrorMessage(STR_PASTE_FULL);
1576 return false;
1579 ScMarkData aMark(rViewData.GetMarkData());
1581 ScRangeList aRanges;
1582 aMark.MarkToSimple();
1583 aMark.FillRangeListWithMarks(&aRanges, false);
1584 if (!ScClipUtil::CheckDestRanges(pDoc, nColSize, nRowSize, aMark, aRanges))
1586 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1587 return false;
1590 ScDocShell* pDocSh = rViewData.GetDocShell();
1592 ScDocShellModificator aModificator(*pDocSh);
1594 bool bAskIfNotEmpty =
1595 bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1596 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1598 if (bAskIfNotEmpty)
1600 if (!checkDestRangeForOverwrite(aRanges, pDoc, aMark, rViewData.GetDialogParent()))
1601 return false;
1604 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1605 std::auto_ptr<ScDocument> pUndoDoc;
1606 SAL_WNODEPRECATED_DECLARATIONS_POP
1607 if (pDoc->IsUndoEnabled())
1609 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1610 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1611 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1613 pDoc->CopyToDocument(
1614 *aRanges[i], nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1618 boost::scoped_ptr<ScDocument> pMixDoc;
1619 if (bSkipEmpty || nFunction)
1621 if (nFlags & IDF_CONTENTS)
1623 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1624 pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1625 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1627 pDoc->CopyToDocument(
1628 *aRanges[i], IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1633 if (nFlags & IDF_OBJECTS)
1634 pDocSh->MakeDrawLayer();
1635 if (pDoc->IsUndoEnabled())
1636 pDoc->BeginDrawUndo();
1638 // First, paste everything but the drawing objects.
1639 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1641 pDoc->CopyFromClip(
1642 *aRanges[i], aMark, (nFlags & ~IDF_OBJECTS), NULL, pClipDoc,
1643 false, false, true, bSkipEmpty, NULL);
1646 if (pMixDoc.get())
1648 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1649 pDoc->MixDocument(*aRanges[i], nFunction, bSkipEmpty, pMixDoc.get());
1652 AdjustBlockHeight(); // update row heights before pasting objects
1654 // Then paste the objects.
1655 if (nFlags & IDF_OBJECTS)
1657 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1659 pDoc->CopyFromClip(
1660 *aRanges[i], aMark, IDF_OBJECTS, NULL, pClipDoc,
1661 false, false, true, bSkipEmpty, NULL);
1665 // Refresh the range that includes all pasted ranges. We only need to
1666 // refresh the current sheet.
1667 pDocSh->PostPaint(aRanges, PAINT_GRID);
1669 if (pDoc->IsUndoEnabled())
1671 svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1672 String aUndo = ScGlobal::GetRscString(
1673 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1674 pUndoMgr->EnterListAction(aUndo, aUndo);
1676 ScUndoPasteOptions aOptions; // store options for repeat
1677 aOptions.nFunction = nFunction;
1678 aOptions.bSkipEmpty = bSkipEmpty;
1679 aOptions.bTranspose = bTranspose;
1680 aOptions.bAsLink = bAsLink;
1681 aOptions.eMoveMode = eMoveMode;
1683 ScUndoPaste* pUndo = new ScUndoPaste(
1684 pDocSh, aRanges, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1686 pUndoMgr->AddUndoAction(pUndo, false);
1687 pUndoMgr->LeaveListAction();
1689 aModificator.SetDocumentModified();
1690 PostPasteFromClip(aRanges, aMark);
1692 return false;
1695 void ScViewFunc::PostPasteFromClip(const ScRangeList& rPasteRanges, const ScMarkData& rMark)
1697 ScViewData* pViewData = GetViewData();
1698 ScDocShell* pDocSh = pViewData->GetDocShell();
1699 pDocSh->UpdateOle(pViewData);
1701 SelectionChanged();
1703 // #i97876# Spreadsheet data changes are not notified
1704 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1705 if (!pModelObj || !pModelObj->HasChangesListeners())
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 pModelObj->NotifyChanges( OUString( "cell-change" ), 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 String 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();
1812 return bSuccess;
1815 // Link innerhalb des Dokuments
1817 sal_Bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, sal_Bool bApi )
1819 // Test auf Ueberlappung
1821 if ( rSource.aStart.Tab() == rDestPos.Tab() )
1823 SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() );
1824 SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() );
1826 if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() &&
1827 rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() )
1829 if (!bApi)
1830 ErrorMessage( STR_ERR_LINKOVERLAP );
1831 return false;
1835 // Ausfuehren per Paste
1837 ScDocument* pDoc = GetViewData()->GetDocument();
1838 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
1839 pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(),
1840 rSource.aEnd.Col(), rSource.aEnd.Row(),
1841 rSource.aStart.Tab(), pClipDoc );
1843 // Zielbereich markieren (Cursor setzen, keine Markierung)
1845 if ( GetViewData()->GetTabNo() != rDestPos.Tab() )
1846 SetTabNo( rDestPos.Tab() );
1848 MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, false, false );
1850 // Paste
1852 PasteFromClip( IDF_ALL, pClipDoc, PASTE_NOFUNC, false, false, sal_True ); // als Link
1854 delete pClipDoc;
1856 return sal_True;
1859 void ScViewFunc::DataFormPutData( SCROW nCurrentRow ,
1860 SCROW nStartRow , SCCOL nStartCol ,
1861 SCROW nEndRow , SCCOL nEndCol ,
1862 boost::ptr_vector<boost::nullable<Edit> >& aEdits,
1863 sal_uInt16 aColLength )
1865 ScDocument* pDoc = GetViewData()->GetDocument();
1866 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1867 ScMarkData& rMark = GetViewData()->GetMarkData();
1868 ScDocShellModificator aModificator( *pDocSh );
1869 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1870 if ( pDoc )
1872 const sal_Bool bRecord( pDoc->IsUndoEnabled());
1873 ScDocument* pUndoDoc = NULL;
1874 ScDocument* pRedoDoc = NULL;
1875 ScRefUndoData* pUndoData = NULL;
1876 SCTAB nTab = GetViewData()->GetTabNo();
1877 SCTAB nStartTab = nTab;
1878 SCTAB nEndTab = nTab;
1881 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1882 if ( pChangeTrack )
1883 pChangeTrack->ResetLastCut(); // kein CutMode mehr
1885 ScRange aUserRange( nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab );
1886 sal_Bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1887 sal_Bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1888 SCCOL nUndoEndCol = nStartCol+aColLength-1;
1889 SCROW nUndoEndRow = nCurrentRow;
1890 sal_uInt16 nUndoFlags = IDF_NONE;
1892 if ( bRecord )
1894 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1895 pUndoDoc->InitUndoSelected( pDoc , rMark , bColInfo , bRowInfo );
1896 pDoc->CopyToDocument( aUserRange , 1 , false , pUndoDoc );
1898 sal_uInt16 nExtFlags = 0;
1899 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab , nEndCol, nEndRow, nEndTab ); // content before the change
1900 pDoc->BeginDrawUndo();
1902 for(sal_uInt16 i = 0; i < aColLength; i++)
1904 if (!aEdits.is_null(i))
1906 String aFieldName=aEdits[i].GetText();
1907 pDoc->SetString( nStartCol + i, nCurrentRow, nTab, aFieldName );
1910 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab ); // content after the change
1911 SfxUndoAction* pUndo = new ScUndoDataForm( pDocSh,
1912 nStartCol, nCurrentRow, nStartTab,
1913 nUndoEndCol, nUndoEndRow, nEndTab, rMark,
1914 pUndoDoc, pRedoDoc, nUndoFlags,
1915 pUndoData, NULL, NULL, NULL,
1916 false ); // FALSE = Redo data not yet copied
1917 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1919 sal_uInt16 nPaint = PAINT_GRID;
1920 if (bColInfo)
1922 nPaint |= PAINT_TOP;
1923 nUndoEndCol = MAXCOL; // nur zum Zeichnen !
1925 if (bRowInfo)
1927 nPaint |= PAINT_LEFT;
1928 nUndoEndRow = MAXROW; // nur zum Zeichnen !
1931 pDocSh->PostPaint(
1932 ScRange(nStartCol, nCurrentRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1933 nPaint, nExtFlags);
1934 pDocSh->UpdateOle(GetViewData());
1939 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */