xref: /aoo42x/main/sc/source/ui/app/transobj.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 // INCLUDE ---------------------------------------------------------------
32 
33 
34 
35 #include "scitems.hxx"
36 #include <editeng/eeitem.hxx>
37 
38 
39 #include <com/sun/star/uno/Sequence.hxx>
40 #include <com/sun/star/embed/XTransactedObject.hpp>
41 
42 #include <unotools/tempfile.hxx>
43 #include <unotools/ucbstreamhelper.hxx>
44 #include <comphelper/storagehelper.hxx>
45 #include <sot/storage.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/virdev.hxx>
48 #include <vos/mutex.hxx>
49 #include <sfx2/app.hxx>
50 #include <sfx2/docfile.hxx>
51 
52 #include "transobj.hxx"
53 #include "document.hxx"
54 #include "viewopti.hxx"
55 #include "editutil.hxx"
56 #include "impex.hxx"
57 #include "cell.hxx"
58 #include "printfun.hxx"
59 #include "docfunc.hxx"
60 #include "scmod.hxx"
61 
62 // for InitDocShell
63 #include <editeng/paperinf.hxx>
64 #include <editeng/sizeitem.hxx>
65 #include <svx/algitem.hxx>
66 #include <svl/intitem.hxx>
67 #include <svl/zforlist.hxx>
68 #include "docsh.hxx"
69 #include "markdata.hxx"
70 #include "stlpool.hxx"
71 #include "viewdata.hxx"
72 #include "dociter.hxx"
73 #include "cellsuno.hxx"
74 
75 using namespace com::sun::star;
76 
77 // -----------------------------------------------------------------------
78 
79 #define SCTRANS_TYPE_IMPEX			1
80 #define SCTRANS_TYPE_EDIT_RTF		2
81 #define SCTRANS_TYPE_EDIT_BIN		3
82 #define SCTRANS_TYPE_EMBOBJ			4
83 
84 // -----------------------------------------------------------------------
85 
86 // static
87 void ScTransferObj::GetAreaSize( ScDocument* pDoc, SCTAB nTab1, SCTAB nTab2, SCROW& nRow, SCCOL& nCol )
88 {
89 	SCCOL nMaxCol = 0;
90 	SCROW nMaxRow = 0;
91 	for( SCTAB nTab = nTab1; nTab <= nTab2; nTab++ )
92 	{
93         SCCOL nLastCol = 0;
94         SCROW nLastRow = 0;
95         // GetPrintArea instead of GetCellArea - include drawing objects
96 		if( pDoc->GetPrintArea( nTab, nLastCol, nLastRow ) )
97 		{
98 			if( nLastCol > nMaxCol )
99 				nMaxCol = nLastCol;
100 			if( nLastRow > nMaxRow  )
101 				nMaxRow = nLastRow;
102 		}
103 	}
104 	nRow = nMaxRow;
105 	nCol = nMaxCol;
106 }
107 
108 // static
109 void ScTransferObj::PaintToDev( OutputDevice* pDev, ScDocument* pDoc, double nPrintFactor,
110 								const ScRange& rBlock, sal_Bool bMetaFile )
111 {
112 	if (!pDoc)
113 		return;
114 
115 	Point aPoint;
116 	Rectangle aBound( aPoint, pDev->GetOutputSize() ); 		//! use size from clip area?
117 
118 	ScViewData aViewData(NULL,NULL);
119 	aViewData.InitData( pDoc );
120 
121 	aViewData.SetTabNo( rBlock.aEnd.Tab() );
122 	aViewData.SetScreen( rBlock.aStart.Col(), rBlock.aStart.Row(),
123 							rBlock.aEnd.Col(), rBlock.aEnd.Row() );
124 
125 	ScPrintFunc::DrawToDev( pDoc, pDev, nPrintFactor, aBound, &aViewData, bMetaFile );
126 }
127 
128 // -----------------------------------------------------------------------
129 
130 ScTransferObj::ScTransferObj( ScDocument* pClipDoc, const TransferableObjectDescriptor& rDesc ) :
131 	pDoc( pClipDoc ),
132 	aObjDesc( rDesc ),
133 	nDragHandleX( 0 ),
134 	nDragHandleY( 0 ),
135 	nDragSourceFlags( 0 ),
136 	bDragWasInternal( sal_False ),
137     bUsedForLink( sal_False ),
138     bUseInApi( false )
139 {
140 	DBG_ASSERT(pDoc->IsClipboard(), "wrong document");
141 
142 	//
143 	// get aBlock from clipboard doc
144 	//
145 
146 	SCCOL nCol1;
147 	SCROW nRow1;
148 	SCCOL nCol2;
149 	SCROW nRow2;
150 	pDoc->GetClipStart( nCol1, nRow1 );
151 	pDoc->GetClipArea( nCol2, nRow2, sal_True );	// real source area - include filtered rows
152     nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nCol1 );
153     nRow2 = sal::static_int_cast<SCROW>( nRow2 + nRow1 );
154 
155 	SCCOL nDummy;
156 	pDoc->GetClipArea( nDummy, nNonFiltered, sal_False );
157     bHasFiltered = (nNonFiltered < (nRow2 - nRow1));
158 	++nNonFiltered;		// to get count instead of diff
159 
160 	SCTAB nTab1=0;
161 	SCTAB nTab2=0;
162 	sal_Bool bFirst = sal_True;
163 	for (SCTAB i=0; i<=MAXTAB; i++)
164 		if (pDoc->HasTable(i))
165 		{
166 			if (bFirst)
167 				nTab1 = i;
168 			nTab2 = i;
169 			bFirst = sal_False;
170 		}
171 	DBG_ASSERT(!bFirst, "no sheet selected");
172 
173 	//	only limit to used cells if whole sheet was marked
174 	//	(so empty cell areas can be copied)
175 	if ( nCol2>=MAXCOL && nRow2>=MAXROW )
176 	{
177         SCROW nMaxRow;
178         SCCOL nMaxCol;
179         GetAreaSize( pDoc, nTab1, nTab2, nMaxRow, nMaxCol );
180 		if( nMaxRow < nRow2 )
181 			nRow2 = nMaxRow;
182 		if( nMaxCol < nCol2 )
183 			nCol2 = nMaxCol;
184 	}
185 
186 	aBlock = ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
187 	nVisibleTab = nTab1;	// valid table as default
188 
189 	Rectangle aMMRect = pDoc->GetMMRect( nCol1,nRow1, nCol2,nRow2, nTab1 );
190     aObjDesc.maSize = aMMRect.GetSize();
191     PrepareOLE( aObjDesc );
192 }
193 
194 ScTransferObj::~ScTransferObj()
195 {
196 	Application::GetSolarMutex().acquire();
197 
198 	ScModule* pScMod = SC_MOD();
199 	if ( pScMod->GetClipData().pCellClipboard == this )
200 	{
201 		DBG_ERROR("ScTransferObj wasn't released");
202 		pScMod->SetClipObject( NULL, NULL );
203 	}
204 	if ( pScMod->GetDragData().pCellTransfer == this )
205 	{
206 		DBG_ERROR("ScTransferObj wasn't released");
207 		pScMod->ResetDragObject();
208 	}
209 
210 	delete pDoc;		// ScTransferObj is owner of clipboard document
211 
212 	aDocShellRef.Clear();	// before releasing the mutex
213 
214     aDrawPersistRef.Clear();                    // after the model
215 
216 	Application::GetSolarMutex().release();
217 }
218 
219 // static
220 ScTransferObj* ScTransferObj::GetOwnClipboard( Window* pUIWin )
221 {
222 	ScTransferObj* pObj = SC_MOD()->GetClipData().pCellClipboard;
223 	if ( pObj && pUIWin )
224 	{
225 		//	check formats to see if pObj is really in the system clipboard
226 
227 		//	pUIWin is NULL when called from core (IsClipboardSource),
228 		//	in that case don't access the system clipboard, because the call
229 		//	may be from other clipboard operations (like flushing, #86059#)
230 
231 		TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pUIWin ) );
232 		if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_DIF ) )
233 		{
234 //			DBG_ERROR("ScTransferObj wasn't released");
235 			pObj = NULL;
236 		}
237 	}
238 	return pObj;
239 }
240 
241 void ScTransferObj::AddSupportedFormats()
242 {
243 	AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
244 	AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
245 	AddFormat( SOT_FORMAT_GDIMETAFILE );
246 	AddFormat( SOT_FORMAT_BITMAP );
247 
248 	// ScImportExport formats
249 	AddFormat( SOT_FORMATSTR_ID_HTML );
250 	AddFormat( SOT_FORMATSTR_ID_SYLK );
251 	AddFormat( SOT_FORMATSTR_ID_LINK );
252 	AddFormat( SOT_FORMATSTR_ID_DIF );
253 	AddFormat( SOT_FORMAT_STRING );
254 
255 	AddFormat( SOT_FORMAT_RTF );
256 	if ( aBlock.aStart == aBlock.aEnd )
257 		AddFormat( SOT_FORMATSTR_ID_EDITENGINE );
258 }
259 
260 sal_Bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor )
261 {
262 	sal_uInt32	nFormat = SotExchange::GetFormat( rFlavor );
263 	sal_Bool	bOK = sal_False;
264 
265 	if( HasFormat( nFormat ) )
266 	{
267 		if ( nFormat == SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR || nFormat == SOT_FORMATSTR_ID_OBJECTDESCRIPTOR )
268 		{
269 			bOK = SetTransferableObjectDescriptor( aObjDesc, rFlavor );
270 		}
271 		else if ( ( nFormat == SOT_FORMAT_RTF || nFormat == SOT_FORMATSTR_ID_EDITENGINE ) &&
272 						aBlock.aStart == aBlock.aEnd )
273 		{
274 			//	RTF from a single cell is handled by EditEngine
275 
276 			SCCOL nCol = aBlock.aStart.Col();
277 			SCROW nRow = aBlock.aStart.Row();
278 			SCTAB nTab = aBlock.aStart.Tab();
279 
280 			const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
281 			ScTabEditEngine aEngine( *pPattern, pDoc->GetEditPool() );
282 			ScBaseCell* pCell = NULL;
283 			pDoc->GetCell( nCol, nRow, nTab, pCell );
284 			if (pCell)
285 			{
286 				if (pCell->GetCellType() == CELLTYPE_EDIT)
287 				{
288 					const EditTextObject* pObj;
289 					((ScEditCell*)pCell)->GetData(pObj);
290 					aEngine.SetText( *pObj );
291 				}
292 				else
293 				{
294 					String aText;
295 					pDoc->GetString( nCol, nRow, nTab, aText );
296 					aEngine.SetText(aText);
297 				}
298 			}
299 
300 			bOK = SetObject( &aEngine,
301 							(nFormat == FORMAT_RTF) ? SCTRANS_TYPE_EDIT_RTF : SCTRANS_TYPE_EDIT_BIN,
302 							rFlavor );
303 		}
304 		else if ( ScImportExport::IsFormatSupported( nFormat ) || nFormat == SOT_FORMAT_RTF )
305 		{
306 			//	if this transfer object was used to create a DDE link, filtered rows
307 			//	have to be included for subsequent calls (to be consistent with link data)
308 			if ( nFormat == SOT_FORMATSTR_ID_LINK )
309 				bUsedForLink = sal_True;
310 
311 			sal_Bool bIncludeFiltered = pDoc->IsCutMode() || bUsedForLink;
312 
313 			ScImportExport aObj( pDoc, aBlock );
314             if ( bUsedForLink )
315                 aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) );
316 			aObj.SetFormulas( pDoc->GetViewOptions().GetOption( VOPT_FORMULAS ) );
317 			aObj.SetIncludeFiltered( bIncludeFiltered );
318 
319 			//	DataType depends on format type:
320 
321 			if ( rFlavor.DataType.equals( ::getCppuType( (const ::rtl::OUString*) 0 ) ) )
322 			{
323 				rtl::OUString aString;
324 				if ( aObj.ExportString( aString, nFormat ) )
325 					bOK = SetString( aString, rFlavor );
326 			}
327 			else if ( rFlavor.DataType.equals( ::getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ) )
328 			{
329 				//	SetObject converts a stream into a Int8-Sequence
330 				bOK = SetObject( &aObj, SCTRANS_TYPE_IMPEX, rFlavor );
331 			}
332 			else
333 			{
334 				DBG_ERROR("unknown DataType");
335 			}
336 		}
337 		else if ( nFormat == SOT_FORMAT_BITMAP )
338 		{
339 			Rectangle aMMRect = pDoc->GetMMRect( aBlock.aStart.Col(), aBlock.aStart.Row(),
340 												 aBlock.aEnd.Col(), aBlock.aEnd.Row(),
341 												 aBlock.aStart.Tab() );
342 			VirtualDevice aVirtDev;
343 			aVirtDev.SetOutputSizePixel( aVirtDev.LogicToPixel( aMMRect.GetSize(), MAP_100TH_MM ) );
344 
345 			PaintToDev( &aVirtDev, pDoc, 1.0, aBlock, sal_False );
346 
347 			aVirtDev.SetMapMode( MapMode( MAP_PIXEL ) );
348 			Bitmap aBmp = aVirtDev.GetBitmap( Point(), aVirtDev.GetOutputSize() );
349 			bOK = SetBitmap( aBmp, rFlavor );
350 		}
351 		else if ( nFormat == SOT_FORMAT_GDIMETAFILE )
352 		{
353 			InitDocShell();
354             SfxObjectShell* pEmbObj = aDocShellRef;
355 
356 			// like SvEmbeddedTransfer::GetData:
357 
358 			GDIMetaFile		aMtf;
359 			VirtualDevice	aVDev;
360 			MapMode			aMapMode( pEmbObj->GetMapUnit() );
361 			Rectangle		aVisArea( pEmbObj->GetVisArea( ASPECT_CONTENT ) );
362 
363 			aVDev.EnableOutput( sal_False );
364 			aVDev.SetMapMode( aMapMode );
365 			aMtf.SetPrefSize( aVisArea.GetSize() );
366 			aMtf.SetPrefMapMode( aMapMode );
367 			aMtf.Record( &aVDev );
368 
369 			pEmbObj->DoDraw( &aVDev, Point(), aVisArea.GetSize(), JobSetup(), ASPECT_CONTENT );
370 
371 			aMtf.Stop();
372 			aMtf.WindStart();
373 
374 			bOK = SetGDIMetaFile( aMtf, rFlavor );
375 		}
376 		else if ( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE )
377 		{
378             //TODO/LATER: differentiate between formats?!
379 			InitDocShell();			// set aDocShellRef
380 
381             SfxObjectShell* pEmbObj = aDocShellRef;
382 			bOK = SetObject( pEmbObj, SCTRANS_TYPE_EMBOBJ, rFlavor );
383 		}
384 	}
385 	return bOK;
386 }
387 
388 sal_Bool ScTransferObj::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId,
389 										const datatransfer::DataFlavor& rFlavor )
390 {
391 	// called from SetObject, put data into stream
392 
393 	sal_Bool bRet = sal_False;
394 	switch (nUserObjectId)
395 	{
396 		case SCTRANS_TYPE_IMPEX:
397 			{
398 				ScImportExport* pImpEx = (ScImportExport*)pUserObject;
399 
400 				sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
401                 // mba: no BaseURL for data exchange
402                 if ( pImpEx->ExportStream( *rxOStm, String(), nFormat ) )
403 					bRet = ( rxOStm->GetError() == ERRCODE_NONE );
404 			}
405 			break;
406 
407 		case SCTRANS_TYPE_EDIT_RTF:
408 		case SCTRANS_TYPE_EDIT_BIN:
409 			{
410 				ScTabEditEngine* pEngine = (ScTabEditEngine*)pUserObject;
411 				if ( nUserObjectId == SCTRANS_TYPE_EDIT_RTF )
412 				{
413 					pEngine->Write( *rxOStm, EE_FORMAT_RTF );
414 					bRet = ( rxOStm->GetError() == ERRCODE_NONE );
415 				}
416 				else
417 				{
418 					//	#107722# can't use Write for EditEngine format because that would
419 					//	write old format without support for unicode characters.
420 					//	Get the data from the EditEngine's transferable instead.
421 
422 					sal_uInt16 nParCnt = pEngine->GetParagraphCount();
423 					if ( nParCnt == 0 )
424 						nParCnt = 1;
425 					ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) );
426 
427 					uno::Reference<datatransfer::XTransferable> xEditTrans = pEngine->CreateTransferable( aSel );
428 					TransferableDataHelper aEditHelper( xEditTrans );
429 
430 					bRet = aEditHelper.GetSotStorageStream( rFlavor, rxOStm );
431 				}
432 			}
433 			break;
434 
435 		case SCTRANS_TYPE_EMBOBJ:
436 			{
437                 // TODO/MBA: testing
438                 SfxObjectShell*   pEmbObj = (SfxObjectShell*) pUserObject;
439                 ::utl::TempFile     aTempFile;
440                 aTempFile.EnableKillingFile();
441                 uno::Reference< embed::XStorage > xWorkStore =
442                     ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
443 
444                 // write document storage
445                 pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, sal_False );
446 
447                 // mba: no relative ULRs for clipboard!
448                 SfxMedium aMedium( xWorkStore, String() );
449                 bRet = pEmbObj->DoSaveObjectAs( aMedium, sal_False );
450                 pEmbObj->DoSaveCompleted();
451 
452                 uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
453                 if ( xTransact.is() )
454                     xTransact->commit();
455 
456                 SvStream* pSrcStm = ::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), STREAM_READ );
457                 if( pSrcStm )
458                 {
459                     rxOStm->SetBufferSize( 0xff00 );
460                     *rxOStm << *pSrcStm;
461                     delete pSrcStm;
462                 }
463 
464                 bRet = sal_True;
465 
466                 xWorkStore->dispose();
467                 xWorkStore = uno::Reference < embed::XStorage >();
468                 rxOStm->Commit();
469 			}
470 			break;
471 
472 		default:
473 			DBG_ERROR("unknown object id");
474 	}
475 	return bRet;
476 }
477 
478 void ScTransferObj::ObjectReleased()
479 {
480 	ScModule* pScMod = SC_MOD();
481 	if ( pScMod->GetClipData().pCellClipboard == this )
482 		pScMod->SetClipObject( NULL, NULL );
483 
484 	TransferableHelper::ObjectReleased();
485 }
486 
487 void ScTransferObj::DragFinished( sal_Int8 nDropAction )
488 {
489 	if ( nDropAction == DND_ACTION_MOVE && !bDragWasInternal && !(nDragSourceFlags & SC_DROP_NAVIGATOR) )
490 	{
491 		//	move: delete source data
492 		ScDocShell* pSourceSh = GetSourceDocShell();
493 		if (pSourceSh)
494 		{
495 			ScMarkData aMarkData = GetSourceMarkData();
496 			//	external drag&drop doesn't copy objects, so they also aren't deleted:
497 			//	#105703# bApi=sal_True, don't show error messages from drag&drop
498 			pSourceSh->GetDocFunc().DeleteContents( aMarkData, IDF_ALL & ~IDF_OBJECTS, sal_True, sal_True );
499 		}
500 	}
501 
502 	ScModule* pScMod = SC_MOD();
503 	if ( pScMod->GetDragData().pCellTransfer == this )
504 		pScMod->ResetDragObject();
505 
506 	xDragSourceRanges = NULL;		// don't keep source after dropping
507 
508 	TransferableHelper::DragFinished( nDropAction );
509 }
510 
511 void ScTransferObj::SetDragHandlePos( SCCOL nX, SCROW nY )
512 {
513 	nDragHandleX = nX;
514 	nDragHandleY = nY;
515 }
516 
517 void ScTransferObj::SetVisibleTab( SCTAB nNew )
518 {
519 	nVisibleTab = nNew;
520 }
521 
522 void ScTransferObj::SetDrawPersist( const SfxObjectShellRef& rRef )
523 {
524     aDrawPersistRef = rRef;
525 }
526 
527 void ScTransferObj::SetDragSource( ScDocShell* pSourceShell, const ScMarkData& rMark )
528 {
529 	ScRangeList aRanges;
530 	rMark.FillRangeListWithMarks( &aRanges, sal_False );
531 	xDragSourceRanges = new ScCellRangesObj( pSourceShell, aRanges );
532 }
533 
534 void ScTransferObj::SetDragSourceFlags( sal_uInt16 nFlags )
535 {
536 	nDragSourceFlags = nFlags;
537 }
538 
539 void ScTransferObj::SetDragWasInternal()
540 {
541 	bDragWasInternal = sal_True;
542 }
543 
544 void ScTransferObj::SetUseInApi( bool bSet )
545 {
546     bUseInApi = bSet;
547 }
548 
549 ScDocument* ScTransferObj::GetSourceDocument()
550 {
551 	ScDocShell* pSourceDocSh = GetSourceDocShell();
552 	if (pSourceDocSh)
553 		return pSourceDocSh->GetDocument();
554 	return NULL;
555 }
556 
557 ScDocShell* ScTransferObj::GetSourceDocShell()
558 {
559 	ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
560 	if (pRangesObj)
561 		return pRangesObj->GetDocShell();
562 
563 	return NULL;	// none set
564 }
565 
566 ScMarkData ScTransferObj::GetSourceMarkData()
567 {
568 	ScMarkData aMarkData;
569 	ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
570 	if (pRangesObj)
571 	{
572 		const ScRangeList& rRanges = pRangesObj->GetRangeList();
573 		aMarkData.MarkFromRangeList( rRanges, sal_False );
574 	}
575 	return aMarkData;
576 }
577 
578 //
579 //	initialize aDocShellRef with a live document from the ClipDoc
580 //
581 
582 void ScTransferObj::InitDocShell()
583 {
584 	if ( !aDocShellRef.Is() )
585 	{
586 		ScDocShell* pDocSh = new ScDocShell;
587 		aDocShellRef = pDocSh;		// ref must be there before InitNew
588 
589 		pDocSh->DoInitNew(NULL);
590 
591 		ScDocument* pDestDoc = pDocSh->GetDocument();
592 		ScMarkData aDestMark;
593 		aDestMark.SelectTable( 0, sal_True );
594 
595         pDestDoc->SetDocOptions( pDoc->GetDocOptions() );   // #i42666#
596 
597 		String aTabName;
598 		pDoc->GetName( aBlock.aStart.Tab(), aTabName );
599 		pDestDoc->RenameTab( 0, aTabName, sal_False );			// no UpdateRef (empty)
600 
601 		pDestDoc->CopyStdStylesFrom( pDoc );
602 
603 		SCCOL nStartX = aBlock.aStart.Col();
604 		SCROW nStartY = aBlock.aStart.Row();
605 		SCCOL nEndX = aBlock.aEnd.Col();
606 		SCROW nEndY = aBlock.aEnd.Row();
607 
608 		//	widths / heights
609 		//	(must be copied before CopyFromClip, for drawing objects)
610 
611 		SCCOL nCol, nLastCol;
612 		SCTAB nSrcTab = aBlock.aStart.Tab();
613         pDestDoc->SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab));
614 		for (nCol=nStartX; nCol<=nEndX; nCol++)
615 			if ( pDoc->ColHidden(nCol, nSrcTab, nLastCol) )
616 				pDestDoc->ShowCol( nCol, 0, sal_False );
617 			else
618 				pDestDoc->SetColWidth( nCol, 0, pDoc->GetColWidth( nCol, nSrcTab ) );
619 
620         ScBitMaskCompressedArray< SCROW, sal_uInt8> & rDestRowFlags =
621             pDestDoc->GetRowFlagsArrayModifiable(0);
622 
623 		for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow)
624 		{
625             sal_uInt8 nSourceFlags = pDoc->GetRowFlags(nRow, nSrcTab);
626             SCROW nLastRow = -1;
627             if ( pDoc->RowHidden(nRow, nSrcTab, nLastRow) )
628 				pDestDoc->ShowRow( nRow, 0, sal_False );
629 			else
630 			{
631 				pDestDoc->SetRowHeight( nRow, 0, pDoc->GetOriginalHeight( nRow, nSrcTab ) );
632 
633 				//	if height was set manually, that flag has to be copied, too
634 				if ( nSourceFlags & CR_MANUALSIZE )
635 					rDestRowFlags.OrValue( nRow, CR_MANUALSIZE);
636 			}
637 		}
638 
639 		if ( pDoc->GetDrawLayer() )
640 			pDocSh->MakeDrawLayer();
641 
642 		//	cell range is copied to the original position, but on the first sheet
643 		//	-> bCutMode must be set
644 		//	pDoc is always a Clipboard-document
645 
646 		ScRange aDestRange( nStartX,nStartY,0, nEndX,nEndY,0 );
647 		sal_Bool bWasCut = pDoc->IsCutMode();
648 		if (!bWasCut)
649 			pDoc->SetClipArea( aDestRange, sal_True );			// Cut
650 		pDestDoc->CopyFromClip( aDestRange, aDestMark, IDF_ALL, NULL, pDoc, sal_False );
651 		pDoc->SetClipArea( aDestRange, bWasCut );
652 
653 		StripRefs( pDoc, nStartX,nStartY, nEndX,nEndY, pDestDoc, 0,0 );
654 
655 		ScRange aMergeRange = aDestRange;
656 		pDestDoc->ExtendMerge( aMergeRange, sal_True );
657 
658 		pDoc->CopyDdeLinks( pDestDoc );			// copy values of DDE Links
659 
660 		//	page format (grid etc) and page size (maximum size for ole object)
661 
662 		Size aPaperSize = SvxPaperInfo::GetPaperSize( PAPER_A4 );		// Twips
663 		ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
664 		String aStyleName = pDoc->GetPageStyle( aBlock.aStart.Tab() );
665 		SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
666 		if (pStyleSheet)
667 		{
668 			const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
669 			aPaperSize = ((const SvxSizeItem&) rSourceSet.Get(ATTR_PAGE_SIZE)).GetSize();
670 
671 			//	CopyStyleFrom kopiert SetItems mit richtigem Pool
672 			ScStyleSheetPool* pDestPool = pDestDoc->GetStyleSheetPool();
673 			pDestPool->CopyStyleFrom( pStylePool, aStyleName, SFX_STYLE_FAMILY_PAGE );
674 		}
675 
676 		ScViewData aViewData( pDocSh, NULL );
677 		aViewData.SetScreen( nStartX,nStartY, nEndX,nEndY );
678 		aViewData.SetCurX( nStartX );
679 		aViewData.SetCurY( nStartY );
680 
681 		pDestDoc->SetViewOptions( pDoc->GetViewOptions() );
682 
683 		//		Size
684 		//! get while copying sizes
685 
686 		long nPosX = 0;
687 		long nPosY = 0;
688 
689 		for (nCol=0; nCol<nStartX; nCol++)
690 			nPosX += pDestDoc->GetColWidth( nCol, 0 );
691         nPosY += pDestDoc->GetRowHeight( 0, nStartY-1, 0 );
692 		nPosX = (long) ( nPosX * HMM_PER_TWIPS );
693 		nPosY = (long) ( nPosY * HMM_PER_TWIPS );
694 
695 
696 		aPaperSize.Width()  *= 2;		// limit OLE object to double of page size
697 		aPaperSize.Height() *= 2;
698 
699 		long nSizeX = 0;
700 		long nSizeY = 0;
701 		for (nCol=nStartX; nCol<=nEndX; nCol++)
702 		{
703 			long nAdd = pDestDoc->GetColWidth( nCol, 0 );
704 			if ( nSizeX+nAdd > aPaperSize.Width() && nSizeX )	// above limit?
705 				break;
706 			nSizeX += nAdd;
707 		}
708 		for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
709 		{
710 			long nAdd = pDestDoc->GetRowHeight( nRow, 0 );
711 			if ( nSizeY+nAdd > aPaperSize.Height() && nSizeY )	// above limit?
712 				break;
713 			nSizeY += nAdd;
714 		}
715 		nSizeX = (long) ( nSizeX * HMM_PER_TWIPS );
716 		nSizeY = (long) ( nSizeY * HMM_PER_TWIPS );
717 
718 //		pDocSh->SetVisAreaSize( Size(nSizeX,nSizeY) );
719 
720 		Rectangle aNewArea( Point(nPosX,nPosY), Size(nSizeX,nSizeY) );
721         //TODO/LATER: why twice?!
722         //pDocSh->SvInPlaceObject::SetVisArea( aNewArea );
723 		pDocSh->SetVisArea( aNewArea );
724 
725 		pDocSh->UpdateOle(&aViewData, sal_True);
726 
727 		//!	SetDocumentModified?
728 		if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() )
729 			pDestDoc->UpdateChartListenerCollection();
730 	}
731 }
732 
733 //	static
734 SfxObjectShell* ScTransferObj::SetDrawClipDoc( sal_Bool bAnyOle )
735 {
736 	// update ScGlobal::pDrawClipDocShellRef
737 
738     delete ScGlobal::pDrawClipDocShellRef;
739     if (bAnyOle)
740     {
741         ScGlobal::pDrawClipDocShellRef =
742                         new ScDocShellRef(new ScDocShell(SFX_CREATE_MODE_INTERNAL));      // there must be a ref
743         (*ScGlobal::pDrawClipDocShellRef)->DoInitNew(NULL);
744         return *ScGlobal::pDrawClipDocShellRef;
745     }
746     else
747     {
748         ScGlobal::pDrawClipDocShellRef = NULL;
749         return NULL;
750     }
751 }
752 
753 //	static
754 void ScTransferObj::StripRefs( ScDocument* pDoc,
755 					SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
756 					ScDocument* pDestDoc, SCCOL nSubX, SCROW nSubY )
757 {
758 	if (!pDestDoc)
759 	{
760 		pDestDoc = pDoc;
761 		DBG_ASSERT(nSubX==0&&nSubY==0, "can't move within the document");
762 	}
763 
764 	//	In a clipboard doc the data don't have to be on the first sheet
765 
766 	SCTAB nSrcTab = 0;
767 	while (nSrcTab<MAXTAB && !pDoc->HasTable(nSrcTab))
768 		++nSrcTab;
769 	SCTAB nDestTab = 0;
770 	while (nDestTab<MAXTAB && !pDestDoc->HasTable(nDestTab))
771 		++nDestTab;
772 
773 	if (!pDoc->HasTable(nSrcTab) || !pDestDoc->HasTable(nDestTab))
774 	{
775 		DBG_ERROR("Sheet not found in ScTransferObj::StripRefs");
776 		return;
777 	}
778 
779 	SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
780 	ScRange aRef;
781 
782 	ScCellIterator aIter( pDoc, nStartX, nStartY, nSrcTab, nEndX, nEndY, nSrcTab );
783 	ScBaseCell* pCell = aIter.GetFirst();
784 	while (pCell)
785 	{
786 		if (pCell->GetCellType() == CELLTYPE_FORMULA)
787 		{
788 			ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
789 			sal_Bool bOut = sal_False;
790 			ScDetectiveRefIter aRefIter( pFCell );
791 			while ( !bOut && aRefIter.GetNextRef( aRef ) )
792 			{
793 				if ( aRef.aStart.Tab() != nSrcTab || aRef.aEnd.Tab() != nSrcTab ||
794 						aRef.aStart.Col() < nStartX || aRef.aEnd.Col() > nEndX ||
795 						aRef.aStart.Row() < nStartY || aRef.aEnd.Row() > nEndY )
796 					bOut = sal_True;
797 			}
798 			if (bOut)
799 			{
800 				SCCOL nCol = aIter.GetCol() - nSubX;
801 				SCROW nRow = aIter.GetRow() - nSubY;
802 
803 				ScBaseCell* pNew = 0;
804 				sal_uInt16 nErrCode = pFCell->GetErrCode();
805 				if (nErrCode)
806 				{
807 					pNew = new ScStringCell( ScGlobal::GetErrorString(nErrCode) );
808 					if ( ((const SvxHorJustifyItem*) pDestDoc->GetAttr(
809 							nCol,nRow,nDestTab, ATTR_HOR_JUSTIFY))->GetValue() ==
810 							SVX_HOR_JUSTIFY_STANDARD )
811 						pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
812 								SvxHorJustifyItem(SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY) );
813 				}
814 				else if (pFCell->IsValue())
815 				{
816 					double fVal = pFCell->GetValue();
817 					pNew = new ScValueCell( fVal );
818 				}
819 				else
820 				{
821 					String aStr;
822 					pFCell->GetString(aStr);
823                     if ( pFCell->IsMultilineResult() )
824                         pNew = new ScEditCell( aStr, pDestDoc );
825                     else
826                         pNew = new ScStringCell( aStr );
827 				}
828 				pDestDoc->PutCell( nCol,nRow,nDestTab, pNew );
829 
830 				//	number formats
831 
832 				sal_uLong nOldFormat = ((const SfxUInt32Item*)
833 								pDestDoc->GetAttr(nCol,nRow,nDestTab, ATTR_VALUE_FORMAT))->GetValue();
834 				if ( (nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
835 				{
836 					sal_uLong nNewFormat = pFCell->GetStandardFormat( *pFormatter,
837 						nOldFormat );
838 					pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
839 								SfxUInt32Item(ATTR_VALUE_FORMAT, nNewFormat) );
840 				}
841 			}
842 		}
843 		pCell = aIter.GetNext();
844 	}
845 }
846 
847 const com::sun::star::uno::Sequence< sal_Int8 >& ScTransferObj::getUnoTunnelId()
848 {
849     static com::sun::star::uno::Sequence< sal_Int8 > aSeq;
850     if( !aSeq.getLength() )
851     {
852         static osl::Mutex           aCreateMutex;
853         osl::Guard< osl::Mutex >    aGuard( aCreateMutex );
854         aSeq.realloc( 16 );
855         rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
856     }
857     return aSeq;
858 }
859 
860 sal_Int64 SAL_CALL ScTransferObj::getSomething( const com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( com::sun::star::uno::RuntimeException )
861 {
862     sal_Int64 nRet;
863     if( ( rId.getLength() == 16 ) &&
864         ( 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
865     {
866         nRet = reinterpret_cast< sal_Int64 >( this );
867     }
868     else
869         nRet = TransferableHelper::getSomething(rId);
870     return nRet;
871 }
872 
873 
874