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