xref: /AOO41X/main/sc/source/ui/view/viewfun3.cxx (revision 52f1c2ee1b77392125ca30aec3c767684308e131)
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