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