xref: /AOO41X/main/sc/source/ui/view/viewfun3.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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 
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 
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 
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 
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 
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 
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 
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 
823 sal_Bool ScViewFunc::PasteOnDrawObject( const uno::Reference<datatransfer::XTransferable>& rxTransferable,
824                                     SdrObject* pHitObj, sal_Bool bLink )
825 {
826     sal_Bool bRet = sal_False;
827     if ( bLink )
828     {
829         TransferableDataHelper aDataHelper( rxTransferable );
830         if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
831         {
832             SotStorageStreamRef xStm;
833             if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) )
834             {
835                 Graphic aGraphic;
836                 *xStm >> aGraphic;
837                 bRet = ApplyGraphicToObject( pHitObj, aGraphic );
838             }
839         }
840         else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
841         {
842             GDIMetaFile aMtf;
843             if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) )
844                 bRet = ApplyGraphicToObject( pHitObj, Graphic(aMtf) );
845         }
846         else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
847         {
848             Bitmap aBmp;
849             if( aDataHelper.GetBitmap( FORMAT_BITMAP, aBmp ) )
850                 bRet = ApplyGraphicToObject( pHitObj, Graphic(aBmp) );
851         }
852     }
853     else
854     {
855         //  ham' wa noch nich
856     }
857     return bRet;
858 }
859 
860 sal_Bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
861                         const ScMarkData& rTabSelection, sal_uInt16 nMask )
862 {
863     SCTAB nTabCount = pDoc->GetTableCount();
864     for (SCTAB nTab=0; nTab<nTabCount; nTab++)
865         if ( rTabSelection.GetTableSelect(nTab) && pDoc->HasAttrib( nCol1, nRow1, nTab, nCol2, nRow2, nTab, nMask ) )
866             return sal_True;
867     return sal_False;
868 }
869 
870 //
871 //      Einfuegen auf Tabelle:
872 //
873 
874 //  internes Paste
875 
876 namespace {
877 
878 class CursorSwitcher
879 {
880 public:
881     CursorSwitcher(ScViewFunc* pViewFunc) :
882         mpViewFunc(pViewFunc)
883     {
884         mpViewFunc->HideCursor();
885     }
886 
887     ~CursorSwitcher()
888     {
889         mpViewFunc->ShowCursor();
890     }
891 private:
892     ScViewFunc* mpViewFunc;
893 };
894 
895 bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
896 {
897     bool bIsEmpty = true;
898     SCTAB nTabCount = pDoc->GetTableCount();
899     for (SCTAB nTab=0; nTab < nTabCount && bIsEmpty; ++nTab)
900     {
901         if (!rMark.GetTableSelect(nTab))
902             continue;
903 
904         bIsEmpty = pDoc->IsBlockEmpty(nTab, rDestRange.aStart.Col(), rDestRange.aStart.Row(),
905                                       rDestRange.aEnd.Col(), rDestRange.aEnd.Row());
906     }
907 
908     if (!bIsEmpty)
909     {
910         ScReplaceWarnBox aBox(pParentWnd);
911         if (aBox.Execute() != RET_YES)
912         {
913             //  changing the configuration is within the ScReplaceWarnBox
914             return false;
915         }
916     }
917     return true;
918 }
919 
920 }
921 
922 sal_Bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc,
923                                     sal_uInt16 nFunction, sal_Bool bSkipEmpty,
924                                     sal_Bool bTranspose, sal_Bool bAsLink,
925                                     InsCellCmd eMoveMode, sal_uInt16 nUndoExtraFlags,
926                                     sal_Bool bAllowDialogs )
927 {
928     if (!pClipDoc)
929     {
930         DBG_ERROR("PasteFromClip: pClipDoc=0 not allowed");
931         return sal_False;
932     }
933 
934     //  fuer Undo etc. immer alle oder keine Inhalte sichern
935     sal_uInt16 nContFlags = IDF_NONE;
936     if (nFlags & IDF_CONTENTS)
937         nContFlags |= IDF_CONTENTS;
938     if (nFlags & IDF_ATTRIB)
939         nContFlags |= IDF_ATTRIB;
940     // evtl. Attribute ins Undo ohne sie vom Clip ins Doc zu kopieren
941     sal_uInt16 nUndoFlags = nContFlags;
942     if (nUndoExtraFlags & IDF_ATTRIB)
943         nUndoFlags |= IDF_ATTRIB;
944     // do not copy note captions into undo document
945     nUndoFlags |= IDF_NOCAPTIONS;
946 
947     ScClipParam& rClipParam = pClipDoc->GetClipParam();
948     if (rClipParam.isMultiRange())
949         return PasteMultiRangesFromClip(
950             nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
951             eMoveMode, nContFlags, nUndoFlags);
952 
953     sal_Bool bCutMode = pClipDoc->IsCutMode();      // if transposing, take from original clipdoc
954     sal_Bool bIncludeFiltered = bCutMode;
955 
956     // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions)
957     sal_Bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) );
958 
959     ScDocShellRef aTransShellRef;   // for objects in xTransClip - must remain valid as long as xTransClip
960     ScDocument* pOrigClipDoc = NULL;
961     ::std::auto_ptr< ScDocument > xTransClip;
962     if ( bTranspose )
963     {
964         SCCOL nX;
965         SCROW nY;
966         // include filtered rows until TransposeClip can skip them
967         bIncludeFiltered = sal_True;
968         pClipDoc->GetClipArea( nX, nY, sal_True );
969         if ( nY > static_cast<sal_Int32>(MAXCOL) )                      // zuviele Zeilen zum Transponieren
970         {
971             ErrorMessage(STR_PASTE_FULL);
972             return sal_False;
973         }
974         pOrigClipDoc = pClipDoc;        // fuer Referenzen
975 
976         if ( bPasteDraw )
977         {
978             aTransShellRef = new ScDocShell;        // DocShell needs a Ref immediately
979             aTransShellRef->DoInitNew(NULL);
980         }
981         ScDrawLayer::SetGlobalDrawPersist(aTransShellRef);
982 
983         xTransClip.reset( new ScDocument( SCDOCMODE_CLIP ));
984         pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink );
985         pClipDoc = xTransClip.get();
986 
987         ScDrawLayer::SetGlobalDrawPersist(NULL);
988     }
989 
990     SCCOL nStartCol;
991     SCROW nStartRow;
992     SCTAB nStartTab;
993     SCCOL nEndCol;
994     SCROW nEndRow;
995     SCTAB nEndTab;
996     SCCOL nClipSizeX;
997     SCROW nClipSizeY;
998     pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, sal_True );      // size in clipboard doc
999 
1000     //  size in target doc: include filtered rows only if CutMode is set
1001     SCCOL nDestSizeX;
1002     SCROW nDestSizeY;
1003     pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered );
1004 
1005     ScDocument* pDoc = GetViewData()->GetDocument();
1006     ScDocShell* pDocSh = GetViewData()->GetDocShell();
1007     ScMarkData& rMark = GetViewData()->GetMarkData();
1008     ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1009     const sal_Bool bRecord(pDoc->IsUndoEnabled());
1010 
1011     ScDocShellModificator aModificator( *pDocSh );
1012 
1013     ScRange aMarkRange;
1014     ScMarkData aFilteredMark( rMark);   // local copy for all modifications
1015     ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange, aFilteredMark);
1016     bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED);
1017     bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) ||
1018             (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink)));
1019     if (!bNoPaste && !rMark.IsMarked())
1020     {
1021         // Create a selection with clipboard row count and check that for
1022         // filtered.
1023         nStartCol = GetViewData()->GetCurX();
1024         nStartRow = GetViewData()->GetCurY();
1025         nStartTab = GetViewData()->GetTabNo();
1026         nEndCol = nStartCol + nDestSizeX;
1027         nEndRow = nStartRow + nDestSizeY;
1028         nEndTab = nStartTab;
1029         aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1030         if (ScViewUtil::HasFiltered( aMarkRange, pDoc))
1031         {
1032             bMarkIsFiltered = true;
1033             // Fit to clipboard's row count unfiltered rows. If there is no
1034             // fit assume that pasting is not possible. Note that nDestSizeY is
1035             // size-1 (difference).
1036             if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
1037                 bNoPaste = true;
1038         }
1039         aFilteredMark.SetMarkArea( aMarkRange);
1040     }
1041     if (bNoPaste)
1042     {
1043         ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1044         return sal_False;
1045     }
1046 
1047     SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1;
1048     ScRangeList aRangeList;
1049     if (bMarkIsFiltered)
1050     {
1051         ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1052         aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_False);
1053         nUnfilteredRows = 0;
1054         for (ScRange* p = aRangeList.First(); p; p = aRangeList.Next())
1055         {
1056             nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1;
1057         }
1058 #if 0
1059         /* This isn't needed but could be a desired restriction. */
1060         // For filtered, destination rows have to be an exact multiple of
1061         // source rows. Note that nDestSizeY is size-1 (difference), so
1062         // nDestSizeY==0 fits always.
1063         if ((nUnfilteredRows % (nDestSizeY+1)) != 0)
1064         {
1065             /* FIXME: this should be a more descriptive error message then. */
1066             ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1067             return sal_False;
1068         }
1069 #endif
1070     }
1071 
1072     SCCOL nMarkAddX = 0;
1073     SCROW nMarkAddY = 0;
1074 
1075     // Also for a filtered selection the area is used, for undo et al.
1076     if ( aFilteredMark.IsMarked() || bMarkIsFiltered )
1077     {
1078         aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1079         SCCOL nBlockAddX = nEndCol-nStartCol;
1080         SCROW nBlockAddY = nEndRow-nStartRow;
1081 
1082         //  #58422# Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner
1083         //  als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt)
1084 
1085         //  ClipSize is not size, but difference
1086         if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) ||
1087              ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) ||
1088              ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) )
1089         {
1090             ScWaitCursorOff aWaitOff( GetFrameWin() );
1091             String aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER );
1092             QueryBox aBox( GetViewData()->GetDialogParent(),
1093                             WinBits(WB_YES_NO | WB_DEF_NO), aMessage );
1094             if ( aBox.Execute() != RET_YES )
1095             {
1096                 return sal_False;
1097             }
1098         }
1099 
1100         if (nBlockAddX > nDestSizeX)
1101             nMarkAddX = nBlockAddX - nDestSizeX;            // fuer Merge-Test
1102         else
1103         {
1104             nEndCol = nStartCol + nDestSizeX;
1105             if (nEndCol > aMarkRange.aEnd.Col())
1106             {
1107                 // #i113553# larger range has to be included in aFilteredMark (for undo), but extending columns can't changed the filtered status
1108                 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1109                 aFilteredMark.SetMarkArea( aMarkRange );
1110                 if (bMarkIsFiltered)
1111                 {
1112                     ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc );
1113                     aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True );
1114                 }
1115             }
1116         }
1117 
1118         if (nBlockAddY > nDestSizeY)
1119             nMarkAddY = nBlockAddY - nDestSizeY;            // fuer Merge-Test
1120         else
1121         {
1122             nEndRow = nStartRow + nDestSizeY;
1123             if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row())
1124             {
1125                 // Same as above if nothing was marked: re-fit selection to
1126                 // unfiltered rows. Extending the selection actually may
1127                 // introduce filtered rows where there weren't any before, so
1128                 // we also need to test for that.
1129                 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1130                 if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc))
1131                 {
1132                     bMarkIsFiltered = true;
1133                     // Worst case: all rows up to the end of the sheet are filtered.
1134                     if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
1135                     {
1136                         ErrorMessage(STR_PASTE_FULL);
1137                         return sal_False;
1138                     }
1139                 }
1140                 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1141                 aFilteredMark.SetMarkArea( aMarkRange);
1142                 if (bMarkIsFiltered)
1143                 {
1144                     ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1145                     aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True);
1146                 }
1147             }
1148         }
1149     }
1150     else
1151     {
1152         nStartCol = GetViewData()->GetCurX();
1153         nStartRow = GetViewData()->GetCurY();
1154         nStartTab = GetViewData()->GetTabNo();
1155         nEndCol = nStartCol + nDestSizeX;
1156         nEndRow = nStartRow + nDestSizeY;
1157         nEndTab = nStartTab;
1158     }
1159 
1160     bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow);
1161 
1162     //  Zielbereich, wie er angezeigt wird:
1163     ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1164 
1165     //  Sollen Zellen eingefuegt werden?
1166     //  (zu grosse nEndCol/nEndRow werden weiter unten erkannt)
1167     sal_Bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits );
1168     if ( bInsertCells )
1169     {
1170         //  #94115# Instead of EnterListAction, the paste undo action is merged into the
1171         //  insert action, so Repeat can insert the right cells
1172 
1173         MarkRange( aUserRange );            // wird vor CopyFromClip sowieso gesetzt
1174 
1175         // #72930# CutMode is reset on insertion of cols/rows but needed again on cell move
1176         sal_Bool bCut = pClipDoc->IsCutMode();
1177         if (!InsertCells( eMoveMode, bRecord, sal_True ))   // is inserting possible?
1178         {
1179             return sal_False;
1180             //  #i21036# EnterListAction isn't used, and InsertCells doesn't insert
1181             //  its undo action on failure, so no undo handling is needed here
1182         }
1183         if ( bCut )
1184             pClipDoc->SetCutMode( bCut );
1185     }
1186     else if (!bOffLimits)
1187     {
1188         sal_Bool bAskIfNotEmpty = bAllowDialogs &&
1189                                 ( nFlags & IDF_CONTENTS ) &&
1190                                 nFunction == PASTE_NOFUNC &&
1191                                 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1192         if ( bAskIfNotEmpty )
1193         {
1194             if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
1195                 return false;
1196         }
1197     }
1198 
1199     SCCOL nClipStartX;                      // Clipboard-Bereich erweitern
1200     SCROW nClipStartY;
1201     pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1202     SCCOL nUndoEndCol = nClipStartX + nClipSizeX;
1203     SCROW nUndoEndRow = nClipStartY + nClipSizeY;   // end of source area in clipboard document
1204     sal_Bool bClipOver = sal_False;
1205     // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers.
1206     // The same end column/row can be used for all calls because the clip doc doesn't contain
1207     // content outside the clip area.
1208     for (SCTAB nClipTab=0; nClipTab<=MAXTAB; nClipTab++)
1209         if ( pClipDoc->HasTable(nClipTab) )
1210             if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, sal_False ) )
1211                 bClipOver = sal_True;
1212     nUndoEndCol -= nClipStartX + nClipSizeX;
1213     nUndoEndRow -= nClipStartY + nClipSizeY;        // now contains only the difference added by ExtendMerge
1214     nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol );
1215     nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells
1216 
1217 //  if (nUndoEndCol < nEndCol) nUndoEndCol = nEndCol;
1218 //  if (nUndoEndRow < nEndRow) nUndoEndRow = nEndRow;
1219 
1220 //  nUndoEndCol += nMarkAddX;
1221 //  nUndoEndRow += nMarkAddY;
1222 
1223     if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW)
1224     {
1225         ErrorMessage(STR_PASTE_FULL);
1226         return sal_False;
1227     }
1228 
1229     pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, sal_False );
1230 
1231         //  Test auf Zellschutz
1232 
1233     ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow );
1234     if (!aTester.IsEditable())
1235     {
1236         ErrorMessage(aTester.GetMessageId());
1237         return sal_False;
1238     }
1239 
1240         //! Test auf Ueberlappung
1241         //! nur wirkliche Schnittmenge testen !!!!!!!
1242 
1243     //  pDoc->HasCommonAttr( StartCol,nStartRow, nUndoEndCol,nUndoEndRow, nStartTab,
1244     //                          pClipDoc, nClipStartX, nClipStartY );
1245 
1246     ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
1247     if ( bRecord )
1248     {
1249         String aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY );
1250         pUndoMgr->EnterListAction( aUndo, aUndo );
1251     }
1252 
1253     if (bClipOver)
1254         if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED ))
1255         {       // "Cell merge not possible if cells already merged"
1256             ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow );
1257             const ScPatternAttr* pPattern = NULL;
1258             const ScMergeAttr* pMergeFlag = NULL;
1259             const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1260             SCCOL nCol = -1;
1261             SCROW nRow1 = -1;
1262             SCROW nRow2 = -1;
1263             while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL )
1264             {
1265                 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1266                 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1267                 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) )
1268                 {
1269                     ScRange aRange(nCol, nRow1, nStartTab);
1270                     pDoc->ExtendOverlapped(aRange);
1271                     pDoc->ExtendMerge(aRange, sal_True, sal_True);
1272                     rDocFunc.UnmergeCells(aRange, bRecord, sal_True);
1273                 }
1274             }
1275         }
1276 
1277     if ( !bCutMode )
1278     {
1279         ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1280         if ( pChangeTrack )
1281             pChangeTrack->ResetLastCut();   // kein CutMode mehr
1282     }
1283 
1284     sal_Bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1285     sal_Bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1286 
1287     ScDocument* pUndoDoc    = NULL;
1288     ScDocument* pRefUndoDoc = NULL;
1289     ScDocument* pRedoDoc    = NULL;
1290     ScRefUndoData* pUndoData = NULL;
1291 
1292     if ( bRecord )
1293     {
1294         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1295         pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo );
1296 
1297         // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
1298         SCTAB nTabCount = pDoc->GetTableCount();
1299         pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1,
1300                                 nUndoFlags, sal_False, pUndoDoc );
1301 
1302         if ( bCutMode )
1303         {
1304             pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1305             pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False );
1306 
1307             pUndoData = new ScRefUndoData( pDoc );
1308         }
1309     }
1310 
1311     sal_uInt16 nExtFlags = 0;
1312     pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1313                                        nEndCol,   nEndRow,   nEndTab );     // content before the change
1314 
1315     if (GetViewData()->IsActive())
1316     {
1317         DoneBlockMode();
1318         InitOwnBlockMode();
1319     }
1320     rMark.SetMarkArea( aUserRange );
1321     MarkDataChanged();
1322 
1323     HideCursor();                           // Cursor aendert sich !
1324 
1325         //
1326         //  Aus Clipboard kopieren,
1327         //  wenn gerechnet werden soll, Originaldaten merken
1328         //
1329 
1330     ScDocument* pMixDoc = NULL;
1331     if ( bSkipEmpty || nFunction )
1332     {
1333         if ( nFlags & IDF_CONTENTS )
1334         {
1335             pMixDoc = new ScDocument( SCDOCMODE_UNDO );
1336             pMixDoc->InitUndo( pDoc, nStartTab, nEndTab );
1337             pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1338                                     IDF_CONTENTS, sal_False, pMixDoc );
1339         }
1340     }
1341 
1342     /*  Make draw layer and start drawing undo.
1343         - Needed before AdjustBlockHeight to track moved drawing objects.
1344         - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1345      */
1346     if ( bPasteDraw )
1347         pDocSh->MakeDrawLayer();
1348     if ( bRecord )
1349         pDoc->BeginDrawUndo();
1350 
1351     sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1352     if (!bAsLink)
1353     {
1354         //  copy normally (original range)
1355         pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags,
1356                 pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered,
1357                 bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) );
1358 
1359         // bei Transpose Referenzen per Hand anpassen
1360         if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) )
1361             pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc );
1362     }
1363     else if (!bTranspose)
1364     {
1365         //  copy with bAsLink=TRUE
1366         pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc,
1367                                 sal_True, sal_True, bIncludeFiltered, bSkipEmpty );
1368     }
1369     else
1370     {
1371         //  alle Inhalte kopieren (im TransClipDoc stehen nur Formeln)
1372         pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc );
1373     }
1374 
1375     // skipped rows and merged cells don't mix
1376     if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
1377         rDocFunc.UnmergeCells( aUserRange, sal_False, sal_True );
1378 
1379     pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, sal_True );    // Refresh
1380                                                                                     // und Bereich neu
1381 
1382     if ( pMixDoc )              // Rechenfunktionen mit Original-Daten auszufuehren ?
1383     {
1384         pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc );
1385     }
1386     delete pMixDoc;
1387 
1388     AdjustBlockHeight();            // update row heights before pasting objects
1389 
1390     ::std::vector< ::rtl::OUString > aExcludedChartNames;
1391     SdrPage* pPage = NULL;
1392 
1393     if ( nFlags & IDF_OBJECTS )
1394     {
1395         ScDrawView* pScDrawView = GetScDrawView();
1396         SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL );
1397         pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL );
1398         if ( pPage )
1399         {
1400             ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
1401         }
1402 
1403         //  Paste the drawing objects after the row heights have been updated.
1404 
1405         pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc,
1406                                 sal_True, sal_False, bIncludeFiltered );
1407     }
1408 
1409     //
1410     //
1411     //
1412 
1413     pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1414                                        nEndCol,   nEndRow,   nEndTab );     // content after the change
1415 
1416 
1417         //  ggf. Autofilter-Koepfe loeschen
1418     if (bCutMode)
1419         if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX,
1420                                         nClipStartY+nClipSizeY, nStartTab ))
1421             pDocSh->PostPaint( nClipStartX,nClipStartY,nStartTab,
1422                                 nClipStartX+nClipSizeX,nClipStartY,nStartTab,
1423                                 PAINT_GRID );
1424 
1425     ShowCursor();                           // Cursor aendert sich !
1426 
1427     //!     Block-Bereich bei RefUndoDoc weglassen !!!
1428 
1429     if ( bRecord )
1430     {
1431         // Redo-Daten werden erst beim ersten Undo kopiert
1432         // ohne RefUndoDoc muss das Redo-Doc noch nicht angelegt werden
1433 
1434         if (pRefUndoDoc)
1435         {
1436             pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
1437             pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo );
1438 
1439             //      angepasste Referenzen ins Redo-Doc
1440 
1441             SCTAB nTabCount = pDoc->GetTableCount();
1442             pRedoDoc->AddUndoTab( 0, nTabCount-1 );
1443             pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc );
1444 
1445             //      alte Referenzen ins Undo-Doc
1446 
1447             //! Tabellen selektieren ?
1448             pUndoDoc->AddUndoTab( 0, nTabCount-1 );
1449             pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL );
1450             pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
1451                                             IDF_FORMULA, sal_False, pUndoDoc );
1452             delete pRefUndoDoc;
1453         }
1454 
1455         //  DeleteUnchanged for pUndoData is in ScUndoPaste ctor,
1456         //  UndoData for redo is made during first undo
1457 
1458         ScUndoPasteOptions aOptions;            // store options for repeat
1459         aOptions.nFunction  = nFunction;
1460         aOptions.bSkipEmpty = bSkipEmpty;
1461         aOptions.bTranspose = bTranspose;
1462         aOptions.bAsLink    = bAsLink;
1463         aOptions.eMoveMode  = eMoveMode;
1464 
1465         SfxUndoAction* pUndo = new ScUndoPaste( pDocSh,
1466                                 nStartCol, nStartRow, nStartTab,
1467                                 nUndoEndCol, nUndoEndRow, nEndTab, aFilteredMark,
1468                                 pUndoDoc, pRedoDoc, nFlags | nUndoFlags,
1469                                 pUndoData, NULL, NULL, NULL,
1470                                 sal_False, &aOptions );     // sal_False = Redo data not yet copied
1471 
1472         if ( bInsertCells )
1473         {
1474             //  Merge the paste undo action into the insert action.
1475             //  Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action.
1476 
1477             pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), sal_True );
1478         }
1479         else
1480             pUndoMgr->AddUndoAction( pUndo );
1481         pUndoMgr->LeaveListAction();
1482     }
1483 
1484     sal_uInt16 nPaint = PAINT_GRID;
1485     if (bColInfo)
1486     {
1487         nPaint |= PAINT_TOP;
1488         nUndoEndCol = MAXCOL;               // nur zum Zeichnen !
1489     }
1490     if (bRowInfo)
1491     {
1492         nPaint |= PAINT_LEFT;
1493         nUndoEndRow = MAXROW;               // nur zum Zeichnen !
1494     }
1495     pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
1496                         nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags );
1497     // AdjustBlockHeight has already been called above
1498 
1499     aModificator.SetDocumentModified();
1500     PostPasteFromClip(aUserRange, rMark);
1501 
1502     if ( nFlags & IDF_OBJECTS )
1503     {
1504         ScModelObj* pModelObj = ( pDocSh ? ScModelObj::getImplementation( pDocSh->GetModel() ) : NULL );
1505         if ( pDoc && pPage && pModelObj )
1506         {
1507             bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() );
1508             const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector );
1509             ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab,
1510                 rProtectedChartRangesVector, aExcludedChartNames, bSameDoc );
1511         }
1512     }
1513 
1514     return sal_True;
1515 }
1516 
1517 bool ScViewFunc::PasteMultiRangesFromClip(
1518     sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1519     bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1520     InsCellCmd eMoveMode, sal_uInt16 /*nContFlags*/, sal_uInt16 nUndoFlags)
1521 {
1522     ScViewData& rViewData = *GetViewData();
1523     ScDocument* pDoc = rViewData.GetDocument();
1524     ScDocShell* pDocSh = rViewData.GetDocShell();
1525     ScMarkData aMark(rViewData.GetMarkData());
1526     const ScAddress& rCurPos = rViewData.GetCurPos();
1527     ScClipParam& rClipParam = pClipDoc->GetClipParam();
1528     SCCOL nColSize = rClipParam.getPasteColSize();
1529     SCROW nRowSize = rClipParam.getPasteRowSize();
1530 
1531     if (bTranspose)
1532     {
1533         if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
1534         {
1535             ErrorMessage(STR_PASTE_FULL);
1536             return false;
1537         }
1538 
1539         ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
1540         pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
1541         pClipDoc = pTransClip.release();
1542         SCCOL nTempColSize = nColSize;
1543         nColSize = static_cast<SCCOL>(nRowSize);
1544         nRowSize = static_cast<SCROW>(nTempColSize);
1545     }
1546 
1547     if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1548     {
1549         ErrorMessage(STR_PASTE_FULL);
1550         return false;
1551     }
1552 
1553     // Determine the first and last selected sheet numbers.
1554     SCTAB nTab1 = aMark.GetFirstSelected();
1555     SCTAB nTab2 = nTab1;
1556     for (SCTAB i = nTab1+1; i <= MAXTAB; ++i)
1557         if (aMark.GetTableSelect(i))
1558             nTab2 = i;
1559 
1560     ScDocShellModificator aModificator(*pDocSh);
1561 
1562     // For multi-selection paste, we don't support cell duplication for larger
1563     // destination range.  In case the destination is marked, we reset it to
1564     // the clip size.
1565     ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
1566                          rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
1567 
1568     // Extend the marked range to account for filtered rows in the destination
1569     // area.
1570     if (ScViewUtil::HasFiltered(aMarkedRange, pDoc))
1571     {
1572         if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize))
1573             return false;
1574     }
1575 
1576     bool bAskIfNotEmpty =
1577         bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1578         nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1579 
1580     if (bAskIfNotEmpty)
1581     {
1582         if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent()))
1583             return false;
1584     }
1585 
1586     aMark.SetMarkArea(aMarkedRange);
1587     MarkRange(aMarkedRange);
1588 
1589     bool bInsertCells = (eMoveMode != INS_NONE);
1590     if (bInsertCells)
1591     {
1592         if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
1593             return false;
1594     }
1595 
1596     ::std::auto_ptr<ScDocument> pUndoDoc;
1597     if (pDoc->IsUndoEnabled())
1598     {
1599         pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1600         pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1601         pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1602     }
1603 
1604     ::std::auto_ptr<ScDocument> pMixDoc;
1605     if ( bSkipEmpty || nFunction )
1606     {
1607         if ( nFlags & IDF_CONTENTS )
1608         {
1609             pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1610             pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1611             pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1612         }
1613     }
1614 
1615     /*  Make draw layer and start drawing undo.
1616         - Needed before AdjustBlockHeight to track moved drawing objects.
1617         - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1618      */
1619     if (nFlags & IDF_OBJECTS)
1620         pDocSh->MakeDrawLayer();
1621     if (pDoc->IsUndoEnabled())
1622         pDoc->BeginDrawUndo();
1623 
1624     CursorSwitcher aCursorSwitch(this);
1625     sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1626     pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
1627                                  true, bAsLink, false, bSkipEmpty);
1628 
1629     if (pMixDoc.get())
1630         pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
1631 
1632     AdjustBlockHeight();            // update row heights before pasting objects
1633 
1634     if (nFlags & IDF_OBJECTS)
1635     {
1636         //  Paste the drawing objects after the row heights have been updated.
1637         pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
1638                                      true, false, false, true);
1639     }
1640 
1641     pDocSh->PostPaint(
1642         aMarkedRange.aStart.Col(), aMarkedRange.aStart.Row(), nTab1,
1643         aMarkedRange.aEnd.Col(), aMarkedRange.aEnd.Row(), nTab1, PAINT_GRID);
1644 
1645     if (pDoc->IsUndoEnabled())
1646     {
1647         ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1648         String aUndo = ScGlobal::GetRscString(
1649             pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1650         pUndoMgr->EnterListAction(aUndo, aUndo);
1651 
1652         ScUndoPasteOptions aOptions;            // store options for repeat
1653         aOptions.nFunction  = nFunction;
1654         aOptions.bSkipEmpty = bSkipEmpty;
1655         aOptions.bTranspose = bTranspose;
1656         aOptions.bAsLink    = bAsLink;
1657         aOptions.eMoveMode  = eMoveMode;
1658 
1659         ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
1660             aMarkedRange.aStart.Col(),
1661             aMarkedRange.aStart.Row(),
1662             aMarkedRange.aStart.Tab(),
1663             aMarkedRange.aEnd.Col(),
1664             aMarkedRange.aEnd.Row(),
1665             aMarkedRange.aEnd.Tab(),
1666             aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions);
1667 
1668         if (bInsertCells)
1669             pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
1670         else
1671             pUndoMgr->AddUndoAction(pUndo, false);
1672 
1673         pUndoMgr->LeaveListAction();
1674     }
1675     aModificator.SetDocumentModified();
1676     PostPasteFromClip(aMarkedRange, aMark);
1677     return true;
1678 }
1679 
1680 void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark)
1681 {
1682     ScViewData* pViewData = GetViewData();
1683     ScDocShell* pDocSh = pViewData->GetDocShell();
1684     ScDocument* pDoc = pViewData->GetDocument();
1685     pDocSh->UpdateOle(pViewData);
1686 
1687     SelectionChanged();
1688 
1689     // #i97876# Spreadsheet data changes are not notified
1690     ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1691     if ( pModelObj && pModelObj->HasChangesListeners() )
1692     {
1693         ScRangeList aChangeRanges;
1694         SCTAB nTabCount = pDoc->GetTableCount();
1695         for ( SCTAB i = 0; i < nTabCount; ++i )
1696         {
1697             if ( rMark.GetTableSelect( i ) )
1698             {
1699                 ScRange aChangeRange(rPasteRange);
1700                 aChangeRange.aStart.SetTab( i );
1701                 aChangeRange.aEnd.SetTab( i );
1702                 aChangeRanges.Append( aChangeRange );
1703             }
1704         }
1705         pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
1706     }
1707 }
1708 
1709 
1710 //----------------------------------------------------------------------------
1711 //      D R A G   A N D   D R O P
1712 //
1713 //  innerhalb des Dokuments
1714 
1715 sal_Bool ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos,
1716                                 sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
1717 {
1718     ScDocShell* pDocSh = GetViewData()->GetDocShell();
1719     HideAllCursors();       // wegen zusammengefassten
1720 
1721     sal_Bool bSuccess = sal_True;
1722     SCTAB nDestTab = rDestPos.Tab();
1723     const ScMarkData& rMark = GetViewData()->GetMarkData();
1724     if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 )
1725     {
1726         //  moving within one table and several tables selected -> apply to all selected tables
1727 
1728         if ( bRecord )
1729         {
1730             String aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY );
1731             pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
1732         }
1733 
1734         //  collect ranges of consecutive selected tables
1735 
1736         ScRange aLocalSource = rSource;
1737         ScAddress aLocalDest = rDestPos;
1738         SCTAB nTabCount = pDocSh->GetDocument()->GetTableCount();
1739         SCTAB nStartTab = 0;
1740         while ( nStartTab < nTabCount && bSuccess )
1741         {
1742             while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) )
1743                 ++nStartTab;
1744             if ( nStartTab < nTabCount )
1745             {
1746                 SCTAB nEndTab = nStartTab;
1747                 while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) )
1748                     ++nEndTab;
1749 
1750                 aLocalSource.aStart.SetTab( nStartTab );
1751                 aLocalSource.aEnd.SetTab( nEndTab );
1752                 aLocalDest.SetTab( nStartTab );
1753 
1754                 bSuccess = pDocSh->GetDocFunc().MoveBlock(
1755                                 aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi );
1756 
1757                 nStartTab = nEndTab + 1;
1758             }
1759         }
1760 
1761         if ( bRecord )
1762             pDocSh->GetUndoManager()->LeaveListAction();
1763     }
1764     else
1765     {
1766         //  move the block as specified
1767         bSuccess = pDocSh->GetDocFunc().MoveBlock(
1768                                 rSource, rDestPos, bCut, bRecord, bPaint, bApi );
1769     }
1770 
1771     ShowAllCursors();
1772     if (bSuccess)
1773     {
1774         //  Zielbereich markieren
1775         ScAddress aDestEnd(
1776                     rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(),
1777                     rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(),
1778                     nDestTab );
1779 
1780         sal_Bool bIncludeFiltered = bCut;
1781         if ( !bIncludeFiltered )
1782         {
1783             // find number of non-filtered rows
1784             SCROW nPastedCount = pDocSh->GetDocument()->CountNonFilteredRows(
1785                 rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab());
1786 
1787             if ( nPastedCount == 0 )
1788                 nPastedCount = 1;
1789             aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 );
1790         }
1791 
1792         MarkRange( ScRange( rDestPos, aDestEnd ), sal_False );          //! sal_False ???
1793 
1794         pDocSh->UpdateOle(GetViewData());
1795         SelectionChanged();
1796     }
1797     return bSuccess;
1798 }
1799 
1800 //  Link innerhalb des Dokuments
1801 
1802 sal_Bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, sal_Bool bApi )
1803 {
1804     //  Test auf Ueberlappung
1805 
1806     if ( rSource.aStart.Tab() == rDestPos.Tab() )
1807     {
1808         SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() );
1809         SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() );
1810 
1811         if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() &&
1812              rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() )
1813         {
1814             if (!bApi)
1815                 ErrorMessage( STR_ERR_LINKOVERLAP );
1816             return sal_False;
1817         }
1818     }
1819 
1820     //  Ausfuehren per Paste
1821 
1822     ScDocument* pDoc = GetViewData()->GetDocument();
1823     ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
1824     pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(),
1825                             rSource.aEnd.Col(), rSource.aEnd.Row(),
1826                             rSource.aStart.Tab(), pClipDoc );
1827 
1828     //  Zielbereich markieren (Cursor setzen, keine Markierung)
1829 
1830     if ( GetViewData()->GetTabNo() != rDestPos.Tab() )
1831         SetTabNo( rDestPos.Tab() );
1832 
1833     MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, sal_False, sal_False );
1834 
1835     //  Paste
1836 
1837     PasteFromClip( IDF_ALL, pClipDoc, PASTE_NOFUNC, sal_False, sal_False, sal_True );       // als Link
1838 
1839     delete pClipDoc;
1840 
1841     return sal_True;
1842 }
1843 
1844 
1845 
1846 
1847