Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "scitems.hxx"
21 : #include <svx/svdetc.hxx>
22 : #include <svx/svditer.hxx>
23 : #include <svx/svdoole2.hxx>
24 : #include <svx/svdpage.hxx>
25 : #include <sfx2/dispatch.hxx>
26 : #include <sfx2/docfile.hxx>
27 : #include <svl/stritem.hxx>
28 : #include <svl/ptitem.hxx>
29 : #include <svl/urlbmk.hxx>
30 : #include <comphelper/classids.hxx>
31 : #include <sot/formats.hxx>
32 : #include <sot/storage.hxx>
33 : #include <vcl/graph.hxx>
34 : #include <vcl/virdev.hxx>
35 : #include <vcl/msgbox.hxx>
36 : #include <tools/urlobj.hxx>
37 : #include <sot/exchange.hxx>
38 : #include <memory>
39 :
40 : #include "attrib.hxx"
41 : #include "patattr.hxx"
42 : #include "dociter.hxx"
43 : #include "viewfunc.hxx"
44 : #include "tabvwsh.hxx"
45 : #include "docsh.hxx"
46 : #include "docfunc.hxx"
47 : #include "undoblk.hxx"
48 : #include "refundo.hxx"
49 : #include "globstr.hrc"
50 : #include "global.hxx"
51 : #include "transobj.hxx"
52 : #include "drwtrans.hxx"
53 : #include "rangenam.hxx"
54 : #include "dbdata.hxx"
55 : #include "impex.hxx"
56 : #include "chgtrack.hxx"
57 : #include "waitoff.hxx"
58 : #include "scmod.hxx"
59 : #include "sc.hrc"
60 : #include "inputopt.hxx"
61 : #include "warnbox.hxx"
62 : #include "drwlayer.hxx"
63 : #include "editable.hxx"
64 : #include "docuno.hxx"
65 : #include "clipparam.hxx"
66 : #include "undodat.hxx"
67 : #include "drawview.hxx"
68 : #include "cliputil.hxx"
69 : #include <gridwin.hxx>
70 : #include <boost/scoped_ptr.hpp>
71 :
72 : using namespace com::sun::star;
73 :
74 : // STATIC DATA ---------------------------------------------------------------
75 :
76 : // GlobalName of writer-DocShell from comphelper/classids.hxx
77 :
78 : // C U T
79 :
80 0 : void ScViewFunc::CutToClip( ScDocument* pClipDoc, bool bIncludeObjects )
81 : {
82 0 : UpdateInputLine();
83 :
84 0 : ScEditableTester aTester( this );
85 0 : if (!aTester.IsEditable()) // selection editable?
86 : {
87 0 : ErrorMessage( aTester.GetMessageId() );
88 0 : return;
89 : }
90 :
91 0 : ScRange aRange; // delete this range
92 0 : if ( GetViewData().GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
93 : {
94 0 : ScDocument* pDoc = GetViewData().GetDocument();
95 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
96 0 : ScMarkData& rMark = GetViewData().GetMarkData();
97 0 : const bool bRecord(pDoc->IsUndoEnabled()); // Undo/Redo
98 :
99 0 : ScDocShellModificator aModificator( *pDocSh );
100 :
101 0 : if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) // mark the range if not marked yet
102 : {
103 0 : DoneBlockMode();
104 0 : InitOwnBlockMode();
105 0 : rMark.SetMarkArea( aRange );
106 0 : MarkDataChanged();
107 : }
108 :
109 0 : CopyToClip( pClipDoc, true, false, bIncludeObjects ); // copy to clipboard
110 :
111 0 : ScAddress aOldEnd( aRange.aEnd ); // combined cells in this range?
112 0 : pDoc->ExtendMerge( aRange, true );
113 :
114 0 : ScDocument* pUndoDoc = NULL;
115 0 : if ( bRecord )
116 : {
117 0 : pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
118 0 : pUndoDoc->InitUndoSelected( pDoc, rMark );
119 : // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
120 0 : ScRange aCopyRange = aRange;
121 0 : aCopyRange.aStart.SetTab(0);
122 0 : aCopyRange.aEnd.SetTab(pDoc->GetTableCount()-1);
123 0 : pDoc->CopyToDocument( aCopyRange, (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS, false, pUndoDoc );
124 0 : pDoc->BeginDrawUndo();
125 : }
126 :
127 0 : sal_uInt16 nExtFlags = 0;
128 0 : pDocSh->UpdatePaintExt( nExtFlags, aRange );
129 :
130 0 : rMark.MarkToMulti();
131 0 : pDoc->DeleteSelection( IDF_ALL, rMark );
132 0 : if ( bIncludeObjects )
133 0 : pDoc->DeleteObjectsInSelection( rMark );
134 0 : rMark.MarkToSimple();
135 :
136 0 : if ( !AdjustRowHeight( aRange.aStart.Row(), aRange.aEnd.Row() ) )
137 0 : pDocSh->PostPaint( aRange, PAINT_GRID, nExtFlags );
138 :
139 0 : if ( bRecord ) // Draw-Undo now available
140 0 : pDocSh->GetUndoManager()->AddUndoAction(
141 0 : new ScUndoCut( pDocSh, aRange, aOldEnd, rMark, pUndoDoc ) );
142 :
143 0 : aModificator.SetDocumentModified();
144 0 : pDocSh->UpdateOle(&GetViewData());
145 :
146 0 : CellContentChanged();
147 : }
148 : else
149 0 : ErrorMessage( STR_NOMULTISELECT );
150 : }
151 :
152 : // C O P Y
153 :
154 12 : bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, bool bCut, bool bApi, bool bIncludeObjects, bool bStopEdit )
155 : {
156 12 : ScRange aRange;
157 12 : ScMarkType eMarkType = GetViewData().GetSimpleArea( aRange );
158 12 : ScMarkData& rMark = GetViewData().GetMarkData();
159 12 : bool bDone = false;
160 :
161 12 : if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
162 : {
163 12 : ScRangeList aRangeList;
164 12 : aRangeList.Append( aRange );
165 12 : bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, false );
166 : }
167 0 : else if (eMarkType == SC_MARK_MULTI)
168 : {
169 0 : ScRangeList aRangeList;
170 0 : rMark.MarkToSimple();
171 0 : rMark.FillRangeListWithMarks(&aRangeList, false);
172 0 : bDone = CopyToClip( pClipDoc, aRangeList, bCut, bApi, bIncludeObjects, bStopEdit, false );
173 : }
174 : else
175 : {
176 0 : if (!bApi)
177 0 : ErrorMessage(STR_NOMULTISELECT);
178 : }
179 :
180 12 : return bDone;
181 : }
182 :
183 : // Copy the content of the Range into clipboard.
184 12 : bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRangeList& rRanges, bool bCut, bool bApi, bool bIncludeObjects, bool bStopEdit, bool bUseRangeForVBA )
185 : {
186 12 : if ( rRanges.empty() )
187 0 : return false;
188 12 : bool bDone = false;
189 12 : if ( bStopEdit )
190 11 : UpdateInputLine();
191 :
192 12 : ScRange aRange = *rRanges[0];
193 12 : ScClipParam aClipParam( aRange, bCut );
194 12 : aClipParam.maRanges = rRanges;
195 :
196 12 : ScDocument* pDoc = GetViewData().GetDocument();
197 12 : ScMarkData& rMark = GetViewData().GetMarkData();
198 :
199 12 : if ( !aClipParam.isMultiRange() )
200 : {
201 12 : if ( pDoc && ( !pDoc->HasSelectedBlockMatrixFragment( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), rMark ) ) )
202 : {
203 12 : bool bSysClip = false;
204 12 : if ( !pClipDoc ) // no clip doc specified
205 : {
206 : // Create one (deleted by ScTransferObj).
207 11 : pClipDoc = new ScDocument( SCDOCMODE_CLIP );
208 11 : bSysClip = true; // and copy into system
209 : }
210 12 : if ( !bCut )
211 : {
212 12 : ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
213 12 : if ( pChangeTrack )
214 0 : pChangeTrack->ResetLastCut();
215 : }
216 :
217 12 : if ( bSysClip && bIncludeObjects )
218 : {
219 11 : bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange );
220 : // Update ScGlobal::pDrawClipDocShellRef.
221 11 : ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
222 : }
223 :
224 12 : if ( !bUseRangeForVBA )
225 : // is this necessary?, will setting the doc id upset the
226 : // following paste operation with range? would be nicer to just set this always
227 : // and lose the 'if' above
228 12 : aClipParam.setSourceDocID( pDoc->GetDocumentID() );
229 :
230 12 : pDoc->CopyToClip( aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
231 12 : if ( !bUseRangeForVBA && pDoc && pClipDoc )
232 : {
233 12 : ScDrawLayer* pDrawLayer = pClipDoc->GetDrawLayer();
234 12 : if ( pDrawLayer )
235 : {
236 0 : ScClipParam& rClipParam = pClipDoc->GetClipParam();
237 0 : ScRangeListVector& rRangesVector = rClipParam.maProtectedChartRangesVector;
238 0 : SCTAB nTabCount = pClipDoc->GetTableCount();
239 0 : for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab )
240 : {
241 0 : SdrPage* pPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) );
242 0 : if ( pPage )
243 : {
244 0 : ScChartHelper::FillProtectedChartRangesVector( rRangesVector, pDoc, pPage );
245 : }
246 : }
247 : }
248 : }
249 :
250 12 : if ( bSysClip )
251 : {
252 11 : ScDrawLayer::SetGlobalDrawPersist(NULL);
253 11 : ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) );
254 : }
255 12 : pClipDoc->ExtendMerge( aRange, true );
256 :
257 12 : if ( bSysClip )
258 : {
259 11 : ScDocShell* pDocSh = GetViewData().GetDocShell();
260 11 : TransferableObjectDescriptor aObjDesc;
261 11 : pDocSh->FillTransferableObjectDescriptor( aObjDesc );
262 11 : aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
263 : // maSize is set in ScTransferObj ctor
264 :
265 11 : ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
266 22 : uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
267 11 : if ( ScGlobal::pDrawClipDocShellRef )
268 : {
269 0 : SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
270 0 : pTransferObj->SetDrawPersist( aPersistRef );// keep persist for ole objects alive
271 :
272 : }
273 11 : pTransferObj->CopyToClipboard( GetActiveWin() );
274 22 : SC_MOD()->SetClipObject( pTransferObj, NULL );
275 : }
276 :
277 12 : bDone = true;
278 : }
279 : }
280 : else
281 : {
282 0 : bool bSuccess = false;
283 0 : aClipParam.mbCutMode = false;
284 :
285 : do
286 : {
287 0 : if (bCut)
288 : // We con't support cutting of multi-selections.
289 0 : break;
290 :
291 0 : if (pClipDoc)
292 : // TODO: What's this for?
293 0 : break;
294 :
295 0 : ::std::unique_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
296 :
297 : // Check for geometrical feasibility of the ranges.
298 0 : bool bValidRanges = true;
299 0 : ScRange* p = aClipParam.maRanges.front();
300 0 : SCCOL nPrevColDelta = 0;
301 0 : SCROW nPrevRowDelta = 0;
302 0 : SCCOL nPrevCol = p->aStart.Col();
303 0 : SCROW nPrevRow = p->aStart.Row();
304 0 : SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
305 0 : SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
306 0 : for ( size_t i = 1; i < aClipParam.maRanges.size(); ++i )
307 : {
308 0 : p = aClipParam.maRanges[i];
309 0 : if ( pDoc->HasSelectedBlockMatrixFragment(
310 0 : p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark) )
311 : {
312 0 : if (!bApi)
313 0 : ErrorMessage(STR_MATRIXFRAGMENTERR);
314 0 : return false;
315 : }
316 :
317 0 : SCCOL nColDelta = p->aStart.Col() - nPrevCol;
318 0 : SCROW nRowDelta = p->aStart.Row() - nPrevRow;
319 :
320 0 : if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
321 : {
322 0 : bValidRanges = false;
323 0 : break;
324 : }
325 :
326 0 : if (aClipParam.meDirection == ScClipParam::Unspecified)
327 : {
328 0 : if (nColDelta)
329 0 : aClipParam.meDirection = ScClipParam::Column;
330 0 : if (nRowDelta)
331 0 : aClipParam.meDirection = ScClipParam::Row;
332 : }
333 :
334 0 : SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
335 0 : SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
336 :
337 0 : if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
338 : {
339 : // column-oriented ranges must have identical row size.
340 0 : bValidRanges = false;
341 0 : break;
342 : }
343 0 : if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
344 : {
345 : // likewise, row-oriented ranges must have identical
346 : // column size.
347 0 : bValidRanges = false;
348 0 : break;
349 : }
350 :
351 0 : nPrevCol = p->aStart.Col();
352 0 : nPrevRow = p->aStart.Row();
353 0 : nPrevColDelta = nColDelta;
354 0 : nPrevRowDelta = nRowDelta;
355 0 : nPrevColSize = nColSize;
356 0 : nPrevRowSize = nRowSize;
357 : }
358 0 : if (!bValidRanges)
359 0 : break;
360 0 : pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, false, bIncludeObjects, true, bUseRangeForVBA );
361 :
362 0 : ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
363 0 : if ( pChangeTrack )
364 0 : pChangeTrack->ResetLastCut(); // no more cut-mode
365 :
366 : {
367 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
368 0 : TransferableObjectDescriptor aObjDesc;
369 0 : pDocSh->FillTransferableObjectDescriptor( aObjDesc );
370 0 : aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
371 : // maSize is set in ScTransferObj ctor
372 :
373 0 : ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
374 0 : uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
375 :
376 0 : if ( ScGlobal::pDrawClipDocShellRef )
377 : {
378 0 : SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
379 0 : pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
380 : }
381 :
382 0 : pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
383 0 : SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
384 : }
385 :
386 0 : bSuccess = true;
387 : }
388 : while (false);
389 :
390 0 : if (!bSuccess && !bApi)
391 0 : ErrorMessage(STR_NOMULTISELECT);
392 :
393 0 : bDone = bSuccess;
394 : }
395 :
396 12 : return bDone;
397 : }
398 :
399 0 : ScTransferObj* ScViewFunc::CopyToTransferable()
400 : {
401 0 : ScRange aRange;
402 0 : if ( GetViewData().GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
403 : {
404 0 : ScDocument* pDoc = GetViewData().GetDocument();
405 0 : ScMarkData& rMark = GetViewData().GetMarkData();
406 0 : if ( !pDoc->HasSelectedBlockMatrixFragment(
407 0 : aRange.aStart.Col(), aRange.aStart.Row(),
408 0 : aRange.aEnd.Col(), aRange.aEnd.Row(),
409 0 : rMark ) )
410 : {
411 0 : ScDocument *pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj)
412 :
413 0 : bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
414 0 : ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
415 :
416 0 : ScClipParam aClipParam(aRange, false);
417 0 : pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true);
418 :
419 0 : ScDrawLayer::SetGlobalDrawPersist(NULL);
420 0 : pClipDoc->ExtendMerge( aRange, true );
421 :
422 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
423 0 : TransferableObjectDescriptor aObjDesc;
424 0 : pDocSh->FillTransferableObjectDescriptor( aObjDesc );
425 0 : aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
426 0 : ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
427 0 : return pTransferObj;
428 : }
429 : }
430 :
431 0 : return NULL;
432 : }
433 :
434 : // P A S T E
435 :
436 0 : void ScViewFunc::PasteDraw()
437 : {
438 0 : ScViewData& rViewData = GetViewData();
439 0 : SCCOL nPosX = rViewData.GetCurX();
440 0 : SCROW nPosY = rViewData.GetCurY();
441 0 : vcl::Window* pWin = GetActiveWin();
442 : Point aPos = pWin->PixelToLogic( rViewData.GetScrPos( nPosX, nPosY,
443 0 : rViewData.GetActivePart() ) );
444 0 : ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
445 0 : if (pDrawClip)
446 : {
447 0 : OUString aSrcShellID = pDrawClip->GetShellID();
448 0 : OUString aDestShellID = SfxObjectShell::CreateShellID(rViewData.GetDocShell());
449 0 : PasteDraw(aPos, pDrawClip->GetModel(), false, aSrcShellID, aDestShellID);
450 : }
451 0 : }
452 :
453 3 : void ScViewFunc::PasteFromSystem()
454 : {
455 3 : UpdateInputLine();
456 :
457 3 : vcl::Window* pWin = GetActiveWin();
458 3 : ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
459 3 : ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
460 :
461 3 : if (pOwnClip)
462 : {
463 : // keep a reference in case the clipboard is changed during PasteFromClip
464 0 : uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
465 : PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
466 : PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
467 0 : true ); // allow warning dialog
468 : }
469 3 : else if (pDrawClip)
470 0 : PasteDraw();
471 : else
472 : {
473 3 : TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
474 :
475 : {
476 3 : SotClipboardFormatId nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
477 3 : SotClipboardFormatId nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
478 :
479 3 : SotExchangeDest nDestination = SotExchangeDest::SCDOC_FREE_AREA;
480 3 : sal_uInt16 nSourceOptions = EXCHG_IN_ACTION_COPY;
481 : SotClipboardFormatId nFormat; // output param for GetExchangeAction
482 : sal_uInt16 nEventAction; // output param for GetExchangeAction
483 :
484 3 : uno::Reference<com::sun::star::datatransfer::XTransferable> xTransferable( aDataHelper.GetXTransferable() );
485 : sal_uInt16 nAction = SotExchange::GetExchangeAction(
486 3 : aDataHelper.GetDataFlavorExVector(),
487 : nDestination,
488 : nSourceOptions,
489 : EXCHG_IN_ACTION_DEFAULT,
490 : nFormat, nEventAction, SotClipboardFormatId::NONE,
491 6 : &xTransferable );
492 :
493 3 : if ( nAction != EXCHG_INOUT_ACTION_NONE )
494 : {
495 0 : nAction = ( nAction & EXCHG_ACTION_MASK );
496 :
497 0 : switch( nAction )
498 : {
499 : case EXCHG_OUT_ACTION_INSERT_SVXB:
500 : case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE:
501 : case EXCHG_OUT_ACTION_INSERT_BITMAP:
502 : case EXCHG_OUT_ACTION_INSERT_GRAPH:
503 : // SotClipboardFormatId::BITMAP
504 : // SotClipboardFormatId::PNG
505 : // SotClipboardFormatId::GDIMETAFILE
506 : // SotClipboardFormatId::SVXB
507 0 : PasteFromSystem(nFormat);
508 0 : break;
509 : default:
510 0 : nAction = EXCHG_INOUT_ACTION_NONE;
511 : }
512 : }
513 :
514 3 : if ( nAction == EXCHG_INOUT_ACTION_NONE )
515 : {
516 : // first SvDraw-model, then drawing
517 : // (only one drawing is allowed)
518 :
519 3 : if (aDataHelper.HasFormat( SotClipboardFormatId::DRAWING ))
520 : {
521 : // special case for tables from drawing
522 0 : if( aDataHelper.HasFormat( SotClipboardFormatId::RTF ) )
523 : {
524 0 : PasteFromSystem( SotClipboardFormatId::RTF );
525 : }
526 : else
527 : {
528 0 : PasteFromSystem( SotClipboardFormatId::DRAWING );
529 : }
530 : }
531 3 : else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBED_SOURCE ))
532 : {
533 : // If it's a Writer object, insert RTF instead of OLE
534 :
535 : // Else, if the class id is all-zero, and SYLK is available,
536 : // it probably is spreadsheet cells that have been put
537 : // on the clipboard by OOo, so use the SYLK. (fdo#31077)
538 :
539 0 : bool bDoRtf = false;
540 0 : TransferableObjectDescriptor aObjDesc;
541 0 : if( aDataHelper.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc ) )
542 : {
543 0 : bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
544 0 : aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
545 0 : && aDataHelper.HasFormat( SotClipboardFormatId::RTF ) );
546 : }
547 0 : if ( bDoRtf )
548 0 : PasteFromSystem( SotClipboardFormatId::RTF );
549 0 : else if ( aObjDesc.maClassName == SvGlobalName( 0,0,0,0,0,0,0,0,0,0,0 )
550 0 : && aDataHelper.HasFormat( SotClipboardFormatId::SYLK ))
551 0 : PasteFromSystem( SotClipboardFormatId::SYLK );
552 : else
553 0 : PasteFromSystem( SotClipboardFormatId::EMBED_SOURCE );
554 : }
555 3 : else if (aDataHelper.HasFormat( SotClipboardFormatId::LINK_SOURCE ))
556 0 : PasteFromSystem( SotClipboardFormatId::LINK_SOURCE );
557 : // the following format can not affect scenario from #89579#
558 3 : else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE ))
559 0 : PasteFromSystem( SotClipboardFormatId::EMBEDDED_OBJ_OLE );
560 : // SotClipboardFormatId::PRIVATE no longer here (can't work if pOwnClip is NULL)
561 3 : else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
562 0 : PasteFromSystem(nBiff8);
563 3 : else if (aDataHelper.HasFormat(nBiff5))
564 0 : PasteFromSystem(nBiff5);
565 3 : else if (aDataHelper.HasFormat(SotClipboardFormatId::RTF))
566 0 : PasteFromSystem(SotClipboardFormatId::RTF);
567 3 : else if (aDataHelper.HasFormat(SotClipboardFormatId::HTML))
568 0 : PasteFromSystem(SotClipboardFormatId::HTML);
569 3 : else if (aDataHelper.HasFormat(SotClipboardFormatId::HTML_SIMPLE))
570 0 : PasteFromSystem(SotClipboardFormatId::HTML_SIMPLE);
571 3 : else if (aDataHelper.HasFormat(SotClipboardFormatId::SYLK))
572 0 : PasteFromSystem(SotClipboardFormatId::SYLK);
573 3 : else if (aDataHelper.HasFormat(SotClipboardFormatId::STRING))
574 0 : PasteFromSystem(SotClipboardFormatId::STRING);
575 : // xxx_OLE formats come last, like in SotExchange tables
576 3 : else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBED_SOURCE_OLE ))
577 0 : PasteFromSystem( SotClipboardFormatId::EMBED_SOURCE_OLE );
578 3 : else if (aDataHelper.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE ))
579 0 : PasteFromSystem( SotClipboardFormatId::LINK_SOURCE_OLE );
580 3 : }
581 3 : }
582 : }
583 : // no exception-> SID_PASTE has FastCall-flag from idl
584 : // will be called in case of empty clipboard (#42531#)
585 3 : }
586 :
587 0 : void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTransferable>& rxTransferable )
588 : {
589 0 : ScTransferObj *pOwnClip=0;
590 0 : ScDrawTransferObj *pDrawClip=0;
591 0 : uno::Reference<lang::XUnoTunnel> xTunnel( rxTransferable, uno::UNO_QUERY );
592 0 : if ( xTunnel.is() )
593 : {
594 0 : sal_Int64 nHandle = xTunnel->getSomething( ScTransferObj::getUnoTunnelId() );
595 0 : if ( nHandle )
596 0 : pOwnClip = reinterpret_cast<ScTransferObj*>( (sal_IntPtr) nHandle);
597 : else
598 : {
599 0 : nHandle = xTunnel->getSomething( ScDrawTransferObj::getUnoTunnelId() );
600 0 : if ( nHandle )
601 0 : pDrawClip = reinterpret_cast<ScDrawTransferObj*>( (sal_IntPtr) nHandle );
602 : }
603 : }
604 :
605 0 : if (pOwnClip)
606 : {
607 : PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
608 : PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
609 0 : true ); // allow warning dialog
610 : }
611 0 : else if (pDrawClip)
612 : {
613 0 : ScViewData& rViewData = GetViewData();
614 0 : SCCOL nPosX = rViewData.GetCurX();
615 0 : SCROW nPosY = rViewData.GetCurY();
616 0 : vcl::Window* pWin = GetActiveWin();
617 0 : Point aPos = pWin->PixelToLogic( rViewData.GetScrPos( nPosX, nPosY, rViewData.GetActivePart() ) );
618 : PasteDraw(
619 : aPos, pDrawClip->GetModel(), false,
620 0 : pDrawClip->GetShellID(), SfxObjectShell::CreateShellID(rViewData.GetDocShell()));
621 : }
622 : else
623 : {
624 0 : TransferableDataHelper aDataHelper( rxTransferable );
625 : {
626 0 : SotClipboardFormatId nBiff8 = SotExchange::RegisterFormatName(OUString("Biff8"));
627 0 : SotClipboardFormatId nBiff5 = SotExchange::RegisterFormatName(OUString("Biff5"));
628 0 : SotClipboardFormatId nFormatId = SotClipboardFormatId::NONE;
629 : // first SvDraw-model, then drawing
630 : // (only one drawing is allowed)
631 :
632 0 : if (aDataHelper.HasFormat( SotClipboardFormatId::DRAWING ))
633 0 : nFormatId = SotClipboardFormatId::DRAWING;
634 0 : else if (aDataHelper.HasFormat( SotClipboardFormatId::SVXB ))
635 0 : nFormatId = SotClipboardFormatId::SVXB;
636 0 : else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBED_SOURCE ))
637 : {
638 : // If it's a Writer object, insert RTF instead of OLE
639 0 : bool bDoRtf = false;
640 0 : TransferableObjectDescriptor aObjDesc;
641 0 : if( aDataHelper.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc ) )
642 : {
643 0 : bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
644 0 : aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
645 0 : && aDataHelper.HasFormat( SotClipboardFormatId::RTF ) );
646 : }
647 0 : if ( bDoRtf )
648 0 : nFormatId = SotClipboardFormatId::RTF;
649 : else
650 0 : nFormatId = SotClipboardFormatId::EMBED_SOURCE;
651 : }
652 0 : else if (aDataHelper.HasFormat( SotClipboardFormatId::LINK_SOURCE ))
653 0 : nFormatId = SotClipboardFormatId::LINK_SOURCE;
654 : // the following format can not affect scenario from #89579#
655 0 : else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE ))
656 0 : nFormatId = SotClipboardFormatId::EMBEDDED_OBJ_OLE;
657 : // SotClipboardFormatId::PRIVATE no longer here (can't work if pOwnClip is NULL)
658 0 : else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
659 0 : nFormatId = nBiff8;
660 0 : else if (aDataHelper.HasFormat(nBiff5))
661 0 : nFormatId = nBiff5;
662 0 : else if (aDataHelper.HasFormat(SotClipboardFormatId::RTF))
663 0 : nFormatId = SotClipboardFormatId::RTF;
664 0 : else if (aDataHelper.HasFormat(SotClipboardFormatId::HTML))
665 0 : nFormatId = SotClipboardFormatId::HTML;
666 0 : else if (aDataHelper.HasFormat(SotClipboardFormatId::HTML_SIMPLE))
667 0 : nFormatId = SotClipboardFormatId::HTML_SIMPLE;
668 0 : else if (aDataHelper.HasFormat(SotClipboardFormatId::SYLK))
669 0 : nFormatId = SotClipboardFormatId::SYLK;
670 0 : else if (aDataHelper.HasFormat(SotClipboardFormatId::STRING))
671 0 : nFormatId = SotClipboardFormatId::STRING;
672 0 : else if (aDataHelper.HasFormat(SotClipboardFormatId::GDIMETAFILE))
673 0 : nFormatId = SotClipboardFormatId::GDIMETAFILE;
674 0 : else if (aDataHelper.HasFormat(SotClipboardFormatId::BITMAP))
675 0 : nFormatId = SotClipboardFormatId::BITMAP;
676 : // xxx_OLE formats come last, like in SotExchange tables
677 0 : else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBED_SOURCE_OLE ))
678 0 : nFormatId = SotClipboardFormatId::EMBED_SOURCE_OLE;
679 0 : else if (aDataHelper.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE ))
680 0 : nFormatId = SotClipboardFormatId::LINK_SOURCE_OLE;
681 : else
682 0 : return;
683 :
684 0 : PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
685 0 : GetViewData().GetCurX(), GetViewData().GetCurY(),
686 0 : NULL, false, false );
687 0 : }
688 0 : }
689 : }
690 :
691 0 : bool ScViewFunc::PasteFromSystem( SotClipboardFormatId nFormatId, bool bApi )
692 : {
693 0 : UpdateInputLine();
694 :
695 0 : bool bRet = true;
696 0 : vcl::Window* pWin = GetActiveWin();
697 0 : ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
698 0 : if ( nFormatId == SotClipboardFormatId::NONE && pOwnClip )
699 : {
700 : // keep a reference in case the clipboard is changed during PasteFromClip
701 0 : uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
702 : PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
703 : PASTE_NOFUNC, false, false, false, INS_NONE, IDF_NONE,
704 0 : !bApi ); // allow warning dialog
705 : }
706 : else
707 : {
708 0 : TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
709 0 : if ( !aDataHelper.GetTransferable().is() )
710 0 : return false;
711 :
712 0 : SCCOL nPosX = 0;
713 0 : SCROW nPosY = 0;
714 :
715 0 : ScViewData& rViewData = GetViewData();
716 0 : ScRange aRange;
717 0 : if ( rViewData.GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
718 : {
719 0 : nPosX = aRange.aStart.Col();
720 0 : nPosY = aRange.aStart.Row();
721 : }
722 : else
723 : {
724 0 : nPosX = rViewData.GetCurX();
725 0 : nPosY = rViewData.GetCurY();
726 : }
727 :
728 0 : bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
729 : nPosX, nPosY,
730 0 : NULL, false, !bApi ); // allow warning dialog
731 :
732 0 : if ( !bRet && !bApi )
733 0 : ErrorMessage(STR_PASTE_ERROR);
734 : }
735 0 : return bRet;
736 : }
737 :
738 : // P A S T E
739 :
740 0 : bool ScViewFunc::PasteOnDrawObjectLinked(
741 : const uno::Reference<datatransfer::XTransferable>& rxTransferable,
742 : SdrObject& rHitObj)
743 : {
744 0 : TransferableDataHelper aDataHelper( rxTransferable );
745 :
746 0 : if ( aDataHelper.HasFormat( SotClipboardFormatId::SVXB ) )
747 : {
748 0 : tools::SvRef<SotStorageStream> xStm;
749 0 : ScDrawView* pScDrawView = GetScDrawView();
750 :
751 0 : if( pScDrawView && aDataHelper.GetSotStorageStream( SotClipboardFormatId::SVXB, xStm ) )
752 : {
753 0 : Graphic aGraphic;
754 :
755 0 : ReadGraphic( *xStm, aGraphic );
756 :
757 0 : const OUString aEmpty;
758 0 : const OUString aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
759 :
760 0 : if(pScDrawView->ApplyGraphicToObject( rHitObj, aGraphic, aBeginUndo, aEmpty, aEmpty ))
761 : {
762 0 : return true;
763 0 : }
764 0 : }
765 : }
766 0 : else if ( aDataHelper.HasFormat( SotClipboardFormatId::GDIMETAFILE ) )
767 : {
768 0 : GDIMetaFile aMtf;
769 0 : ScDrawView* pScDrawView = GetScDrawView();
770 :
771 0 : if( pScDrawView && aDataHelper.GetGDIMetaFile( SotClipboardFormatId::GDIMETAFILE, aMtf ) )
772 : {
773 0 : const OUString aEmpty;
774 0 : const OUString aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
775 :
776 0 : if(pScDrawView->ApplyGraphicToObject( rHitObj, Graphic(aMtf), aBeginUndo, aEmpty, aEmpty ))
777 : {
778 0 : return true;
779 0 : }
780 0 : }
781 : }
782 0 : else if ( aDataHelper.HasFormat( SotClipboardFormatId::BITMAP ) || aDataHelper.HasFormat( SotClipboardFormatId::PNG ) )
783 : {
784 0 : BitmapEx aBmpEx;
785 0 : ScDrawView* pScDrawView = GetScDrawView();
786 :
787 0 : if( pScDrawView && aDataHelper.GetBitmapEx( SotClipboardFormatId::BITMAP, aBmpEx ) )
788 : {
789 0 : const OUString aEmpty;
790 0 : const OUString aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
791 :
792 0 : if(pScDrawView->ApplyGraphicToObject( rHitObj, Graphic(aBmpEx), aBeginUndo, aEmpty, aEmpty ))
793 : {
794 0 : return true;
795 0 : }
796 0 : }
797 : }
798 :
799 0 : return false;
800 : }
801 :
802 0 : static bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
803 : const ScMarkData& rTabSelection, sal_uInt16 nMask )
804 : {
805 0 : ScMarkData::const_iterator itr = rTabSelection.begin(), itrEnd = rTabSelection.end();
806 0 : for (; itr != itrEnd; ++itr)
807 0 : if ( pDoc->HasAttrib( nCol1, nRow1, *itr, nCol2, nRow2, *itr, nMask ) )
808 0 : return true;
809 0 : return false;
810 : }
811 :
812 : // paste into sheet:
813 :
814 : // internal paste
815 :
816 : namespace {
817 :
818 0 : bool checkDestRangeForOverwrite(const ScRangeList& rDestRanges, const ScDocument* pDoc, const ScMarkData& rMark, vcl::Window* pParentWnd)
819 : {
820 0 : bool bIsEmpty = true;
821 0 : ScMarkData::const_iterator itrTab = rMark.begin(), itrTabEnd = rMark.end();
822 0 : size_t nRangeSize = rDestRanges.size();
823 0 : for (; itrTab != itrTabEnd && bIsEmpty; ++itrTab)
824 : {
825 0 : for (size_t i = 0; i < nRangeSize && bIsEmpty; ++i)
826 : {
827 0 : const ScRange& rRange = *rDestRanges[i];
828 : bIsEmpty = pDoc->IsBlockEmpty(
829 0 : *itrTab, rRange.aStart.Col(), rRange.aStart.Row(),
830 0 : rRange.aEnd.Col(), rRange.aEnd.Row());
831 : }
832 : }
833 :
834 0 : if (!bIsEmpty)
835 : {
836 0 : ScopedVclPtrInstance< ScReplaceWarnBox > aBox(pParentWnd);
837 0 : if (aBox->Execute() != RET_YES)
838 : {
839 : // changing the configuration is within the ScReplaceWarnBox
840 0 : return false;
841 0 : }
842 : }
843 0 : return true;
844 : }
845 :
846 : }
847 :
848 29 : bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc,
849 : sal_uInt16 nFunction, bool bSkipEmpty,
850 : bool bTranspose, bool bAsLink,
851 : InsCellCmd eMoveMode, InsertDeleteFlags nUndoExtraFlags,
852 : bool bAllowDialogs )
853 : {
854 29 : if (!pClipDoc)
855 : {
856 : OSL_FAIL("PasteFromClip: pClipDoc=0 not allowed");
857 12 : return false;
858 : }
859 :
860 : // undo: save all or no content
861 17 : InsertDeleteFlags nContFlags = IDF_NONE;
862 17 : if (nFlags & IDF_CONTENTS)
863 17 : nContFlags |= IDF_CONTENTS;
864 17 : if (nFlags & IDF_ATTRIB)
865 17 : nContFlags |= IDF_ATTRIB;
866 : // move attributes to undo without copying them from clip to doc
867 17 : InsertDeleteFlags nUndoFlags = nContFlags;
868 17 : if (nUndoExtraFlags & IDF_ATTRIB)
869 0 : nUndoFlags |= IDF_ATTRIB;
870 : // do not copy note captions into undo document
871 17 : nUndoFlags |= IDF_NOCAPTIONS;
872 :
873 17 : ScClipParam& rClipParam = pClipDoc->GetClipParam();
874 17 : if (rClipParam.isMultiRange())
875 : {
876 : // Source data is multi-range.
877 : return PasteMultiRangesFromClip(
878 : nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
879 0 : eMoveMode, nUndoFlags);
880 : }
881 :
882 17 : ScMarkData& rMark = GetViewData().GetMarkData();
883 17 : if (rMark.IsMultiMarked())
884 : {
885 : // Source data is single-range but destination is multi-range.
886 : return PasteFromClipToMultiRanges(
887 : nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
888 0 : eMoveMode, nUndoFlags);
889 : }
890 :
891 17 : bool bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
892 17 : bool bIncludeFiltered = bCutMode;
893 :
894 : // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions)
895 17 : bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) );
896 :
897 17 : ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip
898 17 : ScDocument* pOrigClipDoc = NULL;
899 34 : ::std::unique_ptr< ScDocument > xTransClip;
900 17 : if ( bTranspose )
901 : {
902 : SCCOL nX;
903 : SCROW nY;
904 : // include filtered rows until TransposeClip can skip them
905 0 : bIncludeFiltered = true;
906 0 : pClipDoc->GetClipArea( nX, nY, true );
907 0 : if ( nY > static_cast<sal_Int32>(MAXCOL) ) // to many lines for transpose
908 : {
909 0 : ErrorMessage(STR_PASTE_FULL);
910 0 : return false;
911 : }
912 0 : pOrigClipDoc = pClipDoc; // refs
913 :
914 0 : if ( bPasteDraw )
915 : {
916 0 : aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately
917 0 : aTransShellRef->DoInitNew(NULL);
918 : }
919 0 : ScDrawLayer::SetGlobalDrawPersist(aTransShellRef);
920 :
921 0 : xTransClip.reset( new ScDocument( SCDOCMODE_CLIP ));
922 0 : pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink );
923 0 : pClipDoc = xTransClip.get();
924 :
925 0 : ScDrawLayer::SetGlobalDrawPersist(NULL);
926 : }
927 :
928 : SCCOL nStartCol;
929 : SCROW nStartRow;
930 : SCTAB nStartTab;
931 : SCCOL nEndCol;
932 : SCROW nEndRow;
933 : SCTAB nEndTab;
934 : SCCOL nClipSizeX;
935 : SCROW nClipSizeY;
936 17 : pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, true ); // size in clipboard doc
937 :
938 : // size in target doc: include filtered rows only if CutMode is set
939 : SCCOL nDestSizeX;
940 : SCROW nDestSizeY;
941 17 : pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered );
942 :
943 17 : ScDocument* pDoc = GetViewData().GetDocument();
944 17 : ScDocShell* pDocSh = GetViewData().GetDocShell();
945 17 : ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
946 17 : const bool bRecord(pDoc->IsUndoEnabled());
947 :
948 34 : ScDocShellModificator aModificator( *pDocSh );
949 :
950 17 : ScRange aMarkRange;
951 34 : ScMarkData aFilteredMark( rMark); // local copy for all modifications
952 17 : ScMarkType eMarkType = GetViewData().GetSimpleArea( aMarkRange, aFilteredMark);
953 17 : bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED);
954 17 : bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) ||
955 17 : (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink)));
956 :
957 17 : if (!bNoPaste)
958 : {
959 17 : if (!rMark.IsMarked())
960 : {
961 : // Create a selection with clipboard row count and check that for
962 : // filtered.
963 17 : nStartCol = GetViewData().GetCurX();
964 17 : nStartRow = GetViewData().GetCurY();
965 17 : nStartTab = GetViewData().GetTabNo();
966 17 : nEndCol = nStartCol + nDestSizeX;
967 17 : nEndRow = nStartRow + nDestSizeY;
968 17 : nEndTab = nStartTab;
969 17 : aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
970 17 : if (ScViewUtil::HasFiltered( aMarkRange, pDoc))
971 : {
972 0 : bMarkIsFiltered = true;
973 : // Fit to clipboard's row count unfiltered rows. If there is no
974 : // fit assume that pasting is not possible. Note that nDestSizeY is
975 : // size-1 (difference).
976 0 : if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
977 0 : bNoPaste = true;
978 : }
979 17 : aFilteredMark.SetMarkArea( aMarkRange);
980 : }
981 : else
982 : {
983 : // Expand the marked area when the destination area is larger than the
984 : // current selection, to get the undo do the right thing. (i#106711)
985 0 : ScRange aRange;
986 0 : aFilteredMark.GetMarkArea( aRange );
987 0 : if( (aRange.aEnd.Col() - aRange.aStart.Col()) < nDestSizeX )
988 : {
989 0 : aRange.aEnd.SetCol(aRange.aStart.Col() + nDestSizeX);
990 0 : aFilteredMark.SetMarkArea(aRange);
991 : }
992 : }
993 : }
994 :
995 17 : if (bNoPaste)
996 : {
997 0 : ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
998 0 : return false;
999 : }
1000 :
1001 17 : SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1;
1002 34 : ScRangeList aRangeList;
1003 17 : if (bMarkIsFiltered)
1004 : {
1005 0 : ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1006 0 : aFilteredMark.FillRangeListWithMarks( &aRangeList, false);
1007 0 : nUnfilteredRows = 0;
1008 0 : size_t ListSize = aRangeList.size();
1009 0 : for ( size_t i = 0; i < ListSize; ++i )
1010 : {
1011 0 : ScRange* p = aRangeList[i];
1012 0 : nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1;
1013 : }
1014 : #if 0
1015 : /* This isn't needed but could be a desired restriction. */
1016 : // For filtered, destination rows have to be an exact multiple of
1017 : // source rows. Note that nDestSizeY is size-1 (difference), so
1018 : // nDestSizeY==0 fits always.
1019 : if ((nUnfilteredRows % (nDestSizeY+1)) != 0)
1020 : {
1021 : /* FIXME: this should be a more descriptive error message then. */
1022 : ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1023 : return false;
1024 : }
1025 : #endif
1026 : }
1027 :
1028 : // Also for a filtered selection the area is used, for undo et al.
1029 17 : if ( aFilteredMark.IsMarked() || bMarkIsFiltered )
1030 : {
1031 17 : aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1032 17 : SCCOL nBlockAddX = nEndCol-nStartCol;
1033 17 : SCROW nBlockAddY = nEndRow-nStartRow;
1034 :
1035 : // Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner
1036 : // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt)
1037 :
1038 : // ClipSize is not size, but difference
1039 17 : if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) ||
1040 17 : ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) ||
1041 0 : ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) )
1042 : {
1043 0 : ScWaitCursorOff aWaitOff( GetFrameWin() );
1044 0 : OUString aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER );
1045 0 : ScopedVclPtrInstance<QueryBox> aBox( GetViewData().GetDialogParent(),
1046 0 : WinBits(WB_YES_NO | WB_DEF_NO), aMessage );
1047 0 : if ( aBox->Execute() != RET_YES )
1048 : {
1049 0 : return false;
1050 0 : }
1051 : }
1052 :
1053 17 : if (nBlockAddX <= nDestSizeX)
1054 17 : nEndCol = nStartCol + nDestSizeX;
1055 :
1056 17 : if (nBlockAddY <= nDestSizeY)
1057 : {
1058 17 : nEndRow = nStartRow + nDestSizeY;
1059 17 : if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row())
1060 : {
1061 : // Same as above if nothing was marked: re-fit selection to
1062 : // unfiltered rows. Extending the selection actually may
1063 : // introduce filtered rows where there weren't any before, so
1064 : // we also need to test for that.
1065 0 : aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1066 0 : if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc))
1067 : {
1068 0 : bMarkIsFiltered = true;
1069 : // Worst case: all rows up to the end of the sheet are filtered.
1070 0 : if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
1071 : {
1072 0 : ErrorMessage(STR_PASTE_FULL);
1073 0 : return false;
1074 : }
1075 : }
1076 0 : aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1077 0 : aFilteredMark.SetMarkArea( aMarkRange);
1078 0 : if (bMarkIsFiltered)
1079 : {
1080 0 : ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1081 0 : aFilteredMark.FillRangeListWithMarks( &aRangeList, true);
1082 : }
1083 : }
1084 : }
1085 : }
1086 : else
1087 : {
1088 0 : nStartCol = GetViewData().GetCurX();
1089 0 : nStartRow = GetViewData().GetCurY();
1090 0 : nStartTab = GetViewData().GetTabNo();
1091 0 : nEndCol = nStartCol + nDestSizeX;
1092 0 : nEndRow = nStartRow + nDestSizeY;
1093 0 : nEndTab = nStartTab;
1094 : }
1095 :
1096 17 : bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow);
1097 :
1098 : // target-range, as displayed:
1099 17 : ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1100 :
1101 : // should lines be inserted?
1102 : // ( too large nEndCol/nEndRow are detected below)
1103 17 : bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits );
1104 17 : if ( bInsertCells )
1105 : {
1106 : // Instead of EnterListAction, the paste undo action is merged into the
1107 : // insert action, so Repeat can insert the right cells
1108 :
1109 0 : MarkRange( aUserRange ); // set through CopyFromClip
1110 :
1111 : // CutMode is reset on insertion of cols/rows but needed again on cell move
1112 0 : bool bCut = pClipDoc->IsCutMode();
1113 0 : if (!InsertCells( eMoveMode, bRecord, true )) // is inserting possible?
1114 : {
1115 0 : return false;
1116 : // #i21036# EnterListAction isn't used, and InsertCells doesn't insert
1117 : // its undo action on failure, so no undo handling is needed here
1118 : }
1119 0 : if ( bCut )
1120 0 : pClipDoc->SetCutMode( bCut );
1121 : }
1122 17 : else if (!bOffLimits)
1123 : {
1124 0 : bool bAskIfNotEmpty = bAllowDialogs &&
1125 17 : ( nFlags & IDF_CONTENTS ) &&
1126 17 : nFunction == PASTE_NOFUNC &&
1127 34 : SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1128 17 : if ( bAskIfNotEmpty )
1129 : {
1130 0 : ScRangeList aTestRanges;
1131 0 : aTestRanges.Append(aUserRange);
1132 0 : if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aFilteredMark, GetViewData().GetDialogParent()))
1133 0 : return false;
1134 : }
1135 : }
1136 :
1137 : SCCOL nClipStartX; // enlarge clipboard-range
1138 : SCROW nClipStartY;
1139 17 : pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1140 17 : SCCOL nUndoEndCol = nClipStartX + nClipSizeX;
1141 17 : SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document
1142 17 : bool bClipOver = false;
1143 : // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers.
1144 : // The same end column/row can be used for all calls because the clip doc doesn't contain
1145 : // content outside the clip area.
1146 34 : for (SCTAB nClipTab=0; nClipTab < pClipDoc->GetTableCount(); nClipTab++)
1147 17 : if ( pClipDoc->HasTable(nClipTab) )
1148 17 : if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, false ) )
1149 0 : bClipOver = true;
1150 17 : nUndoEndCol -= nClipStartX + nClipSizeX;
1151 17 : nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge
1152 17 : nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol );
1153 17 : nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells
1154 :
1155 17 : if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW)
1156 : {
1157 0 : ErrorMessage(STR_PASTE_FULL);
1158 0 : return false;
1159 : }
1160 :
1161 17 : pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, false );
1162 :
1163 : // check cell-protection
1164 :
1165 17 : ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow );
1166 17 : if (!aTester.IsEditable())
1167 : {
1168 0 : ErrorMessage(aTester.GetMessageId());
1169 0 : return false;
1170 : }
1171 :
1172 : //! check overlapping
1173 : //! just check truly intersection !!!!!!!
1174 :
1175 17 : ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
1176 17 : if ( bRecord )
1177 : {
1178 17 : OUString aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY );
1179 17 : pUndoMgr->EnterListAction( aUndo, aUndo );
1180 : }
1181 :
1182 17 : if (bClipOver)
1183 0 : if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED ))
1184 : { // "Cell merge not possible if cells already merged"
1185 0 : ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow );
1186 0 : const ScPatternAttr* pPattern = NULL;
1187 0 : SCCOL nCol = -1;
1188 0 : SCROW nRow1 = -1;
1189 0 : SCROW nRow2 = -1;
1190 0 : while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL )
1191 : {
1192 0 : const ScMergeAttr* pMergeFlag = static_cast<const ScMergeAttr*>( &pPattern->GetItem(ATTR_MERGE) );
1193 0 : const ScMergeFlagAttr* pMergeFlagAttr = static_cast<const ScMergeFlagAttr*>( &pPattern->GetItem(ATTR_MERGE_FLAG) );
1194 0 : if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) )
1195 : {
1196 0 : ScRange aRange(nCol, nRow1, nStartTab);
1197 0 : pDoc->ExtendOverlapped(aRange);
1198 0 : pDoc->ExtendMerge(aRange, true);
1199 0 : rDocFunc.UnmergeCells(aRange, bRecord);
1200 : }
1201 0 : }
1202 : }
1203 :
1204 17 : if ( !bCutMode )
1205 : {
1206 17 : ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1207 17 : if ( pChangeTrack )
1208 0 : pChangeTrack->ResetLastCut(); // no more cut-mode
1209 : }
1210 :
1211 17 : bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1212 17 : bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1213 :
1214 17 : ScDocument* pUndoDoc = NULL;
1215 17 : ScDocument* pRefUndoDoc = NULL;
1216 17 : ScRefUndoData* pUndoData = NULL;
1217 :
1218 17 : if ( bRecord )
1219 : {
1220 17 : pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1221 17 : pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo );
1222 :
1223 : // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
1224 17 : SCTAB nTabCount = pDoc->GetTableCount();
1225 : pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1,
1226 17 : nUndoFlags, false, pUndoDoc );
1227 :
1228 17 : if ( bCutMode )
1229 : {
1230 0 : pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1231 0 : pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
1232 :
1233 0 : pUndoData = new ScRefUndoData( pDoc );
1234 : }
1235 : }
1236 :
1237 17 : sal_uInt16 nExtFlags = 0;
1238 : pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1239 17 : nEndCol, nEndRow, nEndTab ); // content before the change
1240 :
1241 17 : if (GetViewData().IsActive())
1242 : {
1243 17 : DoneBlockMode();
1244 17 : InitOwnBlockMode();
1245 : }
1246 17 : rMark.SetMarkArea( aUserRange );
1247 17 : MarkDataChanged();
1248 :
1249 : // copy from clipboard
1250 : // save original data in case of calculation
1251 :
1252 34 : boost::scoped_ptr<ScDocument> pMixDoc;
1253 17 : if (nFunction)
1254 : {
1255 0 : bSkipEmpty = false;
1256 0 : if ( nFlags & IDF_CONTENTS )
1257 : {
1258 0 : pMixDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1259 0 : pMixDoc->InitUndo( pDoc, nStartTab, nEndTab );
1260 : pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1261 0 : IDF_CONTENTS, false, pMixDoc.get() );
1262 : }
1263 : }
1264 :
1265 : /* Make draw layer and start drawing undo.
1266 : - Needed before AdjustBlockHeight to track moved drawing objects.
1267 : - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1268 : */
1269 17 : if ( bPasteDraw )
1270 0 : pDocSh->MakeDrawLayer();
1271 17 : if ( bRecord )
1272 17 : pDoc->BeginDrawUndo();
1273 :
1274 17 : InsertDeleteFlags nNoObjFlags = nFlags & ~IDF_OBJECTS;
1275 17 : if (!bAsLink)
1276 : {
1277 : // copy normally (original range)
1278 : pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags,
1279 : pRefUndoDoc, pClipDoc, true, false, bIncludeFiltered,
1280 17 : bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) );
1281 :
1282 : // adapt refs manually in case of transpose
1283 17 : if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) )
1284 0 : pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc );
1285 : }
1286 0 : else if (!bTranspose)
1287 : {
1288 : // copy with bAsLink=TRUE
1289 : pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc,
1290 0 : true, true, bIncludeFiltered, bSkipEmpty );
1291 : }
1292 : else
1293 : {
1294 : // copy all content (TransClipDoc contains only formula)
1295 0 : pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc );
1296 : }
1297 :
1298 : // skipped rows and merged cells don't mix
1299 17 : if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
1300 0 : rDocFunc.UnmergeCells( aUserRange, false );
1301 :
1302 17 : pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, true ); // refresh
1303 : // new range
1304 :
1305 17 : if ( pMixDoc ) // calculate with originial data ?
1306 : {
1307 0 : pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc.get() );
1308 : }
1309 17 : pMixDoc.reset();
1310 :
1311 17 : AdjustBlockHeight(); // update row heights before pasting objects
1312 :
1313 34 : ::std::vector< OUString > aExcludedChartNames;
1314 17 : SdrPage* pPage = NULL;
1315 :
1316 17 : if ( nFlags & IDF_OBJECTS )
1317 : {
1318 17 : ScDrawView* pScDrawView = GetScDrawView();
1319 17 : SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL );
1320 17 : pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL );
1321 17 : if ( pPage )
1322 : {
1323 17 : ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
1324 : }
1325 :
1326 : // Paste the drawing objects after the row heights have been updated.
1327 :
1328 : pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc,
1329 17 : true, false, bIncludeFiltered );
1330 : }
1331 :
1332 : pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1333 17 : nEndCol, nEndRow, nEndTab ); // content after the change
1334 :
1335 : // if necessary, delete autofilter-heads
1336 17 : if (bCutMode)
1337 0 : if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX,
1338 0 : nClipStartY+nClipSizeY, nStartTab ))
1339 : {
1340 : pDocSh->PostPaint(
1341 : ScRange(nClipStartX, nClipStartY, nStartTab, nClipStartX+nClipSizeX, nClipStartY, nStartTab),
1342 0 : PAINT_GRID );
1343 : }
1344 :
1345 : //! remove block-range on RefUndoDoc !!!
1346 :
1347 17 : if ( bRecord )
1348 : {
1349 17 : ScDocument* pRedoDoc = NULL;
1350 : // copy redo data after appearance of the first undo
1351 : // don't create Redo-Doc without RefUndoDoc
1352 :
1353 17 : if (pRefUndoDoc)
1354 : {
1355 0 : pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
1356 0 : pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo );
1357 :
1358 : // move adapted refs to Redo-Doc
1359 :
1360 0 : SCTAB nTabCount = pDoc->GetTableCount();
1361 0 : pRedoDoc->AddUndoTab( 0, nTabCount-1 );
1362 0 : pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc );
1363 :
1364 : // move old refs to Undo-Doc
1365 :
1366 : // not charts?
1367 0 : pUndoDoc->AddUndoTab( 0, nTabCount-1 );
1368 0 : pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL );
1369 : pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
1370 0 : IDF_FORMULA, false, pUndoDoc );
1371 0 : delete pRefUndoDoc;
1372 : }
1373 :
1374 : // DeleteUnchanged for pUndoData is in ScUndoPaste ctor,
1375 : // UndoData for redo is made during first undo
1376 :
1377 17 : ScUndoPasteOptions aOptions; // store options for repeat
1378 17 : aOptions.nFunction = nFunction;
1379 17 : aOptions.bSkipEmpty = bSkipEmpty;
1380 17 : aOptions.bTranspose = bTranspose;
1381 17 : aOptions.bAsLink = bAsLink;
1382 17 : aOptions.eMoveMode = eMoveMode;
1383 :
1384 : SfxUndoAction* pUndo = new ScUndoPaste(
1385 : pDocSh, ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1386 34 : aFilteredMark, pUndoDoc, pRedoDoc, nFlags | nUndoFlags, pUndoData,
1387 51 : false, &aOptions ); // false = Redo data not yet copied
1388 :
1389 17 : if ( bInsertCells )
1390 : {
1391 : // Merge the paste undo action into the insert action.
1392 : // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action.
1393 :
1394 0 : pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1395 : }
1396 : else
1397 17 : pUndoMgr->AddUndoAction( pUndo );
1398 17 : pUndoMgr->LeaveListAction();
1399 : }
1400 :
1401 17 : sal_uInt16 nPaint = PAINT_GRID;
1402 17 : if (bColInfo)
1403 : {
1404 0 : nPaint |= PAINT_TOP;
1405 0 : nUndoEndCol = MAXCOL; // just for drawing !
1406 : }
1407 17 : if (bRowInfo)
1408 : {
1409 0 : nPaint |= PAINT_LEFT;
1410 0 : nUndoEndRow = MAXROW; // just for drawing !
1411 : }
1412 : pDocSh->PostPaint(
1413 : ScRange(nStartCol, nStartRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1414 17 : nPaint, nExtFlags);
1415 : // AdjustBlockHeight has already been called above
1416 :
1417 17 : ResetAutoSpell();
1418 17 : aModificator.SetDocumentModified();
1419 17 : PostPasteFromClip(aUserRange, rMark);
1420 :
1421 17 : if ( nFlags & IDF_OBJECTS )
1422 : {
1423 17 : ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1424 17 : if ( pPage && pModelObj )
1425 : {
1426 17 : bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() );
1427 17 : const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector );
1428 : ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab,
1429 17 : rProtectedChartRangesVector, aExcludedChartNames, bSameDoc );
1430 : }
1431 : }
1432 :
1433 34 : return true;
1434 : }
1435 :
1436 0 : bool ScViewFunc::PasteMultiRangesFromClip(
1437 : InsertDeleteFlags nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1438 : bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1439 : InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags)
1440 : {
1441 0 : ScViewData& rViewData = GetViewData();
1442 0 : ScDocument* pDoc = rViewData.GetDocument();
1443 0 : ScDocShell* pDocSh = rViewData.GetDocShell();
1444 0 : ScMarkData aMark(rViewData.GetMarkData());
1445 0 : const ScAddress& rCurPos = rViewData.GetCurPos();
1446 0 : ScClipParam& rClipParam = pClipDoc->GetClipParam();
1447 0 : SCCOL nColSize = rClipParam.getPasteColSize();
1448 0 : SCROW nRowSize = rClipParam.getPasteRowSize();
1449 :
1450 0 : if (bTranspose)
1451 : {
1452 0 : if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
1453 : {
1454 0 : ErrorMessage(STR_PASTE_FULL);
1455 0 : return false;
1456 : }
1457 :
1458 0 : ::std::unique_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
1459 0 : pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
1460 0 : pClipDoc = pTransClip.release();
1461 0 : SCCOL nTempColSize = nColSize;
1462 0 : nColSize = static_cast<SCCOL>(nRowSize);
1463 0 : nRowSize = static_cast<SCROW>(nTempColSize);
1464 : }
1465 :
1466 0 : if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1467 : {
1468 0 : ErrorMessage(STR_PASTE_FULL);
1469 0 : return false;
1470 : }
1471 :
1472 : // Determine the first and last selected sheet numbers.
1473 0 : SCTAB nTab1 = aMark.GetFirstSelected();
1474 0 : SCTAB nTab2 = aMark.GetLastSelected();
1475 :
1476 0 : ScDocShellModificator aModificator(*pDocSh);
1477 :
1478 : // For multi-selection paste, we don't support cell duplication for larger
1479 : // destination range. In case the destination is marked, we reset it to
1480 : // the clip size.
1481 0 : ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
1482 0 : rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
1483 :
1484 : // Extend the marked range to account for filtered rows in the destination
1485 : // area.
1486 0 : if (ScViewUtil::HasFiltered(aMarkedRange, pDoc))
1487 : {
1488 0 : if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize))
1489 0 : return false;
1490 : }
1491 :
1492 : bool bAskIfNotEmpty =
1493 0 : bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1494 0 : nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1495 :
1496 0 : if (bAskIfNotEmpty)
1497 : {
1498 0 : ScRangeList aTestRanges;
1499 0 : aTestRanges.Append(aMarkedRange);
1500 0 : if (!checkDestRangeForOverwrite(aTestRanges, pDoc, aMark, rViewData.GetDialogParent()))
1501 0 : return false;
1502 : }
1503 :
1504 0 : aMark.SetMarkArea(aMarkedRange);
1505 0 : MarkRange(aMarkedRange);
1506 :
1507 0 : bool bInsertCells = (eMoveMode != INS_NONE);
1508 0 : if (bInsertCells)
1509 : {
1510 0 : if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
1511 0 : return false;
1512 : }
1513 :
1514 0 : ::std::unique_ptr<ScDocument> pUndoDoc;
1515 0 : if (pDoc->IsUndoEnabled())
1516 : {
1517 0 : pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1518 0 : pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1519 0 : pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1520 : }
1521 :
1522 0 : ::std::unique_ptr<ScDocument> pMixDoc;
1523 0 : if ( bSkipEmpty || nFunction )
1524 : {
1525 0 : if ( nFlags & IDF_CONTENTS )
1526 : {
1527 0 : pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1528 0 : pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1529 0 : pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1530 : }
1531 : }
1532 :
1533 : /* Make draw layer and start drawing undo.
1534 : - Needed before AdjustBlockHeight to track moved drawing objects.
1535 : - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1536 : */
1537 0 : if (nFlags & IDF_OBJECTS)
1538 0 : pDocSh->MakeDrawLayer();
1539 0 : if (pDoc->IsUndoEnabled())
1540 0 : pDoc->BeginDrawUndo();
1541 :
1542 0 : InsertDeleteFlags nNoObjFlags = nFlags & ~IDF_OBJECTS;
1543 : pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
1544 0 : true, bAsLink, false, bSkipEmpty);
1545 :
1546 0 : if (pMixDoc.get())
1547 0 : pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
1548 :
1549 0 : AdjustBlockHeight(); // update row heights before pasting objects
1550 :
1551 0 : if (nFlags & IDF_OBJECTS)
1552 : {
1553 : // Paste the drawing objects after the row heights have been updated.
1554 : pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
1555 0 : true, false, false, true);
1556 : }
1557 :
1558 0 : ScRange aTmp = aMarkedRange;
1559 0 : aTmp.aStart.SetTab(nTab1);
1560 0 : aTmp.aEnd.SetTab(nTab1);
1561 0 : pDocSh->PostPaint(aTmp, PAINT_GRID);
1562 :
1563 0 : if (pDoc->IsUndoEnabled())
1564 : {
1565 0 : ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1566 : OUString aUndo = ScGlobal::GetRscString(
1567 0 : pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1568 0 : pUndoMgr->EnterListAction(aUndo, aUndo);
1569 :
1570 0 : ScUndoPasteOptions aOptions; // store options for repeat
1571 0 : aOptions.nFunction = nFunction;
1572 0 : aOptions.bSkipEmpty = bSkipEmpty;
1573 0 : aOptions.bTranspose = bTranspose;
1574 0 : aOptions.bAsLink = bAsLink;
1575 0 : aOptions.eMoveMode = eMoveMode;
1576 :
1577 : ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
1578 0 : aMarkedRange, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1579 :
1580 0 : if (bInsertCells)
1581 0 : pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
1582 : else
1583 0 : pUndoMgr->AddUndoAction(pUndo, false);
1584 :
1585 0 : pUndoMgr->LeaveListAction();
1586 : }
1587 :
1588 0 : ResetAutoSpell();
1589 0 : aModificator.SetDocumentModified();
1590 0 : PostPasteFromClip(aMarkedRange, aMark);
1591 0 : return true;
1592 : }
1593 :
1594 0 : bool ScViewFunc::PasteFromClipToMultiRanges(
1595 : InsertDeleteFlags nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1596 : bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1597 : InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags )
1598 : {
1599 0 : if (bTranspose)
1600 : {
1601 : // We don't allow transpose for this yet.
1602 0 : ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1603 0 : return false;
1604 : }
1605 :
1606 0 : if (eMoveMode != INS_NONE)
1607 : {
1608 : // We don't allow insertion mode either. Too complicated.
1609 0 : ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1610 0 : return false;
1611 : }
1612 :
1613 0 : ScViewData& rViewData = GetViewData();
1614 0 : ScClipParam& rClipParam = pClipDoc->GetClipParam();
1615 0 : if (rClipParam.mbCutMode)
1616 : {
1617 : // No cut and paste with this, please.
1618 0 : ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1619 0 : return false;
1620 : }
1621 :
1622 0 : const ScAddress& rCurPos = rViewData.GetCurPos();
1623 0 : ScDocument* pDoc = rViewData.GetDocument();
1624 :
1625 0 : ScRange aSrcRange = rClipParam.getWholeRange();
1626 0 : SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
1627 0 : SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
1628 :
1629 0 : if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1630 : {
1631 0 : ErrorMessage(STR_PASTE_FULL);
1632 0 : return false;
1633 : }
1634 :
1635 0 : ScMarkData aMark(rViewData.GetMarkData());
1636 :
1637 0 : ScRangeList aRanges;
1638 0 : aMark.MarkToSimple();
1639 0 : aMark.FillRangeListWithMarks(&aRanges, false);
1640 0 : if (!ScClipUtil::CheckDestRanges(pDoc, nColSize, nRowSize, aMark, aRanges))
1641 : {
1642 0 : ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1643 0 : return false;
1644 : }
1645 :
1646 0 : ScDocShell* pDocSh = rViewData.GetDocShell();
1647 :
1648 0 : ScDocShellModificator aModificator(*pDocSh);
1649 :
1650 : bool bAskIfNotEmpty =
1651 0 : bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1652 0 : nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1653 :
1654 0 : if (bAskIfNotEmpty)
1655 : {
1656 0 : if (!checkDestRangeForOverwrite(aRanges, pDoc, aMark, rViewData.GetDialogParent()))
1657 0 : return false;
1658 : }
1659 :
1660 0 : std::unique_ptr<ScDocument> pUndoDoc;
1661 0 : if (pDoc->IsUndoEnabled())
1662 : {
1663 0 : pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1664 0 : pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1665 0 : for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1666 : {
1667 : pDoc->CopyToDocument(
1668 0 : *aRanges[i], nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1669 : }
1670 : }
1671 :
1672 0 : boost::scoped_ptr<ScDocument> pMixDoc;
1673 0 : if (bSkipEmpty || nFunction)
1674 : {
1675 0 : if (nFlags & IDF_CONTENTS)
1676 : {
1677 0 : pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1678 0 : pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1679 0 : for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1680 : {
1681 : pDoc->CopyToDocument(
1682 0 : *aRanges[i], IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1683 : }
1684 : }
1685 : }
1686 :
1687 0 : if (nFlags & IDF_OBJECTS)
1688 0 : pDocSh->MakeDrawLayer();
1689 0 : if (pDoc->IsUndoEnabled())
1690 0 : pDoc->BeginDrawUndo();
1691 :
1692 : // First, paste everything but the drawing objects.
1693 0 : for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1694 : {
1695 : pDoc->CopyFromClip(
1696 0 : *aRanges[i], aMark, (nFlags & ~IDF_OBJECTS), NULL, pClipDoc,
1697 0 : false, false, true, bSkipEmpty, NULL);
1698 : }
1699 :
1700 0 : if (pMixDoc.get())
1701 : {
1702 0 : for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1703 0 : pDoc->MixDocument(*aRanges[i], nFunction, bSkipEmpty, pMixDoc.get());
1704 : }
1705 :
1706 0 : AdjustBlockHeight(); // update row heights before pasting objects
1707 :
1708 : // Then paste the objects.
1709 0 : if (nFlags & IDF_OBJECTS)
1710 : {
1711 0 : for (size_t i = 0, n = aRanges.size(); i < n; ++i)
1712 : {
1713 : pDoc->CopyFromClip(
1714 0 : *aRanges[i], aMark, IDF_OBJECTS, NULL, pClipDoc,
1715 0 : false, false, true, bSkipEmpty, NULL);
1716 : }
1717 : }
1718 :
1719 : // Refresh the range that includes all pasted ranges. We only need to
1720 : // refresh the current sheet.
1721 0 : pDocSh->PostPaint(aRanges, PAINT_GRID);
1722 :
1723 0 : if (pDoc->IsUndoEnabled())
1724 : {
1725 0 : svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1726 : OUString aUndo = ScGlobal::GetRscString(
1727 0 : pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1728 0 : pUndoMgr->EnterListAction(aUndo, aUndo);
1729 :
1730 0 : ScUndoPasteOptions aOptions; // store options for repeat
1731 0 : aOptions.nFunction = nFunction;
1732 0 : aOptions.bSkipEmpty = bSkipEmpty;
1733 0 : aOptions.bTranspose = bTranspose;
1734 0 : aOptions.bAsLink = bAsLink;
1735 0 : aOptions.eMoveMode = eMoveMode;
1736 :
1737 : ScUndoPaste* pUndo = new ScUndoPaste(
1738 0 : pDocSh, aRanges, aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, false, &aOptions);
1739 :
1740 0 : pUndoMgr->AddUndoAction(pUndo, false);
1741 0 : pUndoMgr->LeaveListAction();
1742 : }
1743 :
1744 0 : ResetAutoSpell();
1745 0 : aModificator.SetDocumentModified();
1746 0 : PostPasteFromClip(aRanges, aMark);
1747 :
1748 0 : return false;
1749 : }
1750 :
1751 17 : void ScViewFunc::PostPasteFromClip(const ScRangeList& rPasteRanges, const ScMarkData& rMark)
1752 : {
1753 17 : ScViewData& rViewData = GetViewData();
1754 17 : ScDocShell* pDocSh = rViewData.GetDocShell();
1755 17 : pDocSh->UpdateOle(&rViewData);
1756 :
1757 17 : SelectionChanged();
1758 :
1759 17 : ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
1760 17 : if (!pModelObj)
1761 34 : return;
1762 :
1763 0 : ScRangeList aChangeRanges;
1764 0 : for (size_t i = 0, n = rPasteRanges.size(); i < n; ++i)
1765 : {
1766 0 : const ScRange& r = *rPasteRanges[i];
1767 0 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1768 0 : for (; itr != itrEnd; ++itr)
1769 : {
1770 0 : ScRange aChangeRange(r);
1771 0 : aChangeRange.aStart.SetTab(*itr);
1772 0 : aChangeRange.aEnd.SetTab(*itr);
1773 0 : aChangeRanges.Append(aChangeRange);
1774 : }
1775 : }
1776 0 : HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
1777 : }
1778 :
1779 : // D R A G A N D D R O P
1780 :
1781 : // inside the doc
1782 :
1783 0 : bool ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos,
1784 : bool bCut, bool bRecord, bool bPaint, bool bApi )
1785 : {
1786 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
1787 0 : HideAllCursors();
1788 :
1789 0 : bool bSuccess = true;
1790 0 : SCTAB nDestTab = rDestPos.Tab();
1791 0 : const ScMarkData& rMark = GetViewData().GetMarkData();
1792 0 : if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 )
1793 : {
1794 : // moving within one table and several tables selected -> apply to all selected tables
1795 :
1796 0 : if ( bRecord )
1797 : {
1798 0 : OUString aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY );
1799 0 : pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
1800 : }
1801 :
1802 : // collect ranges of consecutive selected tables
1803 :
1804 0 : ScRange aLocalSource = rSource;
1805 0 : ScAddress aLocalDest = rDestPos;
1806 0 : SCTAB nTabCount = pDocSh->GetDocument().GetTableCount();
1807 0 : SCTAB nStartTab = 0;
1808 0 : while ( nStartTab < nTabCount && bSuccess )
1809 : {
1810 0 : while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) )
1811 0 : ++nStartTab;
1812 0 : if ( nStartTab < nTabCount )
1813 : {
1814 0 : SCTAB nEndTab = nStartTab;
1815 0 : while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) )
1816 0 : ++nEndTab;
1817 :
1818 0 : aLocalSource.aStart.SetTab( nStartTab );
1819 0 : aLocalSource.aEnd.SetTab( nEndTab );
1820 0 : aLocalDest.SetTab( nStartTab );
1821 :
1822 0 : bSuccess = pDocSh->GetDocFunc().MoveBlock(
1823 0 : aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi );
1824 :
1825 0 : nStartTab = nEndTab + 1;
1826 : }
1827 : }
1828 :
1829 0 : if ( bRecord )
1830 0 : pDocSh->GetUndoManager()->LeaveListAction();
1831 : }
1832 : else
1833 : {
1834 : // move the block as specified
1835 0 : bSuccess = pDocSh->GetDocFunc().MoveBlock(
1836 0 : rSource, rDestPos, bCut, bRecord, bPaint, bApi );
1837 : }
1838 :
1839 0 : ShowAllCursors();
1840 0 : if (bSuccess)
1841 : {
1842 : // mark destination range
1843 : ScAddress aDestEnd(
1844 0 : rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(),
1845 0 : rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(),
1846 0 : nDestTab );
1847 :
1848 0 : bool bIncludeFiltered = bCut;
1849 0 : if ( !bIncludeFiltered )
1850 : {
1851 : // find number of non-filtered rows
1852 0 : SCROW nPastedCount = pDocSh->GetDocument().CountNonFilteredRows(
1853 0 : rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab());
1854 :
1855 0 : if ( nPastedCount == 0 )
1856 0 : nPastedCount = 1;
1857 0 : aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 );
1858 : }
1859 :
1860 0 : MarkRange( ScRange( rDestPos, aDestEnd ), false ); //! sal_False ???
1861 :
1862 0 : pDocSh->UpdateOle(&GetViewData());
1863 0 : SelectionChanged();
1864 0 : ResetAutoSpell();
1865 : }
1866 0 : return bSuccess;
1867 : }
1868 :
1869 : // link inside the doc
1870 :
1871 0 : bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, bool bApi )
1872 : {
1873 : // check overlapping
1874 :
1875 0 : if ( rSource.aStart.Tab() == rDestPos.Tab() )
1876 : {
1877 0 : SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() );
1878 0 : SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() );
1879 :
1880 0 : if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() &&
1881 0 : rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() )
1882 : {
1883 0 : if (!bApi)
1884 0 : ErrorMessage( STR_ERR_LINKOVERLAP );
1885 0 : return false;
1886 : }
1887 : }
1888 :
1889 : // run with paste
1890 :
1891 0 : ScDocument* pDoc = GetViewData().GetDocument();
1892 0 : boost::scoped_ptr<ScDocument> pClipDoc(new ScDocument( SCDOCMODE_CLIP ));
1893 0 : pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(),
1894 0 : rSource.aEnd.Col(), rSource.aEnd.Row(),
1895 0 : rSource.aStart.Tab(), pClipDoc.get() );
1896 :
1897 : // mark destination area (set cursor, no marks)
1898 :
1899 0 : if ( GetViewData().GetTabNo() != rDestPos.Tab() )
1900 0 : SetTabNo( rDestPos.Tab() );
1901 :
1902 0 : MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, false, false );
1903 :
1904 : // Paste
1905 :
1906 0 : PasteFromClip( IDF_ALL, pClipDoc.get(), PASTE_NOFUNC, false, false, true ); // as a link
1907 :
1908 0 : return true;
1909 : }
1910 :
1911 0 : void ScViewFunc::DataFormPutData( SCROW nCurrentRow ,
1912 : SCROW nStartRow , SCCOL nStartCol ,
1913 : SCROW nEndRow , SCCOL nEndCol ,
1914 : std::vector<VclPtr<Edit> >& aEdits,
1915 : sal_uInt16 aColLength )
1916 : {
1917 0 : ScDocument* pDoc = GetViewData().GetDocument();
1918 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
1919 0 : ScMarkData& rMark = GetViewData().GetMarkData();
1920 0 : ScDocShellModificator aModificator( *pDocSh );
1921 0 : ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1922 0 : if ( pDoc )
1923 : {
1924 0 : const bool bRecord( pDoc->IsUndoEnabled());
1925 0 : ScDocument* pUndoDoc = NULL;
1926 0 : ScDocument* pRedoDoc = NULL;
1927 0 : ScRefUndoData* pUndoData = NULL;
1928 0 : SCTAB nTab = GetViewData().GetTabNo();
1929 0 : SCTAB nStartTab = nTab;
1930 0 : SCTAB nEndTab = nTab;
1931 :
1932 : {
1933 0 : ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1934 0 : if ( pChangeTrack )
1935 0 : pChangeTrack->ResetLastCut(); // no more cut-mode
1936 : }
1937 0 : ScRange aUserRange( nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab );
1938 0 : bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1939 0 : bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1940 0 : SCCOL nUndoEndCol = nStartCol+aColLength-1;
1941 0 : SCROW nUndoEndRow = nCurrentRow;
1942 0 : InsertDeleteFlags nUndoFlags = IDF_NONE;
1943 :
1944 0 : if ( bRecord )
1945 : {
1946 0 : pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1947 0 : pUndoDoc->InitUndoSelected( pDoc , rMark , bColInfo , bRowInfo );
1948 0 : pDoc->CopyToDocument( aUserRange , IDF_VALUE , false , pUndoDoc );
1949 : }
1950 0 : sal_uInt16 nExtFlags = 0;
1951 0 : pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab , nEndCol, nEndRow, nEndTab ); // content before the change
1952 0 : pDoc->BeginDrawUndo();
1953 :
1954 0 : for(sal_uInt16 i = 0; i < aColLength; i++)
1955 : {
1956 0 : if (aEdits[i] != nullptr)
1957 : {
1958 0 : OUString aFieldName=aEdits[i]->GetText();
1959 0 : pDoc->SetString( nStartCol + i, nCurrentRow, nTab, aFieldName );
1960 : }
1961 : }
1962 0 : pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab ); // content after the change
1963 : SfxUndoAction* pUndo = new ScUndoDataForm( pDocSh,
1964 : nStartCol, nCurrentRow, nStartTab,
1965 : nUndoEndCol, nUndoEndRow, nEndTab, rMark,
1966 : pUndoDoc, pRedoDoc, nUndoFlags,
1967 : pUndoData, NULL, NULL, NULL,
1968 0 : false ); // FALSE = Redo data not yet copied
1969 0 : pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), true );
1970 :
1971 0 : sal_uInt16 nPaint = PAINT_GRID;
1972 0 : if (bColInfo)
1973 : {
1974 0 : nPaint |= PAINT_TOP;
1975 0 : nUndoEndCol = MAXCOL; // just for drawing !
1976 : }
1977 0 : if (bRowInfo)
1978 : {
1979 0 : nPaint |= PAINT_LEFT;
1980 0 : nUndoEndRow = MAXROW; // just for drawing !
1981 : }
1982 :
1983 : pDocSh->PostPaint(
1984 : ScRange(nStartCol, nCurrentRow, nStartTab, nUndoEndCol, nUndoEndRow, nEndTab),
1985 0 : nPaint, nExtFlags);
1986 0 : pDocSh->UpdateOle(&GetViewData());
1987 0 : }
1988 156 : }
1989 :
1990 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|