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