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