Bump version to 4.3-4
[LibreOffice.git] / sc / source / ui / view / viewfun3.cxx
blobdc05c142c02dd4b4fa33b8aa9d34ed88e39e3f86
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"
68 #include <gridwin.hxx>
69 #include <boost/scoped_ptr.hpp>
71 using namespace com::sun::star;
73 // STATIC DATA ---------------------------------------------------------------
76 // GlobalName der Writer-DocShell kommt jetzt aus comphelper/classids.hxx
79 // C U T
81 void ScViewFunc::CutToClip( ScDocument* pClipDoc, 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 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, true, false, bIncludeObjects ); // Ab ins Clipboard
112 ScAddress aOldEnd( aRange.aEnd ); // Zusammengefasste Zellen im Bereich?
113 pDoc->ExtendMerge( aRange, 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 );
153 // C O P Y
155 bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, bool bCut, bool bApi, bool bIncludeObjects, bool bStopEdit )
157 ScRange aRange;
158 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange );
159 ScMarkData& rMark = GetViewData()->GetMarkData();
160 bool bDone = false;
162 if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
164 ScRangeList aRangeList;
165 aRangeList.Append( aRange );
166 bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, false );
168 else if (eMarkType == SC_MARK_MULTI)
170 ScRangeList aRangeList;
171 rMark.MarkToSimple();
172 rMark.FillRangeListWithMarks(&aRangeList, false);
173 bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, false );
175 else
177 if (!bApi)
178 ErrorMessage(STR_NOMULTISELECT);
181 return bDone;
184 // Copy the content of the Range into clipboard.
185 bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRangeList& rRanges, bool bCut, bool bApi, bool bIncludeObjects, bool bStopEdit, bool bUseRangeForVBA )
187 if ( rRanges.empty() )
188 return false;
189 bool bDone = false;
190 if ( bStopEdit )
191 UpdateInputLine();
193 ScRange aRange = *rRanges[0];
194 ScClipParam aClipParam( aRange, bCut );
195 aClipParam.maRanges = rRanges;
197 ScDocument* pDoc = GetViewData()->GetDocument();
198 ScMarkData& rMark = GetViewData()->GetMarkData();
200 if ( !aClipParam.isMultiRange() )
202 if ( pDoc && ( !pDoc->HasSelectedBlockMatrixFragment( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), rMark ) ) )
204 bool bSysClip = false;
205 if ( !pClipDoc ) // no clip doc specified
207 // Create one (deleted by ScTransferObj).
208 pClipDoc = new ScDocument( SCDOCMODE_CLIP );
209 bSysClip = true; // and copy into system
211 if ( !bCut )
213 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
214 if ( pChangeTrack )
215 pChangeTrack->ResetLastCut();
218 if ( bSysClip && bIncludeObjects )
220 bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange );
221 // Update ScGlobal::pDrawClipDocShellRef.
222 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
225 if ( !bUseRangeForVBA )
226 // is this necessary?, will setting the doc id upset the
227 // following paste operation with range? would be nicer to just set this always
228 // and lose the 'if' above
229 aClipParam.setSourceDocID( pDoc->GetDocumentID() );
231 pDoc->CopyToClip( aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
232 if ( !bUseRangeForVBA && pDoc && pClipDoc )
234 ScDrawLayer* pDrawLayer = pClipDoc->GetDrawLayer();
235 if ( pDrawLayer )
237 ScClipParam& rClipParam = pClipDoc->GetClipParam();
238 ScRangeListVector& rRangesVector = rClipParam.maProtectedChartRangesVector;
239 SCTAB nTabCount = pClipDoc->GetTableCount();
240 for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab )
242 SdrPage* pPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
243 if ( pPage )
245 ScChartHelper::FillProtectedChartRangesVector( rRangesVector, pDoc, pPage );
251 if ( bSysClip )
253 ScDrawLayer::SetGlobalDrawPersist(NULL);
254 ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) );
256 pClipDoc->ExtendMerge( aRange, true );
258 if ( bSysClip )
260 ScDocShell* pDocSh = GetViewData()->GetDocShell();
261 TransferableObjectDescriptor aObjDesc;
262 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
263 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
264 // maSize is set in ScTransferObj ctor
266 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
267 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
268 if ( ScGlobal::pDrawClipDocShellRef )
270 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
271 pTransferObj->SetDrawPersist( aPersistRef );// keep persist for ole objects alive
274 pTransferObj->CopyToClipboard( GetActiveWin() );
275 SC_MOD()->SetClipObject( pTransferObj, NULL );
278 bDone = true;
281 else
283 bool bSuccess = false;
284 aClipParam.mbCutMode = false;
288 if (bCut)
289 // We con't support cutting of multi-selections.
290 break;
292 if (pClipDoc)
293 // TODO: What's this for?
294 break;
296 SAL_WNODEPRECATED_DECLARATIONS_PUSH
297 ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
298 SAL_WNODEPRECATED_DECLARATIONS_POP
300 // Check for geometrical feasibility of the ranges.
301 bool bValidRanges = true;
302 ScRange* p = aClipParam.maRanges.front();
303 SCCOL nPrevColDelta = 0;
304 SCROW nPrevRowDelta = 0;
305 SCCOL nPrevCol = p->aStart.Col();
306 SCROW nPrevRow = p->aStart.Row();
307 SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
308 SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
309 for ( size_t i = 1; i < aClipParam.maRanges.size(); ++i )
311 p = aClipParam.maRanges[i];
312 if ( pDoc->HasSelectedBlockMatrixFragment(
313 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark) )
315 if (!bApi)
316 ErrorMessage(STR_MATRIXFRAGMENTERR);
317 return false;
320 SCCOL nColDelta = p->aStart.Col() - nPrevCol;
321 SCROW nRowDelta = p->aStart.Row() - nPrevRow;
323 if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
325 bValidRanges = false;
326 break;
329 if (aClipParam.meDirection == ScClipParam::Unspecified)
331 if (nColDelta)
332 aClipParam.meDirection = ScClipParam::Column;
333 if (nRowDelta)
334 aClipParam.meDirection = ScClipParam::Row;
337 SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
338 SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
340 if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
342 // column-oriented ranges must have identical row size.
343 bValidRanges = false;
344 break;
346 if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
348 // likewise, row-oriented ranges must have identical
349 // column size.
350 bValidRanges = false;
351 break;
354 nPrevCol = p->aStart.Col();
355 nPrevRow = p->aStart.Row();
356 nPrevColDelta = nColDelta;
357 nPrevRowDelta = nRowDelta;
358 nPrevColSize = nColSize;
359 nPrevRowSize = nRowSize;
361 if (!bValidRanges)
362 break;
363 pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
365 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
366 if ( pChangeTrack )
367 pChangeTrack->ResetLastCut(); // kein CutMode mehr
370 ScDocShell* pDocSh = GetViewData()->GetDocShell();
371 TransferableObjectDescriptor aObjDesc;
372 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
373 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
374 // maSize is set in ScTransferObj ctor
376 ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
377 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
379 if ( ScGlobal::pDrawClipDocShellRef )
381 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
382 pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
385 pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
386 SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
389 bSuccess = true;
391 while (false);
393 if (!bSuccess && !bApi)
394 ErrorMessage(STR_NOMULTISELECT);
396 bDone = bSuccess;
399 return bDone;
402 ScTransferObj* ScViewFunc::CopyToTransferable()
404 ScRange aRange;
405 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
407 ScDocument* pDoc = GetViewData()->GetDocument();
408 ScMarkData& rMark = GetViewData()->GetMarkData();
409 if ( !pDoc->HasSelectedBlockMatrixFragment(
410 aRange.aStart.Col(), aRange.aStart.Row(),
411 aRange.aEnd.Col(), aRange.aEnd.Row(),
412 rMark ) )
414 ScDocument *pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj)
416 bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
417 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
419 ScClipParam aClipParam(aRange, false);
420 pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true);
422 ScDrawLayer::SetGlobalDrawPersist(NULL);
423 pClipDoc->ExtendMerge( aRange, true );
425 ScDocShell* pDocSh = GetViewData()->GetDocShell();
426 TransferableObjectDescriptor aObjDesc;
427 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
428 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
429 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
430 return pTransferObj;
434 return NULL;
438 // P A S T E
440 void ScViewFunc::PasteDraw()
442 ScViewData* pViewData = GetViewData();
443 SCCOL nPosX = pViewData->GetCurX();
444 SCROW nPosY = pViewData->GetCurY();
445 Window* pWin = GetActiveWin();
446 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY,
447 pViewData->GetActivePart() ) );
448 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
449 if (pDrawClip)
451 OUString aSrcShellID = pDrawClip->GetShellID();
452 OUString aDestShellID = SfxObjectShell::CreateShellID(pViewData->GetDocShell());
453 PasteDraw(aPos, pDrawClip->GetModel(), false, aSrcShellID, aDestShellID);
457 void ScViewFunc::PasteFromSystem()
459 UpdateInputLine();
461 Window* pWin = GetActiveWin();
462 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
463 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
465 if (pOwnClip)
467 // keep a reference in case the clipboard is changed during PasteFromClip
468 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
469 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
470 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
471 true ); // allow warning dialog
473 else if (pDrawClip)
474 PasteDraw();
475 else
477 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
480 sal_uLong nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
481 sal_uLong nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
483 // als erstes SvDraw-Model, dann Grafik
484 // (Grafik darf nur bei einzelner Grafik drinstehen)
486 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
488 // special case for tables from drawing
489 if( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
491 PasteFromSystem( FORMAT_RTF );
493 else
495 PasteFromSystem( SOT_FORMATSTR_ID_DRAWING );
498 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
499 PasteFromSystem( SOT_FORMATSTR_ID_SVXB );
500 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
502 // If it's a Writer object, insert RTF instead of OLE
504 // Else, if the class id is all-zero, and SYLK is available,
505 // it probably is spreadsheet cells that have been put
506 // on the clipboard by OOo, so use the SYLK. (fdo#31077)
508 bool bDoRtf = false;
509 TransferableObjectDescriptor aObjDesc;
510 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
512 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
513 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
514 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
516 if ( bDoRtf )
517 PasteFromSystem( FORMAT_RTF );
518 else if ( aObjDesc.maClassName == SvGlobalName( 0,0,0,0,0,0,0,0,0,0,0 )
519 && aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ))
520 PasteFromSystem( SOT_FORMATSTR_ID_SYLK );
521 else
522 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE );
524 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
525 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE );
526 // the following format can not affect scenario from #89579#
527 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
528 PasteFromSystem( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE );
529 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
530 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
531 PasteFromSystem(nBiff8);
532 else if (aDataHelper.HasFormat(nBiff5))
533 PasteFromSystem(nBiff5);
534 else if (aDataHelper.HasFormat(FORMAT_RTF))
535 PasteFromSystem(FORMAT_RTF);
536 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
537 PasteFromSystem(SOT_FORMATSTR_ID_HTML);
538 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
539 PasteFromSystem(SOT_FORMATSTR_ID_HTML_SIMPLE);
540 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
541 PasteFromSystem(SOT_FORMATSTR_ID_SYLK);
542 else if (aDataHelper.HasFormat(FORMAT_STRING))
543 PasteFromSystem(FORMAT_STRING);
544 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
545 PasteFromSystem(FORMAT_GDIMETAFILE);
546 else if (aDataHelper.HasFormat(FORMAT_BITMAP))
547 PasteFromSystem(FORMAT_BITMAP);
548 // xxx_OLE formats come last, like in SotExchange tables
549 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
550 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE );
551 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
552 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE_OLE );
555 // keine Fehlermeldung, weil SID_PASTE in der idl das FastCall-Flag hat,
556 // also auch gerufen wird, wenn nichts im Clipboard steht (#42531#)
559 void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTransferable>& rxTransferable )
561 ScTransferObj *pOwnClip=0;
562 ScDrawTransferObj *pDrawClip=0;
563 uno::Reference<lang::XUnoTunnel> xTunnel( rxTransferable, uno::UNO_QUERY );
564 if ( xTunnel.is() )
566 sal_Int64 nHandle = xTunnel->getSomething( ScTransferObj::getUnoTunnelId() );
567 if ( nHandle )
568 pOwnClip = (ScTransferObj*) (sal_IntPtr) nHandle;
569 else
571 nHandle = xTunnel->getSomething( ScDrawTransferObj::getUnoTunnelId() );
572 if ( nHandle )
573 pDrawClip = (ScDrawTransferObj*) (sal_IntPtr) nHandle;
577 if (pOwnClip)
579 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
580 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
581 true ); // allow warning dialog
583 else if (pDrawClip)
585 ScViewData* pViewData = GetViewData();
586 SCCOL nPosX = pViewData->GetCurX();
587 SCROW nPosY = pViewData->GetCurY();
588 Window* pWin = GetActiveWin();
589 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY, pViewData->GetActivePart() ) );
590 PasteDraw(
591 aPos, pDrawClip->GetModel(), false,
592 pDrawClip->GetShellID(), SfxObjectShell::CreateShellID(pViewData->GetDocShell()));
594 else
596 TransferableDataHelper aDataHelper( rxTransferable );
598 sal_uLong nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
599 sal_uLong nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
600 sal_uLong nFormatId = 0;
601 // als erstes SvDraw-Model, dann Grafik
602 // (Grafik darf nur bei einzelner Grafik drinstehen)
604 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
605 nFormatId = SOT_FORMATSTR_ID_DRAWING;
606 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
607 nFormatId = SOT_FORMATSTR_ID_SVXB;
608 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
610 // If it's a Writer object, insert RTF instead of OLE
611 bool bDoRtf = false;
612 TransferableObjectDescriptor aObjDesc;
613 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
615 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
616 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
617 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
619 if ( bDoRtf )
620 nFormatId = FORMAT_RTF;
621 else
622 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
624 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
625 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
626 // the following format can not affect scenario from #89579#
627 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
628 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
629 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
630 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
631 nFormatId = nBiff8;
632 else if (aDataHelper.HasFormat(nBiff5))
633 nFormatId = nBiff5;
634 else if (aDataHelper.HasFormat(FORMAT_RTF))
635 nFormatId = FORMAT_RTF;
636 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
637 nFormatId = SOT_FORMATSTR_ID_HTML;
638 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
639 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
640 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
641 nFormatId = SOT_FORMATSTR_ID_SYLK;
642 else if (aDataHelper.HasFormat(FORMAT_STRING))
643 nFormatId = FORMAT_STRING;
644 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
645 nFormatId = FORMAT_GDIMETAFILE;
646 else if (aDataHelper.HasFormat(FORMAT_BITMAP))
647 nFormatId = FORMAT_BITMAP;
648 // xxx_OLE formats come last, like in SotExchange tables
649 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
650 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
651 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
652 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
653 else
654 return;
656 PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
657 GetViewData()->GetCurX(), GetViewData()->GetCurY(),
658 NULL, false, false );
663 bool ScViewFunc::PasteFromSystem( sal_uLong nFormatId, bool bApi )
665 UpdateInputLine();
667 bool bRet = true;
668 Window* pWin = GetActiveWin();
669 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
670 if ( nFormatId == 0 && pOwnClip )
672 // keep a reference in case the clipboard is changed during PasteFromClip
673 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
674 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
675 PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
676 !bApi ); // allow warning dialog
678 else
680 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
681 if ( !aDataHelper.GetTransferable().is() )
682 return false;
684 SCCOL nPosX = 0;
685 SCROW nPosY = 0;
687 ScViewData* pViewData = GetViewData();
688 ScRange aRange;
689 if ( pViewData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
691 nPosX = aRange.aStart.Col();
692 nPosY = aRange.aStart.Row();
694 else
696 nPosX = pViewData->GetCurX();
697 nPosY = pViewData->GetCurY();
700 bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
701 nPosX, nPosY,
702 NULL, false, !bApi ); // allow warning dialog
704 if ( !bRet && !bApi )
705 ErrorMessage(STR_PASTE_ERROR);
707 return bRet;
710 // P A S T E
712 bool ScViewFunc::PasteOnDrawObjectLinked(
713 const uno::Reference<datatransfer::XTransferable>& rxTransferable,
714 SdrObject& rHitObj)
716 TransferableDataHelper aDataHelper( rxTransferable );
718 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
720 SotStorageStreamRef xStm;
721 ScDrawView* pScDrawView = GetScDrawView();
723 if( pScDrawView && aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) )
725 Graphic aGraphic;
727 ReadGraphic( *xStm, aGraphic );
729 const OUString aEmpty;
730 const OUString aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
732 if(pScDrawView->ApplyGraphicToObject( rHitObj, aGraphic, aBeginUndo, aEmpty, aEmpty ))
734 return true;
738 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
740 GDIMetaFile aMtf;
741 ScDrawView* pScDrawView = GetScDrawView();
743 if( pScDrawView && aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) )
745 const OUString aEmpty;
746 const OUString aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
748 if(pScDrawView->ApplyGraphicToObject( rHitObj, Graphic(aMtf), aBeginUndo, aEmpty, aEmpty ))
750 return true;
754 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) || aDataHelper.HasFormat( SOT_FORMATSTR_ID_PNG ) )
756 BitmapEx aBmpEx;
757 ScDrawView* pScDrawView = GetScDrawView();
759 if( pScDrawView && aDataHelper.GetBitmapEx( FORMAT_BITMAP, aBmpEx ) )
761 const OUString aEmpty;
762 const OUString aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
764 if(pScDrawView->ApplyGraphicToObject( rHitObj, Graphic(aBmpEx), aBeginUndo, aEmpty, aEmpty ))
766 return true;
771 return false;
774 static bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
775 const ScMarkData& rTabSelection, sal_uInt16 nMask )
777 ScMarkData::const_iterator itr = rTabSelection.begin(), itrEnd = rTabSelection.end();
778 for (; itr != itrEnd; ++itr)
779 if ( pDoc->HasAttrib( nCol1, nRow1, *itr, nCol2, nRow2, *itr, nMask ) )
780 return true;
781 return false;
785 // Einfuegen auf Tabelle:
788 // internes Paste
790 namespace {
792 bool checkDestRangeForOverwrite(const ScRangeList& rDestRanges, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
794 bool bIsEmpty = true;
795 ScMarkData::const_iterator itrTab = rMark.begin(), itrTabEnd = rMark.end();
796 size_t nRangeSize = rDestRanges.size();
797 for (; itrTab != itrTabEnd && bIsEmpty; ++itrTab)
799 for (size_t i = 0; i < nRangeSize && bIsEmpty; ++i)
801 const ScRange& rRange = *rDestRanges[i];
802 bIsEmpty = pDoc->IsBlockEmpty(
803 *itrTab, rRange.aStart.Col(), rRange.aStart.Row(),
804 rRange.aEnd.Col(), rRange.aEnd.Row());
808 if (!bIsEmpty)
810 ScReplaceWarnBox aBox(pParentWnd);
811 if (aBox.Execute() != RET_YES)
813 // changing the configuration is within the ScReplaceWarnBox
814 return false;
817 return true;
822 bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
823 sal_uInt16 nFunction, bool bSkipEmpty,
824 bool bTranspose, bool bAsLink,
825 InsCellCmd eMoveMode, sal_uInt16 nUndoExtraFlags,
826 bool bAllowDialogs )
828 if (!pClipDoc)
830 OSL_FAIL("PasteFromClip: pClipDoc=0 not allowed");
831 return false;
834 // fuer Undo etc. immer alle oder keine Inhalte sichern
835 sal_uInt16 nContFlags = IDF_NONE;
836 if (nFlags & IDF_CONTENTS)
837 nContFlags |= IDF_CONTENTS;
838 if (nFlags & IDF_ATTRIB)
839 nContFlags |= IDF_ATTRIB;
840 // evtl. Attribute ins Undo ohne sie vom Clip ins Doc zu kopieren
841 sal_uInt16 nUndoFlags = nContFlags;
842 if (nUndoExtraFlags & IDF_ATTRIB)
843 nUndoFlags |= IDF_ATTRIB;
844 // do not copy note captions into undo document
845 nUndoFlags |= IDF_NOCAPTIONS;
847 ScClipParam& rClipParam = pClipDoc->GetClipParam();
848 if (rClipParam.isMultiRange())
850 // Source data is multi-range.
851 return PasteMultiRangesFromClip(
852 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
853 eMoveMode, nUndoFlags);
856 ScMarkData& rMark = GetViewData()->GetMarkData();
857 if (rMark.IsMultiMarked())
859 // Source data is single-range but destination is multi-range.
860 return PasteFromClipToMultiRanges(
861 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
862 eMoveMode, nUndoFlags);
865 bool bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
866 bool bIncludeFiltered = bCutMode;
868 // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions)
869 bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) );
871 ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip
872 ScDocument* pOrigClipDoc = NULL;
873 SAL_WNODEPRECATED_DECLARATIONS_PUSH
874 ::std::auto_ptr< ScDocument > xTransClip;
875 SAL_WNODEPRECATED_DECLARATIONS_POP
876 if ( bTranspose )
878 SCCOL nX;
879 SCROW nY;
880 // include filtered rows until TransposeClip can skip them
881 bIncludeFiltered = true;
882 pClipDoc->GetClipArea( nX, nY, true );
883 if ( nY > static_cast<sal_Int32>(MAXCOL) ) // zuviele Zeilen zum Transponieren
885 ErrorMessage(STR_PASTE_FULL);
886 return false;
888 pOrigClipDoc = pClipDoc; // fuer Referenzen
890 if ( bPasteDraw )
892 aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately
893 aTransShellRef->DoInitNew(NULL);
895 ScDrawLayer::SetGlobalDrawPersist(aTransShellRef);
897 xTransClip.reset( new ScDocument( SCDOCMODE_CLIP ));
898 pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink );
899 pClipDoc = xTransClip.get();
901 ScDrawLayer::SetGlobalDrawPersist(NULL);
904 SCCOL nStartCol;
905 SCROW nStartRow;
906 SCTAB nStartTab;
907 SCCOL nEndCol;
908 SCROW nEndRow;
909 SCTAB nEndTab;
910 SCCOL nClipSizeX;
911 SCROW nClipSizeY;
912 pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, true ); // size in clipboard doc
914 // size in target doc: include filtered rows only if CutMode is set
915 SCCOL nDestSizeX;
916 SCROW nDestSizeY;
917 pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered );
919 ScDocument* pDoc = GetViewData()->GetDocument();
920 ScDocShell* pDocSh = GetViewData()->GetDocShell();
921 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
922 const bool bRecord(pDoc->IsUndoEnabled());
924 ScDocShellModificator aModificator( *pDocSh );
926 ScRange aMarkRange;
927 ScMarkData aFilteredMark( rMark); // local copy for all modifications
928 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange, aFilteredMark);
929 bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED);
930 bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) ||
931 (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink)));
933 if (!bNoPaste)
935 if (!rMark.IsMarked())
937 // Create a selection with clipboard row count and check that for
938 // filtered.
939 nStartCol = GetViewData()->GetCurX();
940 nStartRow = GetViewData()->GetCurY();
941 nStartTab = GetViewData()->GetTabNo();
942 nEndCol = nStartCol + nDestSizeX;
943 nEndRow = nStartRow + nDestSizeY;
944 nEndTab = nStartTab;
945 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
946 if (ScViewUtil::HasFiltered( aMarkRange, pDoc))
948 bMarkIsFiltered = true;
949 // Fit to clipboard's row count unfiltered rows. If there is no
950 // fit assume that pasting is not possible. Note that nDestSizeY is
951 // size-1 (difference).
952 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
953 bNoPaste = true;
955 aFilteredMark.SetMarkArea( aMarkRange);
957 else
959 // Expand the marked area when the destination area is larger than the
960 // current selection, to get the undo do the right thing. (i#106711)
961 ScRange aRange;
962 aFilteredMark.GetMarkArea( aRange );
963 if( (aRange.aEnd.Col() - aRange.aStart.Col()) < nDestSizeX )
965 aRange.aEnd.SetCol(aRange.aStart.Col() + nDestSizeX);
966 aFilteredMark.SetMarkArea(aRange);
971 if (bNoPaste)
973 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
974 return false;
977 SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1;
978 ScRangeList aRangeList;
979 if (bMarkIsFiltered)
981 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
982 aFilteredMark.FillRangeListWithMarks( &aRangeList, false);
983 nUnfilteredRows = 0;
984 size_t ListSize = aRangeList.size();
985 for ( size_t i = 0; i < ListSize; ++i )
987 ScRange* p = aRangeList[i];
988 nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1;
990 #if 0
991 /* This isn't needed but could be a desired restriction. */
992 // For filtered, destination rows have to be an exact multiple of
993 // source rows. Note that nDestSizeY is size-1 (difference), so
994 // nDestSizeY==0 fits always.
995 if ((nUnfilteredRows % (nDestSizeY+1)) != 0)
997 /* FIXME: this should be a more descriptive error message then. */
998 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
999 return false;
1001 #endif
1004 // Also for a filtered selection the area is used, for undo et al.
1005 if ( aFilteredMark.IsMarked() || bMarkIsFiltered )
1007 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1008 SCCOL nBlockAddX = nEndCol-nStartCol;
1009 SCROW nBlockAddY = nEndRow-nStartRow;
1011 // Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner
1012 // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt)
1014 // ClipSize is not size, but difference
1015 if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) ||
1016 ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) ||
1017 ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) )
1019 ScWaitCursorOff aWaitOff( GetFrameWin() );
1020 OUString aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER );
1021 QueryBox aBox( GetViewData()->GetDialogParent(),
1022 WinBits(WB_YES_NO | WB_DEF_NO), aMessage );
1023 if ( aBox.Execute() != RET_YES )
1025 return false;
1029 if (nBlockAddX <= nDestSizeX)
1030 nEndCol = nStartCol + nDestSizeX;
1032 if (nBlockAddY <= nDestSizeY)
1034 nEndRow = nStartRow + nDestSizeY;
1035 if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row())
1037 // Same as above if nothing was marked: re-fit selection to
1038 // unfiltered rows. Extending the selection actually may
1039 // introduce filtered rows where there weren't any before, so
1040 // we also need to test for that.
1041 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1042 if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc))
1044 bMarkIsFiltered = true;
1045 // Worst case: all rows up to the end of the sheet are filtered.
1046 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
1048 ErrorMessage(STR_PASTE_FULL);
1049 return false;
1052 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1053 aFilteredMark.SetMarkArea( aMarkRange);
1054 if (bMarkIsFiltered)
1056 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1057 aFilteredMark.FillRangeListWithMarks( &aRangeList, true);
1062 else
1064 nStartCol = GetViewData()->GetCurX();
1065 nStartRow = GetViewData()->GetCurY();
1066 nStartTab = GetViewData()->GetTabNo();
1067 nEndCol = nStartCol + nDestSizeX;
1068 nEndRow = nStartRow + nDestSizeY;
1069 nEndTab = nStartTab;
1072 bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow);
1074 // Zielbereich, wie er angezeigt wird:
1075 ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1077 // Sollen Zellen eingefuegt werden?
1078 // (zu grosse nEndCol/nEndRow werden weiter unten erkannt)
1079 bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits );
1080 if ( bInsertCells )
1082 // Instead of EnterListAction, the paste undo action is merged into the
1083 // insert action, so Repeat can insert the right cells
1085 MarkRange( aUserRange ); // wird vor CopyFromClip sowieso gesetzt
1087 // CutMode is reset on insertion of cols/rows but needed again on cell move
1088 bool bCut = pClipDoc->IsCutMode();
1089 if (!InsertCells( eMoveMode, bRecord, true )) // is inserting possible?
1091 return false;
1092 // #i21036# EnterListAction isn't used, and InsertCells doesn't insert
1093 // its undo action on failure, so no undo handling is needed here
1095 if ( bCut )
1096 pClipDoc->SetCutMode( bCut );
1098 else if (!bOffLimits)
1100 bool bAskIfNotEmpty = bAllowDialogs &&
1101 ( nFlags & IDF_CONTENTS ) &&
1102 nFunction == PASTE_NOFUNC &&
1103 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1104 if ( bAskIfNotEmpty )
1106 ScRangeList aTestRanges;
1107 aTestRanges.Append(aUserRange);
1108 if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
1109 return false;
1113 SCCOL nClipStartX; // Clipboard-Bereich erweitern
1114 SCROW nClipStartY;
1115 pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1116 SCCOL nUndoEndCol = nClipStartX + nClipSizeX;
1117 SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document
1118 bool bClipOver = false;
1119 // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers.
1120 // The same end column/row can be used for all calls because the clip doc doesn't contain
1121 // content outside the clip area.
1122 for (SCTAB nClipTab=0; nClipTab < pClipDoc->GetTableCount(); nClipTab++)
1123 if ( pClipDoc->HasTable(nClipTab) )
1124 if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, false ) )
1125 bClipOver = true;
1126 nUndoEndCol -= nClipStartX + nClipSizeX;
1127 nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge
1128 nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol );
1129 nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells
1131 if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW)
1133 ErrorMessage(STR_PASTE_FULL);
1134 return false;
1137 pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, false );
1139 // Test auf Zellschutz
1141 ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow );
1142 if (!aTester.IsEditable())
1144 ErrorMessage(aTester.GetMessageId());
1145 return false;
1148 //! Test auf Ueberlappung
1149 //! nur wirkliche Schnittmenge testen !!!!!!!
1151 ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
1152 if ( bRecord )
1154 OUString aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY );
1155 pUndoMgr->EnterListAction( aUndo, aUndo );
1158 if (bClipOver)
1159 if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED ))
1160 { // "Cell merge not possible if cells already merged"
1161 ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow );
1162 const ScPatternAttr* pPattern = NULL;
1163 const ScMergeAttr* pMergeFlag = NULL;
1164 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1165 SCCOL nCol = -1;
1166 SCROW nRow1 = -1;
1167 SCROW nRow2 = -1;
1168 while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL )
1170 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1171 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1172 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) )
1174 ScRange aRange(nCol, nRow1, nStartTab);
1175 pDoc->ExtendOverlapped(aRange);
1176 pDoc->ExtendMerge(aRange, true);
1177 rDocFunc.UnmergeCells(aRange, bRecord);
1182 if ( !bCutMode )
1184 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1185 if ( pChangeTrack )
1186 pChangeTrack->ResetLastCut(); // kein CutMode mehr
1189 bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1190 bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1192 ScDocument* pUndoDoc = NULL;
1193 ScDocument* pRefUndoDoc = NULL;
1194 ScRefUndoData* pUndoData = NULL;
1196 if ( bRecord )
1198 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1199 pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo );
1201 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
1202 SCTAB nTabCount = pDoc->GetTableCount();
1203 pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1,
1204 nUndoFlags, false, pUndoDoc );
1206 if ( bCutMode )
1208 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1209 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
1211 pUndoData = new ScRefUndoData( pDoc );
1215 sal_uInt16 nExtFlags = 0;
1216 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1217 nEndCol, nEndRow, nEndTab ); // content before the change
1219 if (GetViewData()->IsActive())
1221 DoneBlockMode();
1222 InitOwnBlockMode();
1224 rMark.SetMarkArea( aUserRange );
1225 MarkDataChanged();
1228 // Aus Clipboard kopieren,
1229 // wenn gerechnet werden soll, Originaldaten merken
1232 boost::scoped_ptr<ScDocument> pMixDoc;
1233 if (nFunction)
1235 bSkipEmpty = false;
1236 if ( nFlags & IDF_CONTENTS )
1238 pMixDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1239 pMixDoc->InitUndo( pDoc, nStartTab, nEndTab );
1240 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1241 IDF_CONTENTS, false, pMixDoc.get() );
1245 /* Make draw layer and start drawing undo.
1246 - Needed before AdjustBlockHeight to track moved drawing objects.
1247 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1249 if ( bPasteDraw )
1250 pDocSh->MakeDrawLayer();
1251 if ( bRecord )
1252 pDoc->BeginDrawUndo();
1254 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1255 if (!bAsLink)
1257 // copy normally (original range)
1258 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags,
1259 pRefUndoDoc, pClipDoc, true, false, bIncludeFiltered,
1260 bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) );
1262 // bei Transpose Referenzen per Hand anpassen
1263 if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) )
1264 pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc );
1266 else if (!bTranspose)
1268 // copy with bAsLink=TRUE
1269 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc,
1270 true, true, bIncludeFiltered, bSkipEmpty );
1272 else
1274 // alle Inhalte kopieren (im TransClipDoc stehen nur Formeln)
1275 pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc );
1278 // skipped rows and merged cells don't mix
1279 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
1280 rDocFunc.UnmergeCells( aUserRange, false );
1282 pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, true ); // Refresh
1283 // und Bereich neu
1285 if ( pMixDoc ) // Rechenfunktionen mit Original-Daten auszufuehren ?
1287 pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc.get() );
1289 pMixDoc.reset();
1291 AdjustBlockHeight(); // update row heights before pasting objects
1293 ::std::vector< OUString > aExcludedChartNames;
1294 SdrPage* pPage = NULL;
1296 if ( nFlags & IDF_OBJECTS )
1298 ScDrawView* pScDrawView = GetScDrawView();
1299 SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL );
1300 pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL );
1301 if ( pPage )
1303 ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
1306 // Paste the drawing objects after the row heights have been updated.
1308 pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc,
1309 true, false, bIncludeFiltered );
1312 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1313 nEndCol, nEndRow, nEndTab ); // content after the change
1315 // ggf. Autofilter-Koepfe loeschen
1316 if (bCutMode)
1317 if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX,
1318 nClipStartY+nClipSizeY, nStartTab ))
1320 pDocSh->PostPaint(
1321 ScRange(nClipStartX, nClipStartY, nStartTab, nClipStartX+nClipSizeX, nClipStartY, nStartTab),
1322 PAINT_GRID );
1325 //! Block-Bereich bei RefUndoDoc weglassen !!!
1327 if ( bRecord )
1329 ScDocument* pRedoDoc = NULL;
1330 // Redo-Daten werden erst beim ersten Undo kopiert
1331 // ohne RefUndoDoc muss das Redo-Doc noch nicht angelegt werden
1333 if (pRefUndoDoc)
1335 pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
1336 pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo );
1338 // angepasste Referenzen ins Redo-Doc
1340 SCTAB nTabCount = pDoc->GetTableCount();
1341 pRedoDoc->AddUndoTab( 0, nTabCount-1 );
1342 pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc );
1344 // alte Referenzen ins Undo-Doc
1346 //! Tabellen selektieren ?
1347 pUndoDoc->AddUndoTab( 0, nTabCount-1 );
1348 pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL );
1349 pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
1350 IDF_FORMULA, false, pUndoDoc );
1351 delete pRefUndoDoc;
1354 // DeleteUnchanged for pUndoData is in ScUndoPaste ctor,
1355 // UndoData for redo is made during first undo
1357 ScUndoPasteOptions aOptions; // store options for repeat
1358 aOptions.nFunction = nFunction;
1359 aOptions.bSkipEmpty = bSkipEmpty;
1360 aOptions.bTranspose = bTranspose;
1361 aOptions.bAsLink = bAsLink;
1362 aOptions.eMoveMode = eMoveMode;
1364 SfxUndoAction* pUndo = new ScUndoPaste(
1365 pDocSh, ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1366 aFilteredMark, pUndoDoc, pRedoDoc, nFlags | nUndoFlags, pUndoData,
1367 false, &aOptions ); // false = Redo data not yet copied
1369 if ( bInsertCells )
1371 // Merge the paste undo action into the insert action.
1372 // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action.
1374 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1376 else
1377 pUndoMgr->AddUndoAction( pUndo );
1378 pUndoMgr->LeaveListAction();
1381 sal_uInt16 nPaint = PAINT_GRID;
1382 if (bColInfo)
1384 nPaint |= PAINT_TOP;
1385 nUndoEndCol = MAXCOL; // nur zum Zeichnen !
1387 if (bRowInfo)
1389 nPaint |= PAINT_LEFT;
1390 nUndoEndRow = MAXROW; // nur zum Zeichnen !
1392 pDocSh->PostPaint(
1393 ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1394 nPaint, nExtFlags);
1395 // AdjustBlockHeight has already been called above
1397 ResetAutoSpell();
1398 aModificator.SetDocumentModified();
1399 PostPasteFromClip(aUserRange, rMark);
1401 if ( nFlags & IDF_OBJECTS )
1403 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1404 if ( pPage && pModelObj )
1406 bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() );
1407 const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector );
1408 ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab,
1409 rProtectedChartRangesVector, aExcludedChartNames, bSameDoc );
1413 return true;
1416 bool ScViewFunc::PasteMultiRangesFromClip(
1417 sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1418 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1419 InsCellCmd eMoveMode, sal_uInt16 nUndoFlags)
1421 ScViewData& rViewData = *GetViewData();
1422 ScDocument* pDoc = rViewData.GetDocument();
1423 ScDocShell* pDocSh = rViewData.GetDocShell();
1424 ScMarkData aMark(rViewData.GetMarkData());
1425 const ScAddress& rCurPos = rViewData.GetCurPos();
1426 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1427 SCCOL nColSize = rClipParam.getPasteColSize();
1428 SCROW nRowSize = rClipParam.getPasteRowSize();
1430 if (bTranspose)
1432 if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
1434 ErrorMessage(STR_PASTE_FULL);
1435 return false;
1438 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1439 ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
1440 SAL_WNODEPRECATED_DECLARATIONS_POP
1441 pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
1442 pClipDoc = pTransClip.release();
1443 SCCOL nTempColSize = nColSize;
1444 nColSize = static_cast<SCCOL>(nRowSize);
1445 nRowSize = static_cast<SCROW>(nTempColSize);
1448 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1450 ErrorMessage(STR_PASTE_FULL);
1451 return false;
1454 // Determine the first and last selected sheet numbers.
1455 SCTAB nTab1 = aMark.GetFirstSelected();
1456 SCTAB nTab2 = aMark.GetLastSelected();
1458 ScDocShellModificator aModificator(*pDocSh);
1460 // For multi-selection paste, we don't support cell duplication for larger
1461 // destination range. In case the destination is marked, we reset it to
1462 // the clip size.
1463 ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
1464 rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
1466 // Extend the marked range to account for filtered rows in the destination
1467 // area.
1468 if (ScViewUtil::HasFiltered(aMarkedRange, pDoc))
1470 if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize))
1471 return false;
1474 bool bAskIfNotEmpty =
1475 bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1476 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1478 if (bAskIfNotEmpty)
1480 ScRangeList aTestRanges;
1481 aTestRanges.Append(aMarkedRange);
1482 if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aMark, rViewData.GetDialogParent()))
1483 return false;
1486 aMark.SetMarkArea(aMarkedRange);
1487 MarkRange(aMarkedRange);
1489 bool bInsertCells = (eMoveMode != INS_NONE);
1490 if (bInsertCells)
1492 if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
1493 return false;
1496 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1497 ::std::auto_ptr<ScDocument> pUndoDoc;
1498 SAL_WNODEPRECATED_DECLARATIONS_POP
1499 if (pDoc->IsUndoEnabled())
1501 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1502 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1503 pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1506 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1507 ::std::auto_ptr<ScDocument> pMixDoc;
1508 SAL_WNODEPRECATED_DECLARATIONS_POP
1509 if ( bSkipEmpty || nFunction )
1511 if ( nFlags & IDF_CONTENTS )
1513 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1514 pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1515 pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1519 /* Make draw layer and start drawing undo.
1520 - Needed before AdjustBlockHeight to track moved drawing objects.
1521 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1523 if (nFlags & IDF_OBJECTS)
1524 pDocSh->MakeDrawLayer();
1525 if (pDoc->IsUndoEnabled())
1526 pDoc->BeginDrawUndo();
1528 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1529 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
1530 true, bAsLink, false, bSkipEmpty);
1532 if (pMixDoc.get())
1533 pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
1535 AdjustBlockHeight(); // update row heights before pasting objects
1537 if (nFlags & IDF_OBJECTS)
1539 // Paste the drawing objects after the row heights have been updated.
1540 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
1541 true, false, false, true);
1544 ScRange aTmp = aMarkedRange;
1545 aTmp.aStart.SetTab(nTab1);
1546 aTmp.aEnd.SetTab(nTab1);
1547 pDocSh->PostPaint(aTmp, PAINT_GRID);
1549 if (pDoc->IsUndoEnabled())
1551 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1552 OUString aUndo = ScGlobal::GetRscString(
1553 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1554 pUndoMgr->EnterListAction(aUndo, aUndo);
1556 ScUndoPasteOptions aOptions; // store options for repeat
1557 aOptions.nFunction = nFunction;
1558 aOptions.bSkipEmpty = bSkipEmpty;
1559 aOptions.bTranspose = bTranspose;
1560 aOptions.bAsLink = bAsLink;
1561 aOptions.eMoveMode = eMoveMode;
1563 ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
1564 aMarkedRange, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1566 if (bInsertCells)
1567 pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
1568 else
1569 pUndoMgr->AddUndoAction(pUndo, false);
1571 pUndoMgr->LeaveListAction();
1574 ResetAutoSpell();
1575 aModificator.SetDocumentModified();
1576 PostPasteFromClip(aMarkedRange, aMark);
1577 return true;
1580 bool ScViewFunc::PasteFromClipToMultiRanges(
1581 sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1582 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1583 InsCellCmd eMoveMode, sal_uInt16 nUndoFlags )
1585 if (bTranspose)
1587 // We don't allow transpose for this yet.
1588 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1589 return false;
1592 if (eMoveMode != INS_NONE)
1594 // We don't allow insertion mode either. Too complicated.
1595 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1596 return false;
1599 ScViewData& rViewData = *GetViewData();
1600 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1601 if (rClipParam.mbCutMode)
1603 // No cut and paste with this, please.
1604 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1605 return false;
1608 const ScAddress& rCurPos = rViewData.GetCurPos();
1609 ScDocument* pDoc = rViewData.GetDocument();
1611 ScRange aSrcRange = rClipParam.getWholeRange();
1612 SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
1613 SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
1615 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1617 ErrorMessage(STR_PASTE_FULL);
1618 return false;
1621 ScMarkData aMark(rViewData.GetMarkData());
1623 ScRangeList aRanges;
1624 aMark.MarkToSimple();
1625 aMark.FillRangeListWithMarks(&aRanges, false);
1626 if (!ScClipUtil::CheckDestRanges(pDoc, nColSize, nRowSize, aMark, aRanges))
1628 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1629 return false;
1632 ScDocShell* pDocSh = rViewData.GetDocShell();
1634 ScDocShellModificator aModificator(*pDocSh);
1636 bool bAskIfNotEmpty =
1637 bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1638 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1640 if (bAskIfNotEmpty)
1642 if (!checkDestRangeForOverwrite(aRanges, pDoc, aMark, rViewData.GetDialogParent()))
1643 return false;
1646 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1647 std::auto_ptr<ScDocument> pUndoDoc;
1648 SAL_WNODEPRECATED_DECLARATIONS_POP
1649 if (pDoc->IsUndoEnabled())
1651 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1652 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1653 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1655 pDoc->CopyToDocument(
1656 *aRanges[i], nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1660 boost::scoped_ptr<ScDocument> pMixDoc;
1661 if (bSkipEmpty || nFunction)
1663 if (nFlags & IDF_CONTENTS)
1665 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1666 pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1667 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1669 pDoc->CopyToDocument(
1670 *aRanges[i], IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1675 if (nFlags & IDF_OBJECTS)
1676 pDocSh->MakeDrawLayer();
1677 if (pDoc->IsUndoEnabled())
1678 pDoc->BeginDrawUndo();
1680 // First, paste everything but the drawing objects.
1681 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1683 pDoc->CopyFromClip(
1684 *aRanges[i], aMark, (nFlags & ~IDF_OBJECTS), NULL, pClipDoc,
1685 false, false, true, bSkipEmpty, NULL);
1688 if (pMixDoc.get())
1690 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1691 pDoc->MixDocument(*aRanges[i], nFunction, bSkipEmpty, pMixDoc.get());
1694 AdjustBlockHeight(); // update row heights before pasting objects
1696 // Then paste the objects.
1697 if (nFlags & IDF_OBJECTS)
1699 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1701 pDoc->CopyFromClip(
1702 *aRanges[i], aMark, IDF_OBJECTS, NULL, pClipDoc,
1703 false, false, true, bSkipEmpty, NULL);
1707 // Refresh the range that includes all pasted ranges. We only need to
1708 // refresh the current sheet.
1709 pDocSh->PostPaint(aRanges, PAINT_GRID);
1711 if (pDoc->IsUndoEnabled())
1713 svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1714 OUString aUndo = ScGlobal::GetRscString(
1715 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1716 pUndoMgr->EnterListAction(aUndo, aUndo);
1718 ScUndoPasteOptions aOptions; // store options for repeat
1719 aOptions.nFunction = nFunction;
1720 aOptions.bSkipEmpty = bSkipEmpty;
1721 aOptions.bTranspose = bTranspose;
1722 aOptions.bAsLink = bAsLink;
1723 aOptions.eMoveMode = eMoveMode;
1725 ScUndoPaste* pUndo = new ScUndoPaste(
1726 pDocSh, aRanges, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1728 pUndoMgr->AddUndoAction(pUndo, false);
1729 pUndoMgr->LeaveListAction();
1732 ResetAutoSpell();
1733 aModificator.SetDocumentModified();
1734 PostPasteFromClip(aRanges, aMark);
1736 return false;
1739 void ScViewFunc::PostPasteFromClip(const ScRangeList& rPasteRanges, const ScMarkData& rMark)
1741 ScViewData* pViewData = GetViewData();
1742 ScDocShell* pDocSh = pViewData->GetDocShell();
1743 pDocSh->UpdateOle(pViewData);
1745 SelectionChanged();
1747 ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
1748 if (!pModelObj)
1749 return;
1751 ScRangeList aChangeRanges;
1752 for (size_t i = 0, n = rPasteRanges.size(); i < n; ++i)
1754 const ScRange& r = *rPasteRanges[i];
1755 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1756 for (; itr != itrEnd; ++itr)
1758 ScRange aChangeRange(r);
1759 aChangeRange.aStart.SetTab(*itr);
1760 aChangeRange.aEnd.SetTab(*itr);
1761 aChangeRanges.Append(aChangeRange);
1764 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
1767 // D R A G A N D D R O P
1769 // innerhalb des Dokuments
1771 bool ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos,
1772 bool bCut, bool bRecord, bool bPaint, bool bApi )
1774 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1775 HideAllCursors(); // wegen zusammengefassten
1777 bool bSuccess = true;
1778 SCTAB nDestTab = rDestPos.Tab();
1779 const ScMarkData& rMark = GetViewData()->GetMarkData();
1780 if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 )
1782 // moving within one table and several tables selected -> apply to all selected tables
1784 if ( bRecord )
1786 OUString aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY );
1787 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
1790 // collect ranges of consecutive selected tables
1792 ScRange aLocalSource = rSource;
1793 ScAddress aLocalDest = rDestPos;
1794 SCTAB nTabCount = pDocSh->GetDocument()->GetTableCount();
1795 SCTAB nStartTab = 0;
1796 while ( nStartTab < nTabCount && bSuccess )
1798 while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) )
1799 ++nStartTab;
1800 if ( nStartTab < nTabCount )
1802 SCTAB nEndTab = nStartTab;
1803 while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) )
1804 ++nEndTab;
1806 aLocalSource.aStart.SetTab( nStartTab );
1807 aLocalSource.aEnd.SetTab( nEndTab );
1808 aLocalDest.SetTab( nStartTab );
1810 bSuccess = pDocSh->GetDocFunc().MoveBlock(
1811 aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi );
1813 nStartTab = nEndTab + 1;
1817 if ( bRecord )
1818 pDocSh->GetUndoManager()->LeaveListAction();
1820 else
1822 // move the block as specified
1823 bSuccess = pDocSh->GetDocFunc().MoveBlock(
1824 rSource, rDestPos, bCut, bRecord, bPaint, bApi );
1827 ShowAllCursors();
1828 if (bSuccess)
1830 // Zielbereich markieren
1831 ScAddress aDestEnd(
1832 rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(),
1833 rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(),
1834 nDestTab );
1836 bool bIncludeFiltered = bCut;
1837 if ( !bIncludeFiltered )
1839 // find number of non-filtered rows
1840 SCROW nPastedCount = pDocSh->GetDocument()->CountNonFilteredRows(
1841 rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab());
1843 if ( nPastedCount == 0 )
1844 nPastedCount = 1;
1845 aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 );
1848 MarkRange( ScRange( rDestPos, aDestEnd ), false ); //! sal_False ???
1850 pDocSh->UpdateOle(GetViewData());
1851 SelectionChanged();
1852 ResetAutoSpell();
1854 return bSuccess;
1857 // Link innerhalb des Dokuments
1859 bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, bool bApi )
1861 // Test auf Ueberlappung
1863 if ( rSource.aStart.Tab() == rDestPos.Tab() )
1865 SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() );
1866 SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() );
1868 if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() &&
1869 rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() )
1871 if (!bApi)
1872 ErrorMessage( STR_ERR_LINKOVERLAP );
1873 return false;
1877 // Ausfuehren per Paste
1879 ScDocument* pDoc = GetViewData()->GetDocument();
1880 boost::scoped_ptr<ScDocument> pClipDoc(new ScDocument( SCDOCMODE_CLIP ));
1881 pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(),
1882 rSource.aEnd.Col(), rSource.aEnd.Row(),
1883 rSource.aStart.Tab(), pClipDoc.get() );
1885 // Zielbereich markieren (Cursor setzen, keine Markierung)
1887 if ( GetViewData()->GetTabNo() != rDestPos.Tab() )
1888 SetTabNo( rDestPos.Tab() );
1890 MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, false, false );
1892 // Paste
1894 PasteFromClip( IDF_ALL, pClipDoc.get(), PASTE_NOFUNC, false, false, true ); // als Link
1896 return true;
1899 void ScViewFunc::DataFormPutData( SCROW nCurrentRow ,
1900 SCROW nStartRow , SCCOL nStartCol ,
1901 SCROW nEndRow , SCCOL nEndCol ,
1902 boost::ptr_vector<boost::nullable<Edit> >& aEdits,
1903 sal_uInt16 aColLength )
1905 ScDocument* pDoc = GetViewData()->GetDocument();
1906 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1907 ScMarkData& rMark = GetViewData()->GetMarkData();
1908 ScDocShellModificator aModificator( *pDocSh );
1909 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1910 if ( pDoc )
1912 const bool bRecord( pDoc->IsUndoEnabled());
1913 ScDocument* pUndoDoc = NULL;
1914 ScDocument* pRedoDoc = NULL;
1915 ScRefUndoData* pUndoData = NULL;
1916 SCTAB nTab = GetViewData()->GetTabNo();
1917 SCTAB nStartTab = nTab;
1918 SCTAB nEndTab = nTab;
1921 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1922 if ( pChangeTrack )
1923 pChangeTrack->ResetLastCut(); // kein CutMode mehr
1925 ScRange aUserRange( nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab );
1926 bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1927 bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1928 SCCOL nUndoEndCol = nStartCol+aColLength-1;
1929 SCROW nUndoEndRow = nCurrentRow;
1930 sal_uInt16 nUndoFlags = IDF_NONE;
1932 if ( bRecord )
1934 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1935 pUndoDoc->InitUndoSelected( pDoc , rMark , bColInfo , bRowInfo );
1936 pDoc->CopyToDocument( aUserRange , 1 , false , pUndoDoc );
1938 sal_uInt16 nExtFlags = 0;
1939 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab , nEndCol, nEndRow, nEndTab ); // content before the change
1940 pDoc->BeginDrawUndo();
1942 for(sal_uInt16 i = 0; i < aColLength; i++)
1944 if (!aEdits.is_null(i))
1946 OUString aFieldName=aEdits[i].GetText();
1947 pDoc->SetString( nStartCol + i, nCurrentRow, nTab, aFieldName );
1950 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab ); // content after the change
1951 SfxUndoAction* pUndo = new ScUndoDataForm( pDocSh,
1952 nStartCol, nCurrentRow, nStartTab,
1953 nUndoEndCol, nUndoEndRow, nEndTab, rMark,
1954 pUndoDoc, pRedoDoc, nUndoFlags,
1955 pUndoData, NULL, NULL, NULL,
1956 false ); // FALSE = Redo data not yet copied
1957 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1959 sal_uInt16 nPaint = PAINT_GRID;
1960 if (bColInfo)
1962 nPaint |= PAINT_TOP;
1963 nUndoEndCol = MAXCOL; // nur zum Zeichnen !
1965 if (bRowInfo)
1967 nPaint |= PAINT_LEFT;
1968 nUndoEndRow = MAXROW; // nur zum Zeichnen !
1971 pDocSh->PostPaint(
1972 ScRange(nStartCol, nCurrentRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1973 nPaint, nExtFlags);
1974 pDocSh->UpdateOle(GetViewData());
1979 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */