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