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