1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/svdpage.hxx>
22 #include <sfx2/docfile.hxx>
23 #include <comphelper/classids.hxx>
24 #include <comphelper/lok.hxx>
25 #include <sot/formats.hxx>
26 #include <sot/storage.hxx>
27 #include <vcl/graph.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/weld.hxx>
30 #include <tools/urlobj.hxx>
31 #include <sot/exchange.hxx>
33 #include <vcl/uitest/logger.hxx>
34 #include <vcl/uitest/eventdescription.hxx>
35 #include <vcl/TypeSerializer.hxx>
36 #include <osl/diagnose.h>
39 #include <patattr.hxx>
40 #include <dociter.hxx>
41 #include <viewfunc.hxx>
42 #include <tabvwsh.hxx>
44 #include <docfunc.hxx>
45 #include <undoblk.hxx>
46 #include <refundo.hxx>
47 #include <globstr.hrc>
48 #include <scresid.hxx>
50 #include <transobj.hxx>
51 #include <drwtrans.hxx>
52 #include <chgtrack.hxx>
53 #include <waitoff.hxx>
55 #include <inputopt.hxx>
56 #include <warnbox.hxx>
57 #include <drwlayer.hxx>
58 #include <editable.hxx>
60 #include <clipparam.hxx>
61 #include <undodat.hxx>
62 #include <drawview.hxx>
63 #include <cliputil.hxx>
64 #include <clipoptions.hxx>
65 #include <gridwin.hxx>
66 #include <com/sun/star/util/XCloneable.hpp>
68 using namespace com::sun::star
;
72 void collectUIInformation(std::map
<OUString
, OUString
>&& aParameters
, const OUString
& action
)
74 EventDescription aDescription
;
75 aDescription
.aID
= "grid_window";
76 aDescription
.aAction
= action
;
77 aDescription
.aParameters
= std::move(aParameters
);
78 aDescription
.aParent
= "MainWindow";
79 aDescription
.aKeyWord
= "ScGridWinUIObject";
81 UITestLogger::getInstance().logEvent(aDescription
);
86 // GlobalName of writer-DocShell from comphelper/classids.hxx
90 void ScViewFunc::CutToClip()
94 ScEditableTester
aTester( this );
95 if (!aTester
.IsEditable()) // selection editable?
97 ErrorMessage( aTester
.GetMessageId() );
101 ScRange aRange
; // delete this range
102 if ( GetViewData().GetSimpleArea( aRange
) == SC_MARK_SIMPLE
)
104 ScDocument
& rDoc
= GetViewData().GetDocument();
105 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
106 ScMarkData
& rMark
= GetViewData().GetMarkData();
107 const bool bRecord(rDoc
.IsUndoEnabled()); // Undo/Redo
109 ScDocShellModificator
aModificator( *pDocSh
);
111 if ( !rMark
.IsMarked() && !rMark
.IsMultiMarked() ) // mark the range if not marked yet
114 InitOwnBlockMode( aRange
);
115 rMark
.SetMarkArea( aRange
);
119 CopyToClip( nullptr, true, false, true/*bIncludeObjects*/ ); // copy to clipboard
121 ScAddress
aOldEnd( aRange
.aEnd
); // combined cells in this range?
122 rDoc
.ExtendMerge( aRange
, true );
124 ScDocumentUniquePtr pUndoDoc
;
127 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
128 pUndoDoc
->InitUndoSelected( rDoc
, rMark
);
129 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
130 ScRange aCopyRange
= aRange
;
131 aCopyRange
.aStart
.SetTab(0);
132 aCopyRange
.aEnd
.SetTab(rDoc
.GetTableCount()-1);
133 rDoc
.CopyToDocument( aCopyRange
, (InsertDeleteFlags::ALL
& ~InsertDeleteFlags::OBJECTS
) | InsertDeleteFlags::NOCAPTIONS
, false, *pUndoDoc
);
134 rDoc
.BeginDrawUndo();
137 sal_uInt16 nExtFlags
= 0;
138 pDocSh
->UpdatePaintExt( nExtFlags
, aRange
);
141 rDoc
.DeleteSelection( InsertDeleteFlags::ALL
, rMark
);
142 rDoc
.DeleteObjectsInSelection( rMark
);
143 rMark
.MarkToSimple();
145 if ( !AdjustRowHeight( aRange
.aStart
.Row(), aRange
.aEnd
.Row(), true ) )
146 pDocSh
->PostPaint( aRange
, PaintPartFlags::Grid
, nExtFlags
);
148 if ( bRecord
) // Draw-Undo now available
149 pDocSh
->GetUndoManager()->AddUndoAction(
150 std::make_unique
<ScUndoCut
>( pDocSh
, aRange
, aOldEnd
, rMark
, std::move(pUndoDoc
) ) );
152 aModificator
.SetDocumentModified();
153 pDocSh
->UpdateOle(GetViewData());
155 CellContentChanged();
157 OUString aStartAddress
= aRange
.aStart
.GetColRowString();
158 OUString aEndAddress
= aRange
.aEnd
.GetColRowString();
160 collectUIInformation({{"RANGE", aStartAddress
+ ":" + aEndAddress
}}, u
"CUT"_ustr
);
163 ErrorMessage( STR_NOMULTISELECT
);
168 bool ScViewFunc::CopyToClip( ScDocument
* pClipDoc
, bool bCut
, bool bApi
, bool bIncludeObjects
, bool bStopEdit
)
171 ScMarkType eMarkType
= GetViewData().GetSimpleArea( aRange
);
172 ScMarkData
& rMark
= GetViewData().GetMarkData();
175 if ( eMarkType
== SC_MARK_SIMPLE
|| eMarkType
== SC_MARK_SIMPLE_FILTERED
)
177 ScRangeList
aRangeList( aRange
);
178 bDone
= CopyToClip( pClipDoc
, aRangeList
, bCut
, bApi
, bIncludeObjects
, bStopEdit
);
180 else if (eMarkType
== SC_MARK_MULTI
)
182 ScRangeList aRangeList
;
183 rMark
.MarkToSimple();
184 rMark
.FillRangeListWithMarks(&aRangeList
, false);
185 bDone
= CopyToClip( pClipDoc
, aRangeList
, bCut
, bApi
, bIncludeObjects
, bStopEdit
);
190 ErrorMessage(STR_NOMULTISELECT
);
193 OUString aStartAddress
= aRange
.aStart
.GetColRowString();
194 OUString aEndAddress
= aRange
.aEnd
.GetColRowString();
195 collectUIInformation({{"RANGE", aStartAddress
+ ":" + aEndAddress
}}, u
"COPY"_ustr
);
200 // Copy the content of the Range into clipboard.
201 bool ScViewFunc::CopyToClip( ScDocument
* pClipDoc
, const ScRangeList
& rRanges
, bool bCut
, bool bApi
, bool bIncludeObjects
, bool bStopEdit
)
203 if ( rRanges
.empty() )
209 if (rRanges
.size() > 1) // isMultiRange
210 bDone
= CopyToClipMultiRange(pClipDoc
, rRanges
, bCut
, bApi
, bIncludeObjects
);
212 bDone
= CopyToClipSingleRange(pClipDoc
, rRanges
, bCut
, bIncludeObjects
);
217 bool ScViewFunc::CopyToClipSingleRange( ScDocument
* pClipDoc
, const ScRangeList
& rRanges
, bool bCut
, bool bIncludeObjects
)
219 ScRange aRange
= rRanges
[0];
220 ScClipParam
aClipParam( aRange
, bCut
);
221 aClipParam
.maRanges
= rRanges
;
222 ScDocument
& rDoc
= GetViewData().GetDocument();
223 ScMarkData
& rMark
= GetViewData().GetMarkData();
225 if (rDoc
.HasSelectedBlockMatrixFragment( aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), rMark
) )
228 std::shared_ptr
<ScDocument
> pSysClipDoc
;
229 if ( !pClipDoc
) // no clip doc specified
231 // Create one (deleted by ScTransferObj), and copy into system.
232 pSysClipDoc
= std::make_shared
<ScDocument
>( SCDOCMODE_CLIP
);
233 pClipDoc
= pSysClipDoc
.get();
237 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
239 pChangeTrack
->ResetLastCut();
242 if ( pSysClipDoc
&& bIncludeObjects
)
244 bool bAnyOle
= rDoc
.HasOLEObjectsInArea( aRange
);
245 // Update ScGlobal::xDrawClipDocShellRef.
246 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle
, pSysClipDoc
) );
249 // is this necessary?, will setting the doc id upset the
250 // following paste operation with range? would be nicer to just set this always
251 // and lose the 'if' above
252 aClipParam
.setSourceDocID( rDoc
.GetDocumentID() );
254 if (ScDocShell
* pObjectShell
= rDoc
.GetDocumentShell())
256 // Copy document properties from pObjectShell to pClipDoc (to its clip options, as it has no object shell).
257 uno::Reference
<util::XCloneable
> xCloneable(pObjectShell
->getDocProperties(), uno::UNO_QUERY_THROW
);
258 std::unique_ptr
<ScClipOptions
> pOptions(new ScClipOptions
);
259 pOptions
->m_xDocumentProperties
.set(xCloneable
->createClone(), uno::UNO_QUERY
);
260 pClipDoc
->SetClipOptions(std::move(pOptions
));
263 rDoc
.CopyToClip( aClipParam
, pClipDoc
, &rMark
, false, bIncludeObjects
);
264 if (ScDrawLayer
* pDrawLayer
= pClipDoc
->GetDrawLayer())
266 ScClipParam
& rClipDocClipParam
= pClipDoc
->GetClipParam();
267 ScRangeListVector
& rRangesVector
= rClipDocClipParam
.maProtectedChartRangesVector
;
268 SCTAB nTabCount
= pClipDoc
->GetTableCount();
269 for ( SCTAB nTab
= 0; nTab
< nTabCount
; ++nTab
)
271 SdrPage
* pPage
= pDrawLayer
->GetPage( static_cast< sal_uInt16
>( nTab
) );
274 ScChartHelper::FillProtectedChartRangesVector( rRangesVector
, rDoc
, pPage
);
281 ScDrawLayer::SetGlobalDrawPersist(nullptr);
282 ScGlobal::SetClipDocName( rDoc
.GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME
) );
284 pClipDoc
->ExtendMerge( aRange
, true );
288 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
289 TransferableObjectDescriptor aObjDesc
;
290 pDocSh
->FillTransferableObjectDescriptor( aObjDesc
);
291 aObjDesc
.maDisplayName
= pDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
292 // maSize is set in ScTransferObj ctor
294 rtl::Reference
<ScTransferObj
> pTransferObj(new ScTransferObj( pSysClipDoc
, std::move(aObjDesc
) ));
295 if ( ScGlobal::xDrawClipDocShellRef
.is() )
297 SfxObjectShellRef
aPersistRef(ScGlobal::xDrawClipDocShellRef
);
298 pTransferObj
->SetDrawPersist( aPersistRef
);// keep persist for ole objects alive
300 pTransferObj
->CopyToClipboard( GetActiveWin() );
306 bool ScViewFunc::CopyToClipMultiRange( const ScDocument
* pInputClipDoc
, const ScRangeList
& rRanges
, bool bCut
, bool bApi
, bool bIncludeObjects
)
310 // We don't support cutting of multi-selections.
312 ErrorMessage(STR_NOMULTISELECT
);
317 // TODO: What's this for?
319 ErrorMessage(STR_NOMULTISELECT
);
323 ScClipParam
aClipParam( rRanges
[0], bCut
);
324 aClipParam
.maRanges
= rRanges
;
325 ScDocument
& rDoc
= GetViewData().GetDocument();
326 ScMarkData
& rMark
= GetViewData().GetMarkData();
328 bool bSuccess
= false;
329 aClipParam
.mbCutMode
= false;
333 ScDocumentUniquePtr
pDocClip(new ScDocument(SCDOCMODE_CLIP
));
335 // Check for geometrical feasibility of the ranges.
336 bool bValidRanges
= true;
337 ScRange
const * p
= &aClipParam
.maRanges
.front();
338 SCCOL nPrevColDelta
= 0;
339 SCROW nPrevRowDelta
= 0;
340 SCCOL nPrevCol
= p
->aStart
.Col();
341 SCROW nPrevRow
= p
->aStart
.Row();
342 SCCOL nPrevColSize
= p
->aEnd
.Col() - p
->aStart
.Col() + 1;
343 SCROW nPrevRowSize
= p
->aEnd
.Row() - p
->aStart
.Row() + 1;
344 for ( size_t i
= 1; i
< aClipParam
.maRanges
.size(); ++i
)
346 p
= &aClipParam
.maRanges
[i
];
347 if ( rDoc
.HasSelectedBlockMatrixFragment(
348 p
->aStart
.Col(), p
->aStart
.Row(), p
->aEnd
.Col(), p
->aEnd
.Row(), rMark
) )
351 ErrorMessage(STR_MATRIXFRAGMENTERR
);
355 SCCOL nColDelta
= p
->aStart
.Col() - nPrevCol
;
356 SCROW nRowDelta
= p
->aStart
.Row() - nPrevRow
;
358 if ((nColDelta
&& nRowDelta
) || (nPrevColDelta
&& nRowDelta
) || (nPrevRowDelta
&& nColDelta
))
360 bValidRanges
= false;
364 if (aClipParam
.meDirection
== ScClipParam::Unspecified
)
367 aClipParam
.meDirection
= ScClipParam::Column
;
369 aClipParam
.meDirection
= ScClipParam::Row
;
372 SCCOL nColSize
= p
->aEnd
.Col() - p
->aStart
.Col() + 1;
373 SCROW nRowSize
= p
->aEnd
.Row() - p
->aStart
.Row() + 1;
375 if (aClipParam
.meDirection
== ScClipParam::Column
&& nRowSize
!= nPrevRowSize
)
377 // column-oriented ranges must have identical row size.
378 bValidRanges
= false;
381 if (aClipParam
.meDirection
== ScClipParam::Row
&& nColSize
!= nPrevColSize
)
383 // likewise, row-oriented ranges must have identical
385 bValidRanges
= false;
389 nPrevCol
= p
->aStart
.Col();
390 nPrevRow
= p
->aStart
.Row();
391 nPrevColDelta
= nColDelta
;
392 nPrevRowDelta
= nRowDelta
;
393 nPrevColSize
= nColSize
;
394 nPrevRowSize
= nRowSize
;
398 rDoc
.CopyToClip(aClipParam
, pDocClip
.get(), &rMark
, false, bIncludeObjects
);
400 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
402 pChangeTrack
->ResetLastCut(); // no more cut-mode
404 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
405 TransferableObjectDescriptor aObjDesc
;
406 pDocSh
->FillTransferableObjectDescriptor( aObjDesc
);
407 aObjDesc
.maDisplayName
= pDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
408 // maSize is set in ScTransferObj ctor
410 rtl::Reference
<ScTransferObj
> pTransferObj(new ScTransferObj( std::move(pDocClip
), std::move(aObjDesc
) ));
411 if ( ScGlobal::xDrawClipDocShellRef
.is() )
413 SfxObjectShellRef
aPersistRef(ScGlobal::xDrawClipDocShellRef
);
414 pTransferObj
->SetDrawPersist( aPersistRef
); // keep persist for ole objects alive
416 pTransferObj
->CopyToClipboard( GetActiveWin() ); // system clipboard
422 if (!bSuccess
&& !bApi
)
423 ErrorMessage(STR_NOMULTISELECT
);
430 rtl::Reference
<ScTransferObj
> ScViewFunc::CopyToTransferable()
433 auto eMarkType
= GetViewData().GetSimpleArea( aRange
);
434 if ( eMarkType
== SC_MARK_SIMPLE
|| eMarkType
== SC_MARK_SIMPLE_FILTERED
)
436 ScDocument
& rDoc
= GetViewData().GetDocument();
437 ScMarkData
& rMark
= GetViewData().GetMarkData();
438 if ( !rDoc
.HasSelectedBlockMatrixFragment(
439 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
440 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(),
443 ScDocumentUniquePtr
pClipDoc(new ScDocument( SCDOCMODE_CLIP
)); // create one (deleted by ScTransferObj)
445 bool bAnyOle
= rDoc
.HasOLEObjectsInArea( aRange
, &rMark
);
446 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle
) );
448 ScClipParam
aClipParam(aRange
, false);
449 rDoc
.CopyToClip(aClipParam
, pClipDoc
.get(), &rMark
, false, true);
451 ScDrawLayer::SetGlobalDrawPersist(nullptr);
452 pClipDoc
->ExtendMerge( aRange
, true );
454 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
455 TransferableObjectDescriptor aObjDesc
;
456 pDocSh
->FillTransferableObjectDescriptor( aObjDesc
);
457 aObjDesc
.maDisplayName
= pDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
458 return new ScTransferObj( std::move(pClipDoc
), std::move(aObjDesc
) );
461 else if (eMarkType
== SC_MARK_MULTI
)
463 ScDocumentUniquePtr
pClipDoc(new ScDocument(SCDOCMODE_CLIP
));
464 // This takes care of the input line and calls CopyToClipMultiRange() for us.
465 CopyToClip(pClipDoc
.get(), aRange
, /*bCut=*/false, /*bApi=*/true);
466 TransferableObjectDescriptor aObjDesc
;
467 return new ScTransferObj(std::move(pClipDoc
), std::move(aObjDesc
));
475 void ScViewFunc::PasteDraw()
477 ScViewData
& rViewData
= GetViewData();
478 SCCOL nPosX
= rViewData
.GetCurX();
479 SCROW nPosY
= rViewData
.GetCurY();
480 vcl::Window
* pWin
= GetActiveWin();
481 Point aPos
= pWin
->PixelToLogic( rViewData
.GetScrPos( nPosX
, nPosY
,
482 rViewData
.GetActivePart() ) );
483 const ScDrawTransferObj
* pDrawClip
= ScDrawTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(rViewData
.GetActiveWin()));
486 const OUString
& aSrcShellID
= pDrawClip
->GetShellID();
487 OUString aDestShellID
= SfxObjectShell::CreateShellID(rViewData
.GetDocShell());
488 PasteDraw(aPos
, pDrawClip
->GetModel(), false, aSrcShellID
, aDestShellID
);
492 void ScViewFunc::PasteFromSystem()
496 vcl::Window
* pWin
= GetActiveWin();
497 css::uno::Reference
<css::datatransfer::XTransferable2
> xTransferable2(ScTabViewShell::GetClipData(pWin
));
498 const ScTransferObj
* pOwnClip
= ScTransferObj::GetOwnClipboard(xTransferable2
);
499 // keep a reference in case the clipboard is changed during PasteFromClip
500 const ScDrawTransferObj
* pDrawClip
= ScDrawTransferObj::GetOwnClipboard(xTransferable2
);
503 PasteFromClip( InsertDeleteFlags::ALL
, pOwnClip
->GetDocument(),
504 ScPasteFunc::NONE
, false, false, false, INS_NONE
, InsertDeleteFlags::NONE
,
505 true ); // allow warning dialog
511 TransferableDataHelper
aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin
) );
514 SotClipboardFormatId nBiff8
= SotExchange::RegisterFormatName(u
"Biff8"_ustr
);
515 SotClipboardFormatId nBiff5
= SotExchange::RegisterFormatName(u
"Biff5"_ustr
);
517 SotClipboardFormatId nFormat
; // output param for GetExchangeAction
518 sal_uInt8 nEventAction
; // output param for GetExchangeAction
520 uno::Reference
<css::datatransfer::XTransferable
> xTransferable( aDataHelper
.GetXTransferable() );
521 sal_uInt8 nAction
= SotExchange::GetExchangeAction(
522 aDataHelper
.GetDataFlavorExVector(),
523 SotExchangeDest::SCDOC_FREE_AREA
,
524 EXCHG_IN_ACTION_COPY
,
525 EXCHG_IN_ACTION_DEFAULT
,
526 nFormat
, nEventAction
, SotClipboardFormatId::NONE
,
529 if ( nAction
!= EXCHG_INOUT_ACTION_NONE
)
533 case EXCHG_OUT_ACTION_INSERT_SVXB
:
534 case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE
:
535 case EXCHG_OUT_ACTION_INSERT_BITMAP
:
536 case EXCHG_OUT_ACTION_INSERT_GRAPH
:
537 // SotClipboardFormatId::BITMAP
538 // SotClipboardFormatId::PNG
539 // SotClipboardFormatId::GDIMETAFILE
540 // SotClipboardFormatId::SVXB
541 PasteFromSystem(nFormat
);
544 nAction
= EXCHG_INOUT_ACTION_NONE
;
548 if ( nAction
== EXCHG_INOUT_ACTION_NONE
)
550 // first SvDraw-model, then drawing
551 // (only one drawing is allowed)
553 if (aDataHelper
.HasFormat( SotClipboardFormatId::DRAWING
))
555 // special case for tables from drawing
556 if( aDataHelper
.HasFormat( SotClipboardFormatId::RTF
) )
558 PasteFromSystem( SotClipboardFormatId::RTF
);
560 else if( aDataHelper
.HasFormat( SotClipboardFormatId::RICHTEXT
) )
562 PasteFromSystem( SotClipboardFormatId::RICHTEXT
);
566 PasteFromSystem( SotClipboardFormatId::DRAWING
);
569 else if (aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
))
571 // If it's a Writer object, insert RTF instead of OLE
573 // Else, if the class id is all-zero, and SYLK is available,
574 // it probably is spreadsheet cells that have been put
575 // on the clipboard by OOo, so use the SYLK. (fdo#31077)
578 TransferableObjectDescriptor aObjDesc
;
579 if( aDataHelper
.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR
, aObjDesc
) )
581 bDoRtf
= ( ( aObjDesc
.maClassName
== SvGlobalName( SO3_SW_CLASSID
) ||
582 aObjDesc
.maClassName
== SvGlobalName( SO3_SWWEB_CLASSID
) )
583 && ( aDataHelper
.HasFormat( SotClipboardFormatId::RTF
) || aDataHelper
.HasFormat( SotClipboardFormatId::RICHTEXT
) ) );
586 PasteFromSystem( aDataHelper
.HasFormat( SotClipboardFormatId::RTF
) ? SotClipboardFormatId::RTF
: SotClipboardFormatId::RICHTEXT
);
587 else if ( aObjDesc
.maClassName
== SvGlobalName( 0,0,0,0,0,0,0,0,0,0,0 )
588 && aDataHelper
.HasFormat( SotClipboardFormatId::SYLK
))
589 PasteFromSystem( SotClipboardFormatId::SYLK
);
591 PasteFromSystem( SotClipboardFormatId::EMBED_SOURCE
);
593 else if (aDataHelper
.HasFormat( SotClipboardFormatId::LINK_SOURCE
))
594 PasteFromSystem( SotClipboardFormatId::LINK_SOURCE
);
595 // the following format can not affect scenario from #89579#
596 else if (aDataHelper
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE
))
597 PasteFromSystem( SotClipboardFormatId::EMBEDDED_OBJ_OLE
);
598 // SotClipboardFormatId::PRIVATE no longer here (can't work if pOwnClip is NULL)
599 else if (aDataHelper
.HasFormat(nBiff8
)) // before xxx_OLE formats
600 PasteFromSystem(nBiff8
);
601 else if (aDataHelper
.HasFormat(nBiff5
))
602 PasteFromSystem(nBiff5
);
603 else if (aDataHelper
.HasFormat(SotClipboardFormatId::RTF
))
604 PasteFromSystem(SotClipboardFormatId::RTF
);
605 else if (aDataHelper
.HasFormat(SotClipboardFormatId::RICHTEXT
))
606 PasteFromSystem(SotClipboardFormatId::RICHTEXT
);
607 else if (aDataHelper
.HasFormat(SotClipboardFormatId::HTML
))
608 PasteFromSystem(SotClipboardFormatId::HTML
);
609 else if (aDataHelper
.HasFormat(SotClipboardFormatId::BITMAP
))
610 PasteFromSystem(SotClipboardFormatId::BITMAP
);
611 else if (aDataHelper
.HasFormat(SotClipboardFormatId::HTML_SIMPLE
))
612 PasteFromSystem(SotClipboardFormatId::HTML_SIMPLE
);
613 else if (aDataHelper
.HasFormat(SotClipboardFormatId::SYLK
))
614 PasteFromSystem(SotClipboardFormatId::SYLK
);
615 else if (aDataHelper
.HasFormat(SotClipboardFormatId::STRING_TSVC
))
616 PasteFromSystem(SotClipboardFormatId::STRING_TSVC
);
617 else if (aDataHelper
.HasFormat(SotClipboardFormatId::STRING
))
618 PasteFromSystem(SotClipboardFormatId::STRING
);
619 // xxx_OLE formats come last, like in SotExchange tables
620 else if (aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE_OLE
))
621 PasteFromSystem( SotClipboardFormatId::EMBED_SOURCE_OLE
);
622 else if (aDataHelper
.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE
))
623 PasteFromSystem( SotClipboardFormatId::LINK_SOURCE_OLE
);
627 // no exception-> SID_PASTE has FastCall-flag from idl
628 // will be called in case of empty clipboard (#42531#)
631 void ScViewFunc::PasteFromTransferable( const uno::Reference
<datatransfer::XTransferable
>& rxTransferable
)
633 if (auto pOwnClip
= dynamic_cast<ScTransferObj
*>(rxTransferable
.get()))
635 PasteFromClip( InsertDeleteFlags::ALL
, pOwnClip
->GetDocument(),
636 ScPasteFunc::NONE
, false, false, false, INS_NONE
, InsertDeleteFlags::NONE
,
637 true ); // allow warning dialog
639 else if (auto pDrawClip
= dynamic_cast<ScDrawTransferObj
*>(rxTransferable
.get()))
641 ScViewData
& rViewData
= GetViewData();
642 SCCOL nPosX
= rViewData
.GetCurX();
643 SCROW nPosY
= rViewData
.GetCurY();
644 vcl::Window
* pWin
= GetActiveWin();
645 Point aPos
= pWin
->PixelToLogic( rViewData
.GetScrPos( nPosX
, nPosY
, rViewData
.GetActivePart() ) );
647 aPos
, pDrawClip
->GetModel(), false,
648 pDrawClip
->GetShellID(), SfxObjectShell::CreateShellID(rViewData
.GetDocShell()));
652 TransferableDataHelper
aDataHelper( rxTransferable
);
653 SotClipboardFormatId nBiff8
= SotExchange::RegisterFormatName(u
"Biff8"_ustr
);
654 SotClipboardFormatId nBiff5
= SotExchange::RegisterFormatName(u
"Biff5"_ustr
);
655 SotClipboardFormatId nFormatId
= SotClipboardFormatId::NONE
;
656 // first SvDraw-model, then drawing
657 // (only one drawing is allowed)
659 if (aDataHelper
.HasFormat( SotClipboardFormatId::DRAWING
))
660 nFormatId
= SotClipboardFormatId::DRAWING
;
661 else if (aDataHelper
.HasFormat( SotClipboardFormatId::SVXB
))
662 nFormatId
= SotClipboardFormatId::SVXB
;
663 else if (aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
))
665 // If it's a Writer object, insert RTF instead of OLE
667 TransferableObjectDescriptor aObjDesc
;
668 if( aDataHelper
.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR
, aObjDesc
) )
670 bDoRtf
= ( ( aObjDesc
.maClassName
== SvGlobalName( SO3_SW_CLASSID
) ||
671 aObjDesc
.maClassName
== SvGlobalName( SO3_SWWEB_CLASSID
) )
672 && ( aDataHelper
.HasFormat( SotClipboardFormatId::RTF
) || aDataHelper
.HasFormat( SotClipboardFormatId::RICHTEXT
) ));
675 nFormatId
= aDataHelper
.HasFormat( SotClipboardFormatId::RTF
) ? SotClipboardFormatId::RTF
: SotClipboardFormatId::RICHTEXT
;
677 nFormatId
= SotClipboardFormatId::EMBED_SOURCE
;
679 else if (aDataHelper
.HasFormat( SotClipboardFormatId::LINK_SOURCE
))
680 nFormatId
= SotClipboardFormatId::LINK_SOURCE
;
681 // the following format can not affect scenario from #89579#
682 else if (aDataHelper
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE
))
683 nFormatId
= SotClipboardFormatId::EMBEDDED_OBJ_OLE
;
684 // SotClipboardFormatId::PRIVATE no longer here (can't work if pOwnClip is NULL)
685 else if (aDataHelper
.HasFormat(nBiff8
)) // before xxx_OLE formats
687 else if (aDataHelper
.HasFormat(nBiff5
))
689 else if (aDataHelper
.HasFormat(SotClipboardFormatId::RTF
))
690 nFormatId
= SotClipboardFormatId::RTF
;
691 else if (aDataHelper
.HasFormat(SotClipboardFormatId::RICHTEXT
))
692 nFormatId
= SotClipboardFormatId::RICHTEXT
;
693 else if (aDataHelper
.HasFormat(SotClipboardFormatId::HTML
))
694 nFormatId
= SotClipboardFormatId::HTML
;
695 else if (aDataHelper
.HasFormat(SotClipboardFormatId::HTML_SIMPLE
))
696 nFormatId
= SotClipboardFormatId::HTML_SIMPLE
;
697 else if (aDataHelper
.HasFormat(SotClipboardFormatId::SYLK
))
698 nFormatId
= SotClipboardFormatId::SYLK
;
699 else if (aDataHelper
.HasFormat(SotClipboardFormatId::STRING_TSVC
))
700 nFormatId
= SotClipboardFormatId::STRING_TSVC
;
701 else if (aDataHelper
.HasFormat(SotClipboardFormatId::STRING
))
702 nFormatId
= SotClipboardFormatId::STRING
;
703 else if (aDataHelper
.HasFormat(SotClipboardFormatId::GDIMETAFILE
))
704 nFormatId
= SotClipboardFormatId::GDIMETAFILE
;
705 else if (aDataHelper
.HasFormat(SotClipboardFormatId::BITMAP
))
706 nFormatId
= SotClipboardFormatId::BITMAP
;
707 // xxx_OLE formats come last, like in SotExchange tables
708 else if (aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE_OLE
))
709 nFormatId
= SotClipboardFormatId::EMBED_SOURCE_OLE
;
710 else if (aDataHelper
.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE
))
711 nFormatId
= SotClipboardFormatId::LINK_SOURCE_OLE
;
715 PasteDataFormat( nFormatId
, aDataHelper
.GetTransferable(),
716 GetViewData().GetCurX(), GetViewData().GetCurY(), nullptr );
720 bool ScViewFunc::PasteFromSystem( SotClipboardFormatId nFormatId
, bool bApi
)
725 vcl::Window
* pWin
= GetActiveWin();
726 // keep a reference in case the clipboard is changed during PasteFromClip
727 const ScTransferObj
* pOwnClip
= ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin
));
728 if ( nFormatId
== SotClipboardFormatId::NONE
&& pOwnClip
)
730 PasteFromClip( InsertDeleteFlags::ALL
, pOwnClip
->GetDocument(),
731 ScPasteFunc::NONE
, false, false, false, INS_NONE
, InsertDeleteFlags::NONE
,
732 !bApi
); // allow warning dialog
736 TransferableDataHelper
aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin
) );
737 if ( !aDataHelper
.GetTransferable().is() )
743 ScViewData
& rViewData
= GetViewData();
745 if ( rViewData
.GetSimpleArea( aRange
) == SC_MARK_SIMPLE
)
747 nPosX
= aRange
.aStart
.Col();
748 nPosY
= aRange
.aStart
.Row();
752 nPosX
= rViewData
.GetCurX();
753 nPosY
= rViewData
.GetCurY();
756 bRet
= PasteDataFormat( nFormatId
, aDataHelper
.GetTransferable(),
758 nullptr, false, !bApi
); // allow warning dialog
760 if ( !bRet
&& !bApi
)
762 ErrorMessage(STR_PASTE_ERROR
);
764 else if (comphelper::LibreOfficeKit::isActive())
766 ScTabViewShell
* pTabViewShell
= rViewData
.GetViewShell();
767 pTabViewShell
->OnLOKSetWidthOrHeight(rViewData
.GetCurX(), true);
768 pTabViewShell
->OnLOKSetWidthOrHeight(rViewData
.GetCurY(), false);
770 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(pTabViewShell
, true /* bColumns */, true /* bRows */,
771 true /* bSizes */, false /* bHidden */, false /* bFiltered */, false /* bGroups */, rViewData
.GetTabNo());
779 bool ScViewFunc::PasteOnDrawObjectLinked(
780 const uno::Reference
<datatransfer::XTransferable
>& rxTransferable
,
783 TransferableDataHelper
aDataHelper( rxTransferable
);
785 if ( aDataHelper
.HasFormat( SotClipboardFormatId::SVXB
) )
787 if (ScDrawView
* pScDrawView
= GetScDrawView())
788 if (std::unique_ptr
<SvStream
> xStm
= aDataHelper
.GetSotStorageStream( SotClipboardFormatId::SVXB
) )
791 TypeSerializer
aSerializer(*xStm
);
792 aSerializer
.readGraphic(aGraphic
);
794 const OUString
aBeginUndo(ScResId(STR_UNDO_DRAGDROP
));
796 if(pScDrawView
->ApplyGraphicToObject( rHitObj
, aGraphic
, aBeginUndo
, u
""_ustr
))
802 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::GDIMETAFILE
) )
805 ScDrawView
* pScDrawView
= GetScDrawView();
807 if( pScDrawView
&& aDataHelper
.GetGDIMetaFile( SotClipboardFormatId::GDIMETAFILE
, aMtf
) )
809 const OUString
aBeginUndo(ScResId(STR_UNDO_DRAGDROP
));
811 if(pScDrawView
->ApplyGraphicToObject( rHitObj
, Graphic(aMtf
), aBeginUndo
, u
""_ustr
))
817 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::BITMAP
) || aDataHelper
.HasFormat( SotClipboardFormatId::PNG
) )
820 ScDrawView
* pScDrawView
= GetScDrawView();
822 if( pScDrawView
&& aDataHelper
.GetBitmapEx( SotClipboardFormatId::BITMAP
, aBmpEx
) )
824 const OUString
aBeginUndo(ScResId(STR_UNDO_DRAGDROP
));
826 if(pScDrawView
->ApplyGraphicToObject( rHitObj
, Graphic(aBmpEx
), aBeginUndo
, u
""_ustr
))
836 static bool lcl_SelHasAttrib( const ScDocument
& rDoc
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
837 const ScMarkData
& rTabSelection
, HasAttrFlags nMask
)
839 return std::any_of(rTabSelection
.begin(), rTabSelection
.end(),
840 [&](const SCTAB
& rTab
) { return rDoc
.HasAttrib( nCol1
, nRow1
, rTab
, nCol2
, nRow2
, rTab
, nMask
); });
849 bool checkDestRangeForOverwrite(InsertDeleteFlags nFlags
, const ScRangeList
& rDestRanges
,
850 const ScDocument
& rDoc
, const ScMarkData
& rMark
,
851 weld::Window
* pParentWnd
)
853 bool bIsEmpty
= true;
854 size_t nRangeSize
= rDestRanges
.size();
856 for (const auto& rTab
: rMark
)
858 for (size_t i
= 0; i
< nRangeSize
&& bIsEmpty
; ++i
)
860 const ScRange
& rRange
= rDestRanges
[i
];
861 // tdf#158110 - check if just the ADDNOTES flag is present without any other content
862 if ((nFlags
& InsertDeleteFlags::ADDNOTES
) == InsertDeleteFlags::ADDNOTES
863 && (nFlags
& (InsertDeleteFlags::CONTENTS
& ~InsertDeleteFlags::NOTE
))
864 == InsertDeleteFlags::NONE
)
865 bIsEmpty
= rDoc
.IsNotesBlockEmpty(rRange
.aStart
.Col(), rRange
.aStart
.Row(),
866 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rTab
);
868 bIsEmpty
= rDoc
.IsBlockEmpty(rRange
.aStart
.Col(), rRange
.aStart
.Row(),
869 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rTab
);
877 ScReplaceWarnBox
aBox(pParentWnd
);
878 if (aBox
.run() != RET_YES
)
880 // changing the configuration is within the ScReplaceWarnBox
889 bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags
, ScDocument
* pClipDoc
,
890 ScPasteFunc nFunction
, bool bSkipEmptyCells
,
891 bool bTranspose
, bool bAsLink
,
892 InsCellCmd eMoveMode
, InsertDeleteFlags nUndoExtraFlags
,
897 OSL_FAIL("PasteFromClip: pClipDoc=0 not allowed");
901 if (GetViewData().SelectionForbidsPaste(pClipDoc
))
904 // undo: save all or no content
905 InsertDeleteFlags nContFlags
= InsertDeleteFlags::NONE
;
906 if (nFlags
& InsertDeleteFlags::CONTENTS
)
907 nContFlags
|= InsertDeleteFlags::CONTENTS
;
908 if (nFlags
& InsertDeleteFlags::ATTRIB
)
909 nContFlags
|= InsertDeleteFlags::ATTRIB
;
910 // move attributes to undo without copying them from clip to doc
911 InsertDeleteFlags nUndoFlags
= nContFlags
;
912 if (nUndoExtraFlags
& InsertDeleteFlags::ATTRIB
)
913 nUndoFlags
|= InsertDeleteFlags::ATTRIB
;
914 // do not copy note captions into undo document
915 nUndoFlags
|= InsertDeleteFlags::NOCAPTIONS
;
917 ScClipParam
& rClipParam
= pClipDoc
->GetClipParam();
918 if (rClipParam
.isMultiRange())
920 // Source data is multi-range.
921 return PasteMultiRangesFromClip(nFlags
, pClipDoc
, nFunction
, bSkipEmptyCells
, bTranspose
,
922 bAsLink
, bAllowDialogs
, eMoveMode
, nUndoFlags
);
925 ScMarkData
& rMark
= GetViewData().GetMarkData();
926 if (rMark
.IsMultiMarked())
928 // Source data is single-range but destination is multi-range.
929 return PasteFromClipToMultiRanges(
930 nFlags
, pClipDoc
, nFunction
, bSkipEmptyCells
, bTranspose
, bAsLink
, bAllowDialogs
,
931 eMoveMode
, nUndoFlags
);
934 bool bCutMode
= pClipDoc
->IsCutMode(); // if transposing, take from original clipdoc
935 bool bIncludeFiltered
= bCutMode
;
937 // paste drawing: also if InsertDeleteFlags::NOTE is set (to create drawing layer for note captions)
938 bool bPasteDraw
= ( pClipDoc
->GetDrawLayer() && ( nFlags
& (InsertDeleteFlags::OBJECTS
|InsertDeleteFlags::NOTE
) ) );
940 ScDocShellRef aTransShellRef
; // for objects in xTransClip - must remain valid as long as xTransClip
941 ScDocument
* pOrigClipDoc
= nullptr;
942 ScDocumentUniquePtr xTransClip
;
947 // include filtered rows until TransposeClip can skip them
948 pClipDoc
->GetClipArea( nX
, nY
, true );
949 if ( nY
> static_cast<sal_Int32
>(pClipDoc
->MaxCol()) ) // too many lines for transpose
951 ErrorMessage(STR_PASTE_FULL
);
954 pOrigClipDoc
= pClipDoc
; // refs
958 aTransShellRef
= new ScDocShell
; // DocShell needs a Ref immediately
959 aTransShellRef
->DoInitNew();
961 ScDrawLayer::SetGlobalDrawPersist( aTransShellRef
.get() );
963 xTransClip
.reset( new ScDocument( SCDOCMODE_CLIP
));
964 pClipDoc
->TransposeClip(xTransClip
.get(), nFlags
, bAsLink
, bIncludeFiltered
);
965 pClipDoc
= xTransClip
.get();
967 ScDrawLayer::SetGlobalDrawPersist(nullptr);
970 // TODO: position this call better for performance.
971 ResetAutoSpellForContentChange();
981 pClipDoc
->GetClipArea( nClipSizeX
, nClipSizeY
, true ); // size in clipboard doc
983 // size in target doc: include filtered rows only if CutMode is set
986 pClipDoc
->GetClipArea( nDestSizeX
, nDestSizeY
, bIncludeFiltered
);
988 ScDocument
& rDoc
= GetViewData().GetDocument();
989 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
990 SfxUndoManager
* pUndoMgr
= pDocSh
->GetUndoManager();
991 const bool bRecord(rDoc
.IsUndoEnabled());
993 ScDocShellModificator
aModificator( *pDocSh
);
996 ScMarkData
aFilteredMark( rMark
); // local copy for all modifications
997 ScMarkType eMarkType
= GetViewData().GetSimpleArea( aMarkRange
, aFilteredMark
);
998 bool bMarkIsFiltered
= (eMarkType
== SC_MARK_SIMPLE_FILTERED
);
999 bool bNoPaste
= ((eMarkType
!= SC_MARK_SIMPLE
&& !bMarkIsFiltered
) ||
1000 (bMarkIsFiltered
&& (eMoveMode
!= INS_NONE
|| bAsLink
)));
1004 if (!rMark
.IsMarked())
1006 // Create a selection with clipboard row count and check that for
1008 nStartCol
= GetViewData().GetCurX();
1009 nStartRow
= GetViewData().GetCurY();
1010 nStartTab
= GetViewData().GetTabNo();
1011 nEndCol
= nStartCol
+ nDestSizeX
;
1012 nEndRow
= nStartRow
+ nDestSizeY
;
1013 nEndTab
= nStartTab
;
1014 aMarkRange
= ScRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
);
1015 if (ScViewUtil::HasFiltered(aMarkRange
, rDoc
))
1017 bMarkIsFiltered
= true;
1018 // Fit to clipboard's row count unfiltered rows. If there is no
1019 // fit assume that pasting is not possible. Note that nDestSizeY is
1020 // size-1 (difference).
1021 if (!ScViewUtil::FitToUnfilteredRows(aMarkRange
, rDoc
, nDestSizeY
+1))
1024 aFilteredMark
.SetMarkArea( aMarkRange
);
1028 // Expand the marked area when the destination area is larger than the
1029 // current selection, to get the undo do the right thing. (i#106711)
1030 ScRange aRange
= aFilteredMark
.GetMarkArea();
1031 if( (aRange
.aEnd
.Col() - aRange
.aStart
.Col()) < nDestSizeX
)
1033 aRange
.aEnd
.SetCol(aRange
.aStart
.Col() + nDestSizeX
);
1034 aFilteredMark
.SetMarkArea(aRange
);
1041 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0
);
1045 SCROW nUnfilteredRows
= aMarkRange
.aEnd
.Row() - aMarkRange
.aStart
.Row() + 1;
1046 ScRangeList aRangeList
;
1047 if (bMarkIsFiltered
)
1049 ScViewUtil::UnmarkFiltered(aFilteredMark
, rDoc
);
1050 aFilteredMark
.FillRangeListWithMarks( &aRangeList
, false);
1051 nUnfilteredRows
= 0;
1052 size_t ListSize
= aRangeList
.size();
1053 for ( size_t i
= 0; i
< ListSize
; ++i
)
1055 ScRange
& r
= aRangeList
[i
];
1056 nUnfilteredRows
+= r
.aEnd
.Row() - r
.aStart
.Row() + 1;
1059 /* This isn't needed but could be a desired restriction. */
1060 // For filtered, destination rows have to be an exact multiple of
1061 // source rows. Note that nDestSizeY is size-1 (difference), so
1062 // nDestSizeY==0 fits always.
1063 if ((nUnfilteredRows
% (nDestSizeY
+1)) != 0)
1065 /* FIXME: this should be a more descriptive error message then. */
1066 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0
);
1072 // Also for a filtered selection the area is used, for undo et al.
1073 if ( aFilteredMark
.IsMarked() || bMarkIsFiltered
)
1075 aMarkRange
.GetVars( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
);
1076 SCCOL nBlockAddX
= nEndCol
-nStartCol
;
1077 SCROW nBlockAddY
= nEndRow
-nStartRow
;
1079 // request, if the selection is greater than one row/column, but smaller
1080 // as the Clipboard (then inserting is done beyond the selection)
1082 // ClipSize is not size, but difference
1083 if ( ( nBlockAddX
!= 0 && nBlockAddX
< nDestSizeX
) ||
1084 ( nBlockAddY
!= 0 && nBlockAddY
< nDestSizeY
) ||
1085 ( bMarkIsFiltered
&& nUnfilteredRows
< nDestSizeY
+1 ) )
1087 ScWaitCursorOff
aWaitOff( GetFrameWin() );
1088 OUString aMessage
= ScResId( STR_PASTE_BIGGER
);
1090 std::unique_ptr
<weld::MessageDialog
> xQueryBox(Application::CreateMessageDialog(GetViewData().GetDialogParent(),
1091 VclMessageType::Question
, VclButtonsType::YesNo
,
1093 xQueryBox
->set_default_response(RET_NO
);
1094 if (xQueryBox
->run() != RET_YES
)
1100 if (nBlockAddX
<= nDestSizeX
)
1101 nEndCol
= nStartCol
+ nDestSizeX
;
1103 if (nBlockAddY
<= nDestSizeY
)
1105 nEndRow
= nStartRow
+ nDestSizeY
;
1106 if (bMarkIsFiltered
|| nEndRow
> aMarkRange
.aEnd
.Row())
1108 // Same as above if nothing was marked: re-fit selection to
1109 // unfiltered rows. Extending the selection actually may
1110 // introduce filtered rows where there weren't any before, so
1111 // we also need to test for that.
1112 aMarkRange
= ScRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
);
1113 if (bMarkIsFiltered
|| ScViewUtil::HasFiltered(aMarkRange
, rDoc
))
1115 bMarkIsFiltered
= true;
1116 // Worst case: all rows up to the end of the sheet are filtered.
1117 if (!ScViewUtil::FitToUnfilteredRows(aMarkRange
, rDoc
, nDestSizeY
+1))
1119 ErrorMessage(STR_PASTE_FULL
);
1123 aMarkRange
.GetVars( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
);
1124 aFilteredMark
.SetMarkArea( aMarkRange
);
1125 if (bMarkIsFiltered
)
1127 ScViewUtil::UnmarkFiltered(aFilteredMark
, rDoc
);
1128 aFilteredMark
.FillRangeListWithMarks( &aRangeList
, true);
1135 nStartCol
= GetViewData().GetCurX();
1136 nStartRow
= GetViewData().GetCurY();
1137 nStartTab
= GetViewData().GetTabNo();
1138 nEndCol
= nStartCol
+ nDestSizeX
;
1139 nEndRow
= nStartRow
+ nDestSizeY
;
1140 nEndTab
= nStartTab
;
1143 bool bOffLimits
= !rDoc
.ValidCol(nEndCol
) || !rDoc
.ValidRow(nEndRow
);
1145 // target-range, as displayed:
1146 ScRange
aUserRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
);
1148 // should lines be inserted?
1149 // ( too large nEndCol/nEndRow are detected below)
1150 bool bInsertCells
= ( eMoveMode
!= INS_NONE
&& !bOffLimits
);
1153 // Instead of EnterListAction, the paste undo action is merged into the
1154 // insert action, so Repeat can insert the right cells
1156 MarkRange( aUserRange
); // set through CopyFromClip
1158 // CutMode is reset on insertion of cols/rows but needed again on cell move
1159 bool bCut
= pClipDoc
->IsCutMode();
1160 if (!InsertCells( eMoveMode
, bRecord
, true )) // is inserting possible?
1163 // #i21036# EnterListAction isn't used, and InsertCells doesn't insert
1164 // its undo action on failure, so no undo handling is needed here
1167 pClipDoc
->SetCutMode( bCut
);
1169 else if (!bOffLimits
)
1171 bool bAskIfNotEmpty
= bAllowDialogs
&&
1172 ( nFlags
& InsertDeleteFlags::CONTENTS
) &&
1173 nFunction
== ScPasteFunc::NONE
&&
1174 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1175 if ( bAskIfNotEmpty
)
1177 ScRangeList
aTestRanges(aUserRange
);
1178 if (!checkDestRangeForOverwrite(nFlags
, aTestRanges
, rDoc
, aFilteredMark
, GetViewData().GetDialogParent()))
1183 SCCOL nClipStartX
; // enlarge clipboard-range
1185 pClipDoc
->GetClipStart( nClipStartX
, nClipStartY
);
1186 SCCOL nUndoEndCol
= nClipStartX
+ nClipSizeX
;
1187 SCROW nUndoEndRow
= nClipStartY
+ nClipSizeY
; // end of source area in clipboard document
1188 bool bClipOver
= false;
1189 // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers.
1190 // The same end column/row can be used for all calls because the clip doc doesn't contain
1191 // content outside the clip area.
1192 for (SCTAB nClipTab
=0; nClipTab
< pClipDoc
->GetTableCount(); nClipTab
++)
1193 if ( pClipDoc
->HasTable(nClipTab
) )
1194 if ( pClipDoc
->ExtendMerge( nClipStartX
,nClipStartY
, nUndoEndCol
,nUndoEndRow
, nClipTab
) )
1196 nUndoEndCol
-= nClipStartX
+ nClipSizeX
;
1197 nUndoEndRow
-= nClipStartY
+ nClipSizeY
; // now contains only the difference added by ExtendMerge
1198 nUndoEndCol
= sal::static_int_cast
<SCCOL
>( nUndoEndCol
+ nEndCol
);
1199 nUndoEndRow
= sal::static_int_cast
<SCROW
>( nUndoEndRow
+ nEndRow
); // destination area, expanded for merged cells
1201 if (nUndoEndCol
>pClipDoc
->MaxCol() || nUndoEndRow
>pClipDoc
->MaxRow())
1203 ErrorMessage(STR_PASTE_FULL
);
1207 rDoc
.ExtendMergeSel( nStartCol
,nStartRow
, nUndoEndCol
,nUndoEndRow
, aFilteredMark
);
1209 // check cell-protection
1211 ScEditableTester
aTester( rDoc
, nStartTab
, nStartCol
,nStartRow
, nUndoEndCol
,nUndoEndRow
);
1212 if (!aTester
.IsEditable())
1214 ErrorMessage(aTester
.GetMessageId());
1218 //! check overlapping
1219 //! just check truly intersection !!!!!!!
1221 ScDocFunc
& rDocFunc
= pDocSh
->GetDocFunc();
1224 OUString aUndo
= ScResId( pClipDoc
->IsCutMode() ? STR_UNDO_MOVE
: STR_UNDO_COPY
);
1225 pUndoMgr
->EnterListAction( aUndo
, aUndo
, 0, GetViewData().GetViewShell()->GetViewShellId() );
1229 if (lcl_SelHasAttrib( rDoc
, nStartCol
,nStartRow
, nUndoEndCol
,nUndoEndRow
, aFilteredMark
, HasAttrFlags::Overlapped
))
1230 { // "Cell merge not possible if cells already merged"
1231 ScDocAttrIterator
aIter( rDoc
, nStartTab
, nStartCol
, nStartRow
, nUndoEndCol
, nUndoEndRow
);
1232 const ScPatternAttr
* pPattern
= nullptr;
1236 while ( ( pPattern
= aIter
.GetNext( nCol
, nRow1
, nRow2
) ) != nullptr )
1238 const ScMergeAttr
& rMergeFlag
= pPattern
->GetItem(ATTR_MERGE
);
1239 const ScMergeFlagAttr
& rMergeFlagAttr
= pPattern
->GetItem(ATTR_MERGE_FLAG
);
1240 if (rMergeFlag
.IsMerged() || rMergeFlagAttr
.IsOverlapped())
1242 ScRange
aRange(nCol
, nRow1
, nStartTab
);
1243 rDoc
.ExtendOverlapped(aRange
);
1244 rDoc
.ExtendMerge(aRange
, true);
1245 rDocFunc
.UnmergeCells(aRange
, bRecord
, nullptr /*TODO: should pass combined UndoDoc if bRecord*/);
1252 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
1254 pChangeTrack
->ResetLastCut(); // no more cut-mode
1257 bool bColInfo
= ( nStartRow
==0 && nEndRow
==rDoc
.MaxRow() );
1258 bool bRowInfo
= ( nStartCol
==0 && nEndCol
==rDoc
.MaxCol() );
1260 ScDocumentUniquePtr pUndoDoc
;
1261 std::unique_ptr
<ScDocument
> pRefUndoDoc
;
1262 std::unique_ptr
<ScRefUndoData
> pUndoData
;
1266 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
1267 pUndoDoc
->InitUndoSelected( rDoc
, aFilteredMark
, bColInfo
, bRowInfo
);
1269 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
1270 SCTAB nTabCount
= rDoc
.GetTableCount();
1271 rDoc
.CopyToDocument( nStartCol
, nStartRow
, 0, nUndoEndCol
, nUndoEndRow
, nTabCount
-1,
1272 nUndoFlags
, false, *pUndoDoc
);
1276 pRefUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
1277 pRefUndoDoc
->InitUndo( rDoc
, 0, nTabCount
-1 );
1279 pUndoData
.reset(new ScRefUndoData( &rDoc
));
1283 const bool bSingleCellBefore
= nStartCol
== nEndCol
&&
1284 nStartRow
== nEndRow
&&
1285 nStartTab
== nEndTab
;
1286 tools::Long
nBeforeHint(bSingleCellBefore
? pDocSh
->GetTwipWidthHint(ScAddress(nStartCol
, nStartRow
, nStartTab
)) : -1);
1288 sal_uInt16 nExtFlags
= 0;
1289 pDocSh
->UpdatePaintExt( nExtFlags
, nStartCol
, nStartRow
, nStartTab
,
1290 nEndCol
, nEndRow
, nEndTab
); // content before the change
1292 if (GetViewData().IsActive())
1295 InitOwnBlockMode( aUserRange
);
1297 rMark
.SetMarkArea( aUserRange
);
1300 // copy from clipboard
1301 // save original data in case of calculation
1303 ScDocumentUniquePtr pMixDoc
;
1304 if (nFunction
!= ScPasteFunc::NONE
)
1306 bSkipEmptyCells
= false;
1307 if ( nFlags
& InsertDeleteFlags::CONTENTS
)
1309 pMixDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
1310 pMixDoc
->InitUndo( rDoc
, nStartTab
, nEndTab
);
1311 rDoc
.CopyToDocument(nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
,
1312 InsertDeleteFlags::CONTENTS
, false, *pMixDoc
);
1316 /* Make draw layer and start drawing undo.
1317 - Needed before AdjustBlockHeight to track moved drawing objects.
1318 - Needed before rDoc.CopyFromClip to track inserted note caption objects.
1321 pDocSh
->MakeDrawLayer();
1323 rDoc
.BeginDrawUndo();
1325 InsertDeleteFlags nNoObjFlags
= nFlags
& ~InsertDeleteFlags::OBJECTS
;
1328 // copy normally (original range)
1329 rDoc
.CopyFromClip( aUserRange
, aFilteredMark
, nNoObjFlags
,
1330 pRefUndoDoc
.get(), pClipDoc
, true, false, bIncludeFiltered
,
1331 bSkipEmptyCells
, (bMarkIsFiltered
? &aRangeList
: nullptr) );
1333 // adapt refs manually in case of transpose
1334 if ( bTranspose
&& bCutMode
&& (nFlags
& InsertDeleteFlags::CONTENTS
) )
1335 rDoc
.UpdateTranspose( aUserRange
.aStart
, pOrigClipDoc
, aFilteredMark
, pRefUndoDoc
.get() );
1337 else if (!bTranspose
)
1339 // copy with bAsLink=TRUE
1340 rDoc
.CopyFromClip( aUserRange
, aFilteredMark
, nNoObjFlags
, pRefUndoDoc
.get(), pClipDoc
,
1341 true, true, bIncludeFiltered
, bSkipEmptyCells
);
1345 // copy all content (TransClipDoc contains only formula)
1346 rDoc
.CopyFromClip( aUserRange
, aFilteredMark
, nContFlags
, pRefUndoDoc
.get(), pClipDoc
);
1349 // skipped rows and merged cells don't mix
1350 if ( !bIncludeFiltered
&& pClipDoc
->HasClipFilteredRows() )
1351 rDocFunc
.UnmergeCells( aUserRange
, false, nullptr );
1353 rDoc
.ExtendMergeSel( nStartCol
, nStartRow
, nEndCol
, nEndRow
, aFilteredMark
, true ); // refresh
1356 if ( pMixDoc
) // calculate with original data?
1358 rDoc
.MixDocument( aUserRange
, nFunction
, bSkipEmptyCells
, *pMixDoc
);
1362 AdjustBlockHeight(); // update row heights before pasting objects
1364 ::std::vector
< OUString
> aExcludedChartNames
;
1365 SdrPage
* pPage
= nullptr;
1367 if ( nFlags
& InsertDeleteFlags::OBJECTS
)
1369 ScDrawView
* pScDrawView
= GetScDrawView();
1370 SdrModel
* pModel
= ( pScDrawView
? &pScDrawView
->GetModel() : nullptr );
1371 pPage
= ( pModel
? pModel
->GetPage( static_cast< sal_uInt16
>( nStartTab
) ) : nullptr );
1374 ScChartHelper::GetChartNames( aExcludedChartNames
, pPage
);
1377 // Paste the drawing objects after the row heights have been updated.
1379 rDoc
.CopyFromClip( aUserRange
, aFilteredMark
, InsertDeleteFlags::OBJECTS
, pRefUndoDoc
.get(), pClipDoc
,
1380 true, false, bIncludeFiltered
);
1383 pDocSh
->UpdatePaintExt( nExtFlags
, nStartCol
, nStartRow
, nStartTab
,
1384 nEndCol
, nEndRow
, nEndTab
); // content after the change
1386 // if necessary, delete autofilter-heads
1388 if (rDoc
.RefreshAutoFilter( nClipStartX
,nClipStartY
, nClipStartX
+nClipSizeX
,
1389 nClipStartY
+nClipSizeY
, nStartTab
))
1392 ScRange(nClipStartX
, nClipStartY
, nStartTab
, nClipStartX
+nClipSizeX
, nClipStartY
, nStartTab
),
1393 PaintPartFlags::Grid
);
1396 //! remove block-range on RefUndoDoc !!!
1400 ScDocumentUniquePtr pRedoDoc
;
1401 // copy redo data after appearance of the first undo
1402 // don't create Redo-Doc without RefUndoDoc
1406 pRedoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
1407 pRedoDoc
->InitUndo( rDoc
, nStartTab
, nEndTab
, bColInfo
, bRowInfo
);
1409 // move adapted refs to Redo-Doc
1411 SCTAB nTabCount
= rDoc
.GetTableCount();
1412 pRedoDoc
->AddUndoTab( 0, nTabCount
-1 );
1413 rDoc
.CopyUpdated( pRefUndoDoc
.get(), pRedoDoc
.get() );
1415 // move old refs to Undo-Doc
1418 pUndoDoc
->AddUndoTab( 0, nTabCount
-1 );
1419 pRefUndoDoc
->DeleteArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, aFilteredMark
, InsertDeleteFlags::ALL
);
1420 pRefUndoDoc
->CopyToDocument( 0,0,0, pUndoDoc
->MaxCol(), pUndoDoc
->MaxRow(), nTabCount
-1,
1421 InsertDeleteFlags::FORMULA
, false, *pUndoDoc
);
1422 pRefUndoDoc
.reset();
1425 // DeleteUnchanged for pUndoData is in ScUndoPaste ctor,
1426 // UndoData for redo is made during first undo
1428 ScUndoPasteOptions aOptions
; // store options for repeat
1429 aOptions
.nFunction
= nFunction
;
1430 aOptions
.bSkipEmptyCells
= bSkipEmptyCells
;
1431 aOptions
.bTranspose
= bTranspose
;
1432 aOptions
.bAsLink
= bAsLink
;
1433 aOptions
.eMoveMode
= eMoveMode
;
1435 std::unique_ptr
<SfxUndoAction
> pUndo(new ScUndoPaste(
1436 pDocSh
, ScRange(nStartCol
, nStartRow
, nStartTab
, nUndoEndCol
, nUndoEndRow
, nEndTab
),
1437 aFilteredMark
, std::move(pUndoDoc
), std::move(pRedoDoc
), nFlags
| nUndoFlags
, std::move(pUndoData
),
1438 false, &aOptions
)); // false = Redo data not yet copied
1442 // Merge the paste undo action into the insert action.
1443 // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action.
1445 pUndoMgr
->AddUndoAction( std::make_unique
<ScUndoWrapper
>( std::move(pUndo
) ), true );
1448 pUndoMgr
->AddUndoAction( std::move(pUndo
) );
1449 pUndoMgr
->LeaveListAction();
1452 PaintPartFlags nPaint
= PaintPartFlags::Grid
;
1455 nPaint
|= PaintPartFlags::Top
;
1456 nUndoEndCol
= rDoc
.MaxCol(); // just for drawing !
1460 nPaint
|= PaintPartFlags::Left
;
1461 nUndoEndRow
= rDoc
.MaxRow(); // just for drawing !
1464 tools::Long nMaxWidthAffectedHint
= -1;
1465 const bool bSingleCellAfter
= nStartCol
== nUndoEndCol
&&
1466 nStartRow
== nUndoEndRow
&&
1467 nStartTab
== nEndTab
;
1468 if (bSingleCellBefore
&& bSingleCellAfter
)
1470 tools::Long
nAfterHint(pDocSh
->GetTwipWidthHint(ScAddress(nStartCol
, nStartRow
, nStartTab
)));
1471 nMaxWidthAffectedHint
= std::max(nBeforeHint
, nAfterHint
);
1475 ScRange(nStartCol
, nStartRow
, nStartTab
, nUndoEndCol
, nUndoEndRow
, nEndTab
),
1476 nPaint
, nExtFlags
, nMaxWidthAffectedHint
);
1477 // AdjustBlockHeight has already been called above
1479 aModificator
.SetDocumentModified();
1480 PostPasteFromClip(aUserRange
, rMark
);
1482 if ( nFlags
& InsertDeleteFlags::OBJECTS
)
1484 ScModelObj
* pModelObj
= pDocSh
->GetModel();
1485 if ( pPage
&& pModelObj
)
1487 bool bSameDoc
= ( rClipParam
.getSourceDocID() == rDoc
.GetDocumentID() );
1488 const ScRangeListVector
& rProtectedChartRangesVector( rClipParam
.maProtectedChartRangesVector
);
1489 ScChartHelper::CreateProtectedChartListenersAndNotify( rDoc
, pPage
, pModelObj
, nStartTab
,
1490 rProtectedChartRangesVector
, aExcludedChartNames
, bSameDoc
);
1493 OUString aStartAddress
= aMarkRange
.aStart
.GetColRowString();
1494 OUString aEndAddress
= aMarkRange
.aEnd
.GetColRowString();
1495 collectUIInformation({{"RANGE", aStartAddress
+ ":" + aEndAddress
}}, u
"PASTE"_ustr
);
1499 bool ScViewFunc::PasteMultiRangesFromClip(InsertDeleteFlags nFlags
, ScDocument
* pClipDoc
,
1500 ScPasteFunc nFunction
, bool bSkipEmptyCells
,
1501 bool bTranspose
, bool bAsLink
,
1502 bool bAllowDialogs
, InsCellCmd eMoveMode
,
1503 InsertDeleteFlags nUndoFlags
)
1505 ScViewData
& rViewData
= GetViewData();
1506 ScDocument
& rDoc
= rViewData
.GetDocument();
1507 ScDocShell
* pDocSh
= rViewData
.GetDocShell();
1508 ScMarkData
aMark(rViewData
.GetMarkData());
1509 const ScAddress aCurPos
= rViewData
.GetCurPos();
1510 ScClipParam
& rClipParam
= pClipDoc
->GetClipParam();
1511 SCCOL nColSize
= rClipParam
.getPasteColSize();
1512 SCROW nRowSize
= rClipParam
.getPasteRowSize(*pClipDoc
, /*bIncludeFiltered*/false);
1516 if (static_cast<SCROW
>(aCurPos
.Col()) + nRowSize
-1 > static_cast<SCROW
>(pClipDoc
->MaxCol()))
1518 ErrorMessage(STR_PASTE_FULL
);
1522 ScDocumentUniquePtr
pTransClip(new ScDocument(SCDOCMODE_CLIP
));
1523 pClipDoc
->TransposeClip(pTransClip
.get(), nFlags
, bAsLink
, /*bIncludeFiltered*/false);
1524 pClipDoc
= pTransClip
.release();
1525 SCCOL nTempColSize
= nColSize
;
1526 nColSize
= static_cast<SCCOL
>(nRowSize
);
1527 nRowSize
= static_cast<SCROW
>(nTempColSize
);
1530 if (!rDoc
.ValidCol(aCurPos
.Col()+nColSize
-1) || !rDoc
.ValidRow(aCurPos
.Row()+nRowSize
-1))
1532 ErrorMessage(STR_PASTE_FULL
);
1536 // Determine the first and last selected sheet numbers.
1537 SCTAB nTab1
= aMark
.GetFirstSelected();
1538 SCTAB nTab2
= aMark
.GetLastSelected();
1540 ScDocShellModificator
aModificator(*pDocSh
);
1542 // For multi-selection paste, we don't support cell duplication for larger
1543 // destination range. In case the destination is marked, we reset it to
1545 ScRange
aMarkedRange(aCurPos
.Col(), aCurPos
.Row(), nTab1
,
1546 aCurPos
.Col()+nColSize
-1, aCurPos
.Row()+nRowSize
-1, nTab2
);
1548 // Extend the marked range to account for filtered rows in the destination
1550 if (ScViewUtil::HasFiltered(aMarkedRange
, rDoc
))
1552 if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange
, rDoc
, nRowSize
))
1556 bool bAskIfNotEmpty
=
1557 bAllowDialogs
&& (nFlags
& InsertDeleteFlags::CONTENTS
) &&
1558 nFunction
== ScPasteFunc::NONE
&& SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1562 ScRangeList
aTestRanges(aMarkedRange
);
1563 if (!checkDestRangeForOverwrite(nFlags
, aTestRanges
, rDoc
, aMark
, GetViewData().GetDialogParent()))
1567 aMark
.SetMarkArea(aMarkedRange
);
1568 MarkRange(aMarkedRange
);
1570 bool bInsertCells
= (eMoveMode
!= INS_NONE
);
1573 if (!InsertCells(eMoveMode
, rDoc
.IsUndoEnabled(), true))
1577 // TODO: position this call better for performance.
1578 ResetAutoSpellForContentChange();
1580 bool bRowInfo
= ( aMarkedRange
.aStart
.Col()==0 && aMarkedRange
.aEnd
.Col()==pClipDoc
->MaxCol() );
1581 ScDocumentUniquePtr pUndoDoc
;
1582 if (rDoc
.IsUndoEnabled())
1584 pUndoDoc
.reset(new ScDocument(SCDOCMODE_UNDO
));
1585 pUndoDoc
->InitUndoSelected(rDoc
, aMark
, false, bRowInfo
);
1586 rDoc
.CopyToDocument(aMarkedRange
, nUndoFlags
, false, *pUndoDoc
, &aMark
);
1589 ScDocumentUniquePtr pMixDoc
;
1590 if ( bSkipEmptyCells
|| nFunction
!= ScPasteFunc::NONE
)
1592 if ( nFlags
& InsertDeleteFlags::CONTENTS
)
1594 pMixDoc
.reset(new ScDocument(SCDOCMODE_UNDO
));
1595 pMixDoc
->InitUndoSelected(rDoc
, aMark
);
1596 rDoc
.CopyToDocument(aMarkedRange
, InsertDeleteFlags::CONTENTS
, false, *pMixDoc
, &aMark
);
1600 /* Make draw layer and start drawing undo.
1601 - Needed before AdjustBlockHeight to track moved drawing objects.
1602 - Needed before rDoc.CopyFromClip to track inserted note caption objects.
1604 if (nFlags
& InsertDeleteFlags::OBJECTS
)
1605 pDocSh
->MakeDrawLayer();
1606 if (rDoc
.IsUndoEnabled())
1607 rDoc
.BeginDrawUndo();
1609 InsertDeleteFlags nCopyFlags
= nFlags
& ~InsertDeleteFlags::OBJECTS
;
1610 // in case of transpose, links were added in TransposeClip()
1611 if (bAsLink
&& bTranspose
)
1612 nCopyFlags
|= InsertDeleteFlags::FORMULA
;
1613 rDoc
.CopyMultiRangeFromClip(aCurPos
, aMark
, nCopyFlags
, pClipDoc
, true, bAsLink
&& !bTranspose
,
1614 /*bIncludeFiltered*/false, bSkipEmptyCells
);
1617 rDoc
.MixDocument(aMarkedRange
, nFunction
, bSkipEmptyCells
, *pMixDoc
);
1619 AdjustBlockHeight(); // update row heights before pasting objects
1621 if (nFlags
& InsertDeleteFlags::OBJECTS
)
1623 // Paste the drawing objects after the row heights have been updated.
1624 rDoc
.CopyMultiRangeFromClip(aCurPos
, aMark
, InsertDeleteFlags::OBJECTS
, pClipDoc
, true,
1625 false, /*bIncludeFiltered*/false, true);
1629 pDocSh
->PostPaint(aMarkedRange
.aStart
.Col(), aMarkedRange
.aStart
.Row(), nTab1
, pClipDoc
->MaxCol(), pClipDoc
->MaxRow(), nTab1
, PaintPartFlags::Grid
|PaintPartFlags::Left
);
1632 ScRange aTmp
= aMarkedRange
;
1633 aTmp
.aStart
.SetTab(nTab1
);
1634 aTmp
.aEnd
.SetTab(nTab1
);
1635 pDocSh
->PostPaint(aTmp
, PaintPartFlags::Grid
);
1638 if (rDoc
.IsUndoEnabled())
1640 SfxUndoManager
* pUndoMgr
= pDocSh
->GetUndoManager();
1641 OUString aUndo
= ScResId(
1642 pClipDoc
->IsCutMode() ? STR_UNDO_CUT
: STR_UNDO_COPY
);
1643 pUndoMgr
->EnterListAction(aUndo
, aUndo
, 0, GetViewData().GetViewShell()->GetViewShellId());
1645 ScUndoPasteOptions aOptions
; // store options for repeat
1646 aOptions
.nFunction
= nFunction
;
1647 aOptions
.bSkipEmptyCells
= bSkipEmptyCells
;
1648 aOptions
.bTranspose
= bTranspose
;
1649 aOptions
.bAsLink
= bAsLink
;
1650 aOptions
.eMoveMode
= eMoveMode
;
1652 std::unique_ptr
<ScUndoPaste
> pUndo(new ScUndoPaste(pDocSh
,
1653 aMarkedRange
, aMark
, std::move(pUndoDoc
), nullptr, nFlags
|nUndoFlags
, nullptr, false, &aOptions
));
1656 pUndoMgr
->AddUndoAction(std::make_unique
<ScUndoWrapper
>(std::move(pUndo
)), true);
1658 pUndoMgr
->AddUndoAction(std::move(pUndo
));
1660 pUndoMgr
->LeaveListAction();
1663 aModificator
.SetDocumentModified();
1664 PostPasteFromClip(aMarkedRange
, aMark
);
1668 bool ScViewFunc::PasteFromClipToMultiRanges(
1669 InsertDeleteFlags nFlags
, ScDocument
* pClipDoc
, ScPasteFunc nFunction
,
1670 bool bSkipEmptyCells
, bool bTranspose
, bool bAsLink
, bool bAllowDialogs
,
1671 InsCellCmd eMoveMode
, InsertDeleteFlags nUndoFlags
)
1675 // We don't allow transpose for this yet.
1676 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0
);
1680 if (eMoveMode
!= INS_NONE
)
1682 // We don't allow insertion mode either. Too complicated.
1683 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0
);
1687 ScViewData
& rViewData
= GetViewData();
1688 ScClipParam
& rClipParam
= pClipDoc
->GetClipParam();
1689 if (rClipParam
.mbCutMode
)
1691 // No cut and paste with this, please.
1692 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0
);
1696 const ScAddress aCurPos
= rViewData
.GetCurPos();
1697 ScDocument
& rDoc
= rViewData
.GetDocument();
1699 ScRange aSrcRange
= rClipParam
.getWholeRange();
1700 SCROW nRowSize
= aSrcRange
.aEnd
.Row() - aSrcRange
.aStart
.Row() + 1;
1701 SCCOL nColSize
= aSrcRange
.aEnd
.Col() - aSrcRange
.aStart
.Col() + 1;
1703 if (!rDoc
.ValidCol(aCurPos
.Col()+nColSize
-1) || !rDoc
.ValidRow(aCurPos
.Row()+nRowSize
-1))
1705 ErrorMessage(STR_PASTE_FULL
);
1709 ScMarkData
aMark(rViewData
.GetMarkData());
1711 ScRangeList aRanges
;
1712 aMark
.MarkToSimple();
1713 aMark
.FillRangeListWithMarks(&aRanges
, false);
1714 if (!ScClipUtil::CheckDestRanges(rDoc
, nColSize
, nRowSize
, aMark
, aRanges
))
1716 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0
);
1720 ScDocShell
* pDocSh
= rViewData
.GetDocShell();
1722 ScDocShellModificator
aModificator(*pDocSh
);
1724 bool bAskIfNotEmpty
=
1725 bAllowDialogs
&& (nFlags
& InsertDeleteFlags::CONTENTS
) &&
1726 nFunction
== ScPasteFunc::NONE
&& SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1730 if (!checkDestRangeForOverwrite(nFlags
, aRanges
, rDoc
, aMark
, GetViewData().GetDialogParent()))
1734 // TODO: position this call better for performance.
1735 ResetAutoSpellForContentChange();
1737 ScDocumentUniquePtr pUndoDoc
;
1738 if (rDoc
.IsUndoEnabled())
1740 pUndoDoc
.reset(new ScDocument(SCDOCMODE_UNDO
));
1741 pUndoDoc
->InitUndoSelected(rDoc
, aMark
);
1742 for (size_t i
= 0, n
= aRanges
.size(); i
< n
; ++i
)
1744 rDoc
.CopyToDocument(
1745 aRanges
[i
], nUndoFlags
, false, *pUndoDoc
, &aMark
);
1749 ScDocumentUniquePtr pMixDoc
;
1750 if (bSkipEmptyCells
|| nFunction
!= ScPasteFunc::NONE
)
1752 if (nFlags
& InsertDeleteFlags::CONTENTS
)
1754 pMixDoc
.reset(new ScDocument(SCDOCMODE_UNDO
));
1755 pMixDoc
->InitUndoSelected(rDoc
, aMark
);
1756 for (size_t i
= 0, n
= aRanges
.size(); i
< n
; ++i
)
1758 rDoc
.CopyToDocument(
1759 aRanges
[i
], InsertDeleteFlags::CONTENTS
, false, *pMixDoc
, &aMark
);
1764 if (nFlags
& InsertDeleteFlags::OBJECTS
)
1765 pDocSh
->MakeDrawLayer();
1766 if (rDoc
.IsUndoEnabled())
1767 rDoc
.BeginDrawUndo();
1769 // First, paste everything but the drawing objects.
1770 for (size_t i
= 0, n
= aRanges
.size(); i
< n
; ++i
)
1773 aRanges
[i
], aMark
, (nFlags
& ~InsertDeleteFlags::OBJECTS
), nullptr, pClipDoc
,
1774 false, false, true, bSkipEmptyCells
);
1779 for (size_t i
= 0, n
= aRanges
.size(); i
< n
; ++i
)
1780 rDoc
.MixDocument(aRanges
[i
], nFunction
, bSkipEmptyCells
, *pMixDoc
);
1783 AdjustBlockHeight(); // update row heights before pasting objects
1785 // Then paste the objects.
1786 if (nFlags
& InsertDeleteFlags::OBJECTS
)
1788 for (size_t i
= 0, n
= aRanges
.size(); i
< n
; ++i
)
1791 aRanges
[i
], aMark
, InsertDeleteFlags::OBJECTS
, nullptr, pClipDoc
,
1792 false, false, true, bSkipEmptyCells
);
1796 // Refresh the range that includes all pasted ranges. We only need to
1797 // refresh the current sheet.
1798 PaintPartFlags nPaint
= PaintPartFlags::Grid
;
1799 bool bRowInfo
= (aSrcRange
.aStart
.Col()==0 && aSrcRange
.aEnd
.Col()==pClipDoc
->MaxCol());
1801 nPaint
|= PaintPartFlags::Left
;
1802 pDocSh
->PostPaint(aRanges
, nPaint
);
1804 if (rDoc
.IsUndoEnabled())
1806 SfxUndoManager
* pUndoMgr
= pDocSh
->GetUndoManager();
1807 OUString aUndo
= ScResId(
1808 pClipDoc
->IsCutMode() ? STR_UNDO_CUT
: STR_UNDO_COPY
);
1809 pUndoMgr
->EnterListAction(aUndo
, aUndo
, 0, GetViewData().GetViewShell()->GetViewShellId());
1811 ScUndoPasteOptions aOptions
; // store options for repeat
1812 aOptions
.nFunction
= nFunction
;
1813 aOptions
.bSkipEmptyCells
= bSkipEmptyCells
;
1814 aOptions
.bTranspose
= bTranspose
;
1815 aOptions
.bAsLink
= bAsLink
;
1816 aOptions
.eMoveMode
= eMoveMode
;
1819 pUndoMgr
->AddUndoAction(
1820 std::make_unique
<ScUndoPaste
>(
1821 pDocSh
, aRanges
, aMark
, std::move(pUndoDoc
), nullptr, nFlags
|nUndoFlags
, nullptr, false, &aOptions
));
1822 pUndoMgr
->LeaveListAction();
1825 aModificator
.SetDocumentModified();
1826 PostPasteFromClip(aRanges
, aMark
);
1831 void ScViewFunc::PostPasteFromClip(const ScRangeList
& rPasteRanges
, const ScMarkData
& rMark
)
1833 ScViewData
& rViewData
= GetViewData();
1834 ScDocShell
* pDocSh
= rViewData
.GetDocShell();
1835 pDocSh
->UpdateOle(rViewData
);
1837 SelectionChanged(true);
1839 ScModelObj
* pModelObj
= pDocSh
->GetModel();
1841 ScRangeList aChangeRanges
;
1842 for (size_t i
= 0, n
= rPasteRanges
.size(); i
< n
; ++i
)
1844 const ScRange
& r
= rPasteRanges
[i
];
1845 for (const auto& rTab
: rMark
)
1847 ScRange
aChangeRange(r
);
1848 aChangeRange
.aStart
.SetTab(rTab
);
1849 aChangeRange
.aEnd
.SetTab(rTab
);
1850 aChangeRanges
.push_back(aChangeRange
);
1854 if (HelperNotifyChanges::getMustPropagateChangesModel(pModelObj
))
1855 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
, u
"paste"_ustr
);
1857 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
, u
"data-area-invalidate"_ustr
);
1860 // D R A G A N D D R O P
1864 bool ScViewFunc::MoveBlockTo( const ScRange
& rSource
, const ScAddress
& rDestPos
,
1867 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1870 ResetAutoSpellForContentChange();
1872 bool bSuccess
= true;
1873 SCTAB nDestTab
= rDestPos
.Tab();
1874 const ScMarkData
& rMark
= GetViewData().GetMarkData();
1875 if ( rSource
.aStart
.Tab() == nDestTab
&& rSource
.aEnd
.Tab() == nDestTab
&& rMark
.GetSelectCount() > 1 )
1877 // moving within one table and several tables selected -> apply to all selected tables
1879 OUString aUndo
= ScResId( bCut
? STR_UNDO_MOVE
: STR_UNDO_COPY
);
1880 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, GetViewData().GetViewShell()->GetViewShellId() );
1882 // collect ranges of consecutive selected tables
1884 ScRange aLocalSource
= rSource
;
1885 ScAddress aLocalDest
= rDestPos
;
1886 SCTAB nTabCount
= pDocSh
->GetDocument().GetTableCount();
1887 SCTAB nStartTab
= 0;
1888 while ( nStartTab
< nTabCount
&& bSuccess
)
1890 while ( nStartTab
< nTabCount
&& !rMark
.GetTableSelect(nStartTab
) )
1892 if ( nStartTab
< nTabCount
)
1894 SCTAB nEndTab
= nStartTab
;
1895 while ( nEndTab
+1 < nTabCount
&& rMark
.GetTableSelect(nEndTab
+1) )
1898 aLocalSource
.aStart
.SetTab( nStartTab
);
1899 aLocalSource
.aEnd
.SetTab( nEndTab
);
1900 aLocalDest
.SetTab( nStartTab
);
1902 bSuccess
= pDocSh
->GetDocFunc().MoveBlock(
1903 aLocalSource
, aLocalDest
, bCut
, true/*bRecord*/, true/*bPaint*/, true/*bApi*/ );
1905 nStartTab
= nEndTab
+ 1;
1909 pDocSh
->GetUndoManager()->LeaveListAction();
1913 // move the block as specified
1914 bSuccess
= pDocSh
->GetDocFunc().MoveBlock(
1915 rSource
, rDestPos
, bCut
, true/*bRecord*/, true/*bPaint*/, true/*bApi*/ );
1921 // mark destination range
1923 rDestPos
.Col() + rSource
.aEnd
.Col() - rSource
.aStart
.Col(),
1924 rDestPos
.Row() + rSource
.aEnd
.Row() - rSource
.aStart
.Row(),
1927 bool bIncludeFiltered
= bCut
;
1928 if ( !bIncludeFiltered
)
1930 // find number of non-filtered rows
1931 SCROW nPastedCount
= pDocSh
->GetDocument().CountNonFilteredRows(
1932 rSource
.aStart
.Row(), rSource
.aEnd
.Row(), rSource
.aStart
.Tab());
1934 if ( nPastedCount
== 0 )
1936 aDestEnd
.SetRow( rDestPos
.Row() + nPastedCount
- 1 );
1939 MarkRange( ScRange( rDestPos
, aDestEnd
), false ); //! sal_False ???
1941 pDocSh
->UpdateOle(GetViewData());
1947 // link inside the doc
1949 bool ScViewFunc::LinkBlock( const ScRange
& rSource
, const ScAddress
& rDestPos
)
1951 // check overlapping
1953 if ( rSource
.aStart
.Tab() == rDestPos
.Tab() )
1955 SCCOL nDestEndCol
= rDestPos
.Col() + ( rSource
.aEnd
.Col() - rSource
.aStart
.Col() );
1956 SCROW nDestEndRow
= rDestPos
.Row() + ( rSource
.aEnd
.Row() - rSource
.aStart
.Row() );
1958 if ( rSource
.aStart
.Col() <= nDestEndCol
&& rDestPos
.Col() <= rSource
.aEnd
.Col() &&
1959 rSource
.aStart
.Row() <= nDestEndRow
&& rDestPos
.Row() <= rSource
.aEnd
.Row() )
1967 ScDocument
& rDoc
= GetViewData().GetDocument();
1968 ScDocumentUniquePtr
pClipDoc(new ScDocument( SCDOCMODE_CLIP
));
1969 rDoc
.CopyTabToClip( rSource
.aStart
.Col(), rSource
.aStart
.Row(),
1970 rSource
.aEnd
.Col(), rSource
.aEnd
.Row(),
1971 rSource
.aStart
.Tab(), pClipDoc
.get() );
1973 // mark destination area (set cursor, no marks)
1975 if ( GetViewData().GetTabNo() != rDestPos
.Tab() )
1976 SetTabNo( rDestPos
.Tab() );
1978 MoveCursorAbs( rDestPos
.Col(), rDestPos
.Row(), SC_FOLLOW_NONE
, false, false );
1982 PasteFromClip( InsertDeleteFlags::ALL
, pClipDoc
.get(), ScPasteFunc::NONE
, false, false, true ); // as a link
1987 void ScViewFunc::DataFormPutData( SCROW nCurrentRow
,
1988 SCROW nStartRow
, SCCOL nStartCol
,
1989 SCROW nEndRow
, SCCOL nEndCol
,
1990 std::vector
<std::unique_ptr
<ScDataFormFragment
>>& rEdits
,
1991 sal_uInt16 aColLength
)
1993 ScDocument
& rDoc
= GetViewData().GetDocument();
1994 ScDocShell
* pDocSh
= GetViewData().GetDocShell();
1995 ScMarkData
& rMark
= GetViewData().GetMarkData();
1996 ScDocShellModificator
aModificator( *pDocSh
);
1997 SfxUndoManager
* pUndoMgr
= pDocSh
->GetUndoManager();
1999 const bool bRecord( rDoc
.IsUndoEnabled());
2000 ScDocumentUniquePtr pUndoDoc
;
2001 ScDocumentUniquePtr pRedoDoc
;
2002 std::unique_ptr
<ScRefUndoData
> pUndoData
;
2003 SCTAB nTab
= GetViewData().GetTabNo();
2004 SCTAB nStartTab
= nTab
;
2005 SCTAB nEndTab
= nTab
;
2008 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
2010 pChangeTrack
->ResetLastCut(); // no more cut-mode
2012 ScRange
aUserRange( nStartCol
, nCurrentRow
, nStartTab
, nEndCol
, nCurrentRow
, nEndTab
);
2013 bool bColInfo
= ( nStartRow
==0 && nEndRow
==rDoc
.MaxRow() );
2014 bool bRowInfo
= ( nStartCol
==0 && nEndCol
==rDoc
.MaxCol() );
2015 SCCOL nUndoEndCol
= nStartCol
+aColLength
-1;
2016 SCROW nUndoEndRow
= nCurrentRow
;
2020 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
2021 pUndoDoc
->InitUndoSelected( rDoc
, rMark
, bColInfo
, bRowInfo
);
2022 rDoc
.CopyToDocument( aUserRange
, InsertDeleteFlags::VALUE
, false, *pUndoDoc
);
2024 sal_uInt16 nExtFlags
= 0;
2025 pDocSh
->UpdatePaintExt( nExtFlags
, nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
); // content before the change
2026 rDoc
.BeginDrawUndo();
2028 for(sal_uInt16 i
= 0; i
< aColLength
; i
++)
2030 if (rEdits
[i
] != nullptr)
2032 OUString aFieldName
= rEdits
[i
]->m_xEdit
->get_text();
2033 rDoc
.SetString( nStartCol
+ i
, nCurrentRow
, nTab
, aFieldName
);
2036 pDocSh
->UpdatePaintExt( nExtFlags
, nStartCol
, nCurrentRow
, nStartTab
, nEndCol
, nCurrentRow
, nEndTab
); // content after the change
2037 std::unique_ptr
<SfxUndoAction
> pUndo( new ScUndoDataForm( pDocSh
,
2038 nStartCol
, nCurrentRow
, nStartTab
,
2039 nUndoEndCol
, nUndoEndRow
, nEndTab
, rMark
,
2040 std::move(pUndoDoc
), std::move(pRedoDoc
),
2041 std::move(pUndoData
) ) );
2042 pUndoMgr
->AddUndoAction( std::make_unique
<ScUndoWrapper
>( std::move(pUndo
) ), true );
2044 PaintPartFlags nPaint
= PaintPartFlags::Grid
;
2047 nPaint
|= PaintPartFlags::Top
;
2048 nUndoEndCol
= rDoc
.MaxCol(); // just for drawing !
2052 nPaint
|= PaintPartFlags::Left
;
2053 nUndoEndRow
= rDoc
.MaxRow(); // just for drawing !
2057 ScRange(nStartCol
, nCurrentRow
, nStartTab
, nUndoEndCol
, nUndoEndRow
, nEndTab
),
2059 pDocSh
->UpdateOle(GetViewData());
2062 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */