Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / app / transobj.cxx
blob5306c954c3db817cbd664655a5c7cb21e9620c3d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <editeng/eeitem.hxx>
22 #include <editeng/justifyitem.hxx>
25 #include <com/sun/star/uno/Sequence.hxx>
26 #include <com/sun/star/embed/XTransactedObject.hpp>
28 #include <unotools/tempfile.hxx>
29 #include <unotools/ucbstreamhelper.hxx>
30 #include <comphelper/storagehelper.hxx>
31 #include <comphelper/servicehelper.hxx>
32 #include <sot/storage.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/virdev.hxx>
35 #include <osl/mutex.hxx>
36 #include <sfx2/app.hxx>
37 #include <sfx2/docfile.hxx>
39 #include "transobj.hxx"
40 #include "document.hxx"
41 #include "viewopti.hxx"
42 #include "editutil.hxx"
43 #include "impex.hxx"
44 #include "formulacell.hxx"
45 #include "printfun.hxx"
46 #include "docfunc.hxx"
47 #include "scmod.hxx"
48 #include "dragdata.hxx"
49 #include "clipdata.hxx"
50 #include "clipparam.hxx"
52 // for InitDocShell
53 #include <editeng/paperinf.hxx>
54 #include <editeng/sizeitem.hxx>
55 #include <svx/algitem.hxx>
56 #include <svl/intitem.hxx>
57 #include <svl/zforlist.hxx>
58 #include "docsh.hxx"
59 #include "markdata.hxx"
60 #include "stlpool.hxx"
61 #include "viewdata.hxx"
62 #include "dociter.hxx"
63 #include "cellsuno.hxx"
64 #include "stringutil.hxx"
65 #include "formulaiter.hxx"
67 using namespace com::sun::star;
69 // -----------------------------------------------------------------------
71 #define SCTRANS_TYPE_IMPEX 1
72 #define SCTRANS_TYPE_EDIT_RTF 2
73 #define SCTRANS_TYPE_EDIT_BIN 3
74 #define SCTRANS_TYPE_EMBOBJ 4
76 // -----------------------------------------------------------------------
78 void ScTransferObj::GetAreaSize( ScDocument* pDoc, SCTAB nTab1, SCTAB nTab2, SCROW& nRow, SCCOL& nCol )
80 SCCOL nMaxCol = 0;
81 SCROW nMaxRow = 0;
82 for( SCTAB nTab = nTab1; nTab <= nTab2; nTab++ )
84 SCCOL nLastCol = 0;
85 SCROW nLastRow = 0;
86 // GetPrintArea instead of GetCellArea - include drawing objects
87 if( pDoc->GetPrintArea( nTab, nLastCol, nLastRow ) )
89 if( nLastCol > nMaxCol )
90 nMaxCol = nLastCol;
91 if( nLastRow > nMaxRow )
92 nMaxRow = nLastRow;
95 nRow = nMaxRow;
96 nCol = nMaxCol;
99 void ScTransferObj::PaintToDev( OutputDevice* pDev, ScDocument* pDoc, double nPrintFactor,
100 const ScRange& rBlock, sal_Bool bMetaFile )
102 if (!pDoc)
103 return;
105 Point aPoint;
106 Rectangle aBound( aPoint, pDev->GetOutputSize() ); //! use size from clip area?
108 ScViewData aViewData(NULL,NULL);
109 aViewData.InitData( pDoc );
111 aViewData.SetTabNo( rBlock.aEnd.Tab() );
112 aViewData.SetScreen( rBlock.aStart.Col(), rBlock.aStart.Row(),
113 rBlock.aEnd.Col(), rBlock.aEnd.Row() );
115 ScPrintFunc::DrawToDev( pDoc, pDev, nPrintFactor, aBound, &aViewData, bMetaFile );
118 // -----------------------------------------------------------------------
120 ScTransferObj::ScTransferObj( ScDocument* pClipDoc, const TransferableObjectDescriptor& rDesc ) :
121 pDoc( pClipDoc ),
122 aObjDesc( rDesc ),
123 nDragHandleX( 0 ),
124 nDragHandleY( 0 ),
125 nDragSourceFlags( 0 ),
126 bDragWasInternal( false ),
127 bUsedForLink( false ),
128 bUseInApi( false )
130 OSL_ENSURE(pDoc->IsClipboard(), "wrong document");
133 // get aBlock from clipboard doc
136 SCCOL nCol1;
137 SCROW nRow1;
138 SCCOL nCol2;
139 SCROW nRow2;
140 pDoc->GetClipStart( nCol1, nRow1 );
141 pDoc->GetClipArea( nCol2, nRow2, true ); // real source area - include filtered rows
142 nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nCol1 );
143 nRow2 = sal::static_int_cast<SCROW>( nRow2 + nRow1 );
145 SCCOL nDummy;
146 pDoc->GetClipArea( nDummy, nNonFiltered, false );
147 bHasFiltered = (nNonFiltered < (nRow2 - nRow1));
148 ++nNonFiltered; // to get count instead of diff
150 SCTAB nTab1=0;
151 SCTAB nTab2=0;
152 bool bFirst = true;
153 for (SCTAB i=0; i< pDoc->GetTableCount(); i++)
154 if (pDoc->HasTable(i))
156 if (bFirst)
157 nTab1 = i;
158 nTab2 = i;
159 bFirst = false;
161 OSL_ENSURE(!bFirst, "no sheet selected");
163 // only limit to used cells if whole sheet was marked
164 // (so empty cell areas can be copied)
165 if ( nCol2>=MAXCOL && nRow2>=MAXROW )
167 SCROW nMaxRow;
168 SCCOL nMaxCol;
169 GetAreaSize( pDoc, nTab1, nTab2, nMaxRow, nMaxCol );
170 if( nMaxRow < nRow2 )
171 nRow2 = nMaxRow;
172 if( nMaxCol < nCol2 )
173 nCol2 = nMaxCol;
176 aBlock = ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
177 nVisibleTab = nTab1; // valid table as default
179 Rectangle aMMRect = pDoc->GetMMRect( nCol1,nRow1, nCol2,nRow2, nTab1 );
180 aObjDesc.maSize = aMMRect.GetSize();
181 PrepareOLE( aObjDesc );
184 ScTransferObj::~ScTransferObj()
186 SolarMutexGuard aSolarGuard;
188 ScModule* pScMod = SC_MOD();
189 if ( pScMod->GetClipData().pCellClipboard == this )
191 OSL_FAIL("ScTransferObj wasn't released");
192 pScMod->SetClipObject( NULL, NULL );
194 if ( pScMod->GetDragData().pCellTransfer == this )
196 OSL_FAIL("ScTransferObj wasn't released");
197 pScMod->ResetDragObject();
200 delete pDoc; // ScTransferObj is owner of clipboard document
202 aDocShellRef.Clear(); // before releasing the mutex
204 aDrawPersistRef.Clear(); // after the model
208 ScTransferObj* ScTransferObj::GetOwnClipboard( Window* pUIWin )
210 ScTransferObj* pObj = SC_MOD()->GetClipData().pCellClipboard;
211 if ( pObj && pUIWin )
213 // check formats to see if pObj is really in the system clipboard
215 // pUIWin is NULL when called from core (IsClipboardSource),
216 // in that case don't access the system clipboard, because the call
217 // may be from other clipboard operations (like flushing, #86059#)
219 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pUIWin ) );
220 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_DIF ) )
222 // OSL_FAIL("ScTransferObj wasn't released");
223 pObj = NULL;
226 return pObj;
229 void ScTransferObj::AddSupportedFormats()
231 AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
232 AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
233 AddFormat( SOT_FORMAT_GDIMETAFILE );
234 AddFormat( SOT_FORMAT_BITMAP );
236 // ScImportExport formats
237 AddFormat( SOT_FORMATSTR_ID_HTML );
238 AddFormat( SOT_FORMATSTR_ID_SYLK );
239 AddFormat( SOT_FORMATSTR_ID_LINK );
240 AddFormat( SOT_FORMATSTR_ID_DIF );
241 AddFormat( SOT_FORMAT_STRING );
243 AddFormat( SOT_FORMAT_RTF );
244 if ( aBlock.aStart == aBlock.aEnd )
245 AddFormat( SOT_FORMATSTR_ID_EDITENGINE );
248 sal_Bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor )
250 sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
251 bool bOK = false;
253 if( HasFormat( nFormat ) )
255 if ( nFormat == SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR || nFormat == SOT_FORMATSTR_ID_OBJECTDESCRIPTOR )
257 bOK = SetTransferableObjectDescriptor( aObjDesc, rFlavor );
259 else if ( ( nFormat == SOT_FORMAT_RTF || nFormat == SOT_FORMATSTR_ID_EDITENGINE ) &&
260 aBlock.aStart == aBlock.aEnd )
262 // RTF from a single cell is handled by EditEngine
264 SCCOL nCol = aBlock.aStart.Col();
265 SCROW nRow = aBlock.aStart.Row();
266 SCTAB nTab = aBlock.aStart.Tab();
267 ScAddress aPos(nCol, nRow, nTab);
269 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
270 ScTabEditEngine aEngine( *pPattern, pDoc->GetEditPool() );
271 if (pDoc->GetCellType(aPos) == CELLTYPE_EDIT)
273 const EditTextObject* pObj = pDoc->GetEditText(aPos);
274 if (pObj)
275 aEngine.SetText(*pObj);
277 else
279 OUString aText = pDoc->GetString(nCol, nRow, nTab);
280 if (!aText.isEmpty())
281 aEngine.SetText(aText);
284 bOK = SetObject( &aEngine,
285 (nFormat == FORMAT_RTF) ? SCTRANS_TYPE_EDIT_RTF : SCTRANS_TYPE_EDIT_BIN,
286 rFlavor );
288 else if ( ScImportExport::IsFormatSupported( nFormat ) || nFormat == SOT_FORMAT_RTF )
290 // if this transfer object was used to create a DDE link, filtered rows
291 // have to be included for subsequent calls (to be consistent with link data)
292 if ( nFormat == SOT_FORMATSTR_ID_LINK )
293 bUsedForLink = true;
295 bool bIncludeFiltered = pDoc->IsCutMode() || bUsedForLink;
297 ScRange aReducedBlock = aBlock;
298 if ( nFormat == SOT_FORMATSTR_ID_HTML && (aBlock.aEnd.Col() == MAXCOL || aBlock.aEnd.Row() == MAXROW) && aBlock.aStart.Tab() == aBlock.aEnd.Tab() )
300 bool bShrunk = false;
301 //shrink the area to allow pasting to external applications
302 SCCOL aStartCol = aReducedBlock.aStart.Col();
303 SCROW aStartRow = aReducedBlock.aStart.Row();
304 SCCOL aEndCol = aReducedBlock.aEnd.Col();
305 SCROW aEndRow = aReducedBlock.aEnd.Row();
306 pDoc->ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), aStartCol, aStartRow, aEndCol, aEndRow, false);
307 aReducedBlock = ScRange(aStartCol, aStartRow, aReducedBlock.aStart.Tab(), aEndCol, aEndRow, aReducedBlock.aEnd.Tab());
310 ScImportExport aObj( pDoc, aReducedBlock );
311 ScExportTextOptions aTextOptions(ScExportTextOptions::None, 0, true);
312 if ( bUsedForLink )
314 // For a DDE link, convert line breaks and separators to space.
315 aTextOptions.meNewlineConversion = ScExportTextOptions::ToSpace;
316 aTextOptions.mcSeparatorConvertTo = ' ';
317 aTextOptions.mbAddQuotes = false;
319 aObj.SetExportTextOptions(aTextOptions);
320 aObj.SetFormulas( pDoc->GetViewOptions().GetOption( VOPT_FORMULAS ) );
321 aObj.SetIncludeFiltered( bIncludeFiltered );
323 // DataType depends on format type:
325 if ( rFlavor.DataType.equals( ::getCppuType( (const OUString*) 0 ) ) )
327 OUString aString;
328 if ( aObj.ExportString( aString, nFormat ) )
329 bOK = SetString( aString, rFlavor );
331 else if ( rFlavor.DataType.equals( ::getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ) )
333 // SetObject converts a stream into a Int8-Sequence
334 bOK = SetObject( &aObj, SCTRANS_TYPE_IMPEX, rFlavor );
336 else
338 OSL_FAIL("unknown DataType");
341 else if ( nFormat == SOT_FORMAT_BITMAP )
343 Rectangle aMMRect = pDoc->GetMMRect( aBlock.aStart.Col(), aBlock.aStart.Row(),
344 aBlock.aEnd.Col(), aBlock.aEnd.Row(),
345 aBlock.aStart.Tab() );
346 VirtualDevice aVirtDev;
347 aVirtDev.SetOutputSizePixel( aVirtDev.LogicToPixel( aMMRect.GetSize(), MAP_100TH_MM ) );
349 PaintToDev( &aVirtDev, pDoc, 1.0, aBlock, false );
351 aVirtDev.SetMapMode( MapMode( MAP_PIXEL ) );
352 Bitmap aBmp = aVirtDev.GetBitmap( Point(), aVirtDev.GetOutputSize() );
353 bOK = SetBitmapEx( aBmp, rFlavor );
355 else if ( nFormat == SOT_FORMAT_GDIMETAFILE )
357 // #i123405# Do not limit visual size calculation for metafile creation.
358 // It seems unlikely that removing the limitation causes problems since
359 // metafile creation means that no real pixel device in the needed size is
360 // created.
361 InitDocShell(false);
363 SfxObjectShell* pEmbObj = aDocShellRef;
365 // like SvEmbeddedTransfer::GetData:
366 GDIMetaFile aMtf;
367 VirtualDevice aVDev;
368 MapMode aMapMode( pEmbObj->GetMapUnit() );
369 Rectangle aVisArea( pEmbObj->GetVisArea( ASPECT_CONTENT ) );
371 aVDev.EnableOutput( false );
372 aVDev.SetMapMode( aMapMode );
373 aMtf.SetPrefSize( aVisArea.GetSize() );
374 aMtf.SetPrefMapMode( aMapMode );
375 aMtf.Record( &aVDev );
377 pEmbObj->DoDraw( &aVDev, Point(), aVisArea.GetSize(), JobSetup(), ASPECT_CONTENT );
379 aMtf.Stop();
380 aMtf.WindStart();
382 bOK = SetGDIMetaFile( aMtf, rFlavor );
384 else if ( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE )
386 //TODO/LATER: differentiate between formats?!
387 // #i123405# Do limit visual size calculation to PageSize
388 InitDocShell(true); // set aDocShellRef
390 SfxObjectShell* pEmbObj = aDocShellRef;
391 bOK = SetObject( pEmbObj, SCTRANS_TYPE_EMBOBJ, rFlavor );
394 return bOK;
397 sal_Bool ScTransferObj::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId,
398 const datatransfer::DataFlavor& rFlavor )
400 // called from SetObject, put data into stream
402 bool bRet = false;
403 switch (nUserObjectId)
405 case SCTRANS_TYPE_IMPEX:
407 ScImportExport* pImpEx = (ScImportExport*)pUserObject;
409 sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
410 // mba: no BaseURL for data exchange
411 if ( pImpEx->ExportStream( *rxOStm, OUString(), nFormat ) )
412 bRet = ( rxOStm->GetError() == ERRCODE_NONE );
414 break;
416 case SCTRANS_TYPE_EDIT_RTF:
417 case SCTRANS_TYPE_EDIT_BIN:
419 ScTabEditEngine* pEngine = (ScTabEditEngine*)pUserObject;
420 if ( nUserObjectId == SCTRANS_TYPE_EDIT_RTF )
422 pEngine->Write( *rxOStm, EE_FORMAT_RTF );
423 bRet = ( rxOStm->GetError() == ERRCODE_NONE );
425 else
427 // can't use Write for EditEngine format because that would
428 // write old format without support for unicode characters.
429 // Get the data from the EditEngine's transferable instead.
431 sal_Int32 nParCnt = pEngine->GetParagraphCount();
432 if ( nParCnt == 0 )
433 nParCnt = 1;
434 ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) );
436 uno::Reference<datatransfer::XTransferable> xEditTrans = pEngine->CreateTransferable( aSel );
437 TransferableDataHelper aEditHelper( xEditTrans );
439 bRet = aEditHelper.GetSotStorageStream( rFlavor, rxOStm );
442 break;
444 case SCTRANS_TYPE_EMBOBJ:
446 // TODO/MBA: testing
447 SfxObjectShell* pEmbObj = (SfxObjectShell*) pUserObject;
448 ::utl::TempFile aTempFile;
449 aTempFile.EnableKillingFile();
450 uno::Reference< embed::XStorage > xWorkStore =
451 ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
453 // write document storage
454 pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false, false );
456 // mba: no relative ULRs for clipboard!
457 SfxMedium aMedium( xWorkStore, OUString() );
458 bRet = pEmbObj->DoSaveObjectAs( aMedium, false );
459 pEmbObj->DoSaveCompleted();
461 uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
462 if ( xTransact.is() )
463 xTransact->commit();
465 SvStream* pSrcStm = ::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), STREAM_READ );
466 if( pSrcStm )
468 rxOStm->SetBufferSize( 0xff00 );
469 *rxOStm << *pSrcStm;
470 delete pSrcStm;
473 bRet = true;
475 xWorkStore->dispose();
476 xWorkStore = uno::Reference < embed::XStorage >();
477 rxOStm->Commit();
479 break;
481 default:
482 OSL_FAIL("unknown object id");
484 return bRet;
487 void ScTransferObj::ObjectReleased()
489 ScModule* pScMod = SC_MOD();
490 if ( pScMod->GetClipData().pCellClipboard == this )
491 pScMod->SetClipObject( NULL, NULL );
493 TransferableHelper::ObjectReleased();
496 void ScTransferObj::DragFinished( sal_Int8 nDropAction )
498 if ( nDropAction == DND_ACTION_MOVE && !bDragWasInternal && !(nDragSourceFlags & SC_DROP_NAVIGATOR) )
500 // move: delete source data
501 ScDocShell* pSourceSh = GetSourceDocShell();
502 if (pSourceSh)
504 ScMarkData aMarkData = GetSourceMarkData();
505 // external drag&drop doesn't copy objects, so they also aren't deleted:
506 // bApi=TRUE, don't show error messages from drag&drop
507 pSourceSh->GetDocFunc().DeleteContents( aMarkData, IDF_ALL & ~IDF_OBJECTS, true, true );
511 ScModule* pScMod = SC_MOD();
512 if ( pScMod->GetDragData().pCellTransfer == this )
513 pScMod->ResetDragObject();
515 xDragSourceRanges = NULL; // don't keep source after dropping
517 TransferableHelper::DragFinished( nDropAction );
520 void ScTransferObj::SetDragHandlePos( SCCOL nX, SCROW nY )
522 nDragHandleX = nX;
523 nDragHandleY = nY;
526 void ScTransferObj::SetVisibleTab( SCTAB nNew )
528 nVisibleTab = nNew;
531 void ScTransferObj::SetDrawPersist( const SfxObjectShellRef& rRef )
533 aDrawPersistRef = rRef;
536 void ScTransferObj::SetDragSource( ScDocShell* pSourceShell, const ScMarkData& rMark )
538 ScRangeList aRanges;
539 rMark.FillRangeListWithMarks( &aRanges, false );
540 xDragSourceRanges = new ScCellRangesObj( pSourceShell, aRanges );
543 void ScTransferObj::SetDragSourceFlags( sal_uInt16 nFlags )
545 nDragSourceFlags = nFlags;
548 void ScTransferObj::SetDragWasInternal()
550 bDragWasInternal = true;
553 void ScTransferObj::SetUseInApi( bool bSet )
555 bUseInApi = bSet;
558 ScDocument* ScTransferObj::GetSourceDocument()
560 ScDocShell* pSourceDocSh = GetSourceDocShell();
561 if (pSourceDocSh)
562 return pSourceDocSh->GetDocument();
563 return NULL;
566 ScDocShell* ScTransferObj::GetSourceDocShell()
568 ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
569 if (pRangesObj)
570 return pRangesObj->GetDocShell();
572 return NULL; // none set
575 ScMarkData ScTransferObj::GetSourceMarkData()
577 ScMarkData aMarkData;
578 ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
579 if (pRangesObj)
581 const ScRangeList& rRanges = pRangesObj->GetRangeList();
582 aMarkData.MarkFromRangeList( rRanges, false );
584 return aMarkData;
588 // initialize aDocShellRef with a live document from the ClipDoc
590 // #i123405# added parameter to allow size calculation without limitation
591 // to PageSize, e.g. used for Metafile creation for clipboard.
593 void ScTransferObj::InitDocShell(bool bLimitToPageSize)
595 if ( !aDocShellRef.Is() )
597 ScDocShell* pDocSh = new ScDocShell;
598 aDocShellRef = pDocSh; // ref must be there before InitNew
600 pDocSh->DoInitNew(NULL);
602 ScDocument* pDestDoc = pDocSh->GetDocument();
603 ScMarkData aDestMark;
604 aDestMark.SelectTable( 0, true );
606 pDestDoc->SetDocOptions( pDoc->GetDocOptions() ); // #i42666#
608 OUString aTabName;
609 pDoc->GetName( aBlock.aStart.Tab(), aTabName );
610 pDestDoc->RenameTab( 0, aTabName, false ); // no UpdateRef (empty)
612 pDestDoc->CopyStdStylesFrom( pDoc );
614 SCCOL nStartX = aBlock.aStart.Col();
615 SCROW nStartY = aBlock.aStart.Row();
616 SCCOL nEndX = aBlock.aEnd.Col();
617 SCROW nEndY = aBlock.aEnd.Row();
619 // widths / heights
620 // (must be copied before CopyFromClip, for drawing objects)
622 SCCOL nCol;
623 SCTAB nSrcTab = aBlock.aStart.Tab();
624 pDestDoc->SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab));
625 for (nCol=nStartX; nCol<=nEndX; nCol++)
626 if ( pDoc->ColHidden(nCol, nSrcTab) )
627 pDestDoc->ShowCol( nCol, 0, false );
628 else
629 pDestDoc->SetColWidth( nCol, 0, pDoc->GetColWidth( nCol, nSrcTab ) );
631 for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow)
633 if ( pDoc->RowHidden(nRow, nSrcTab) )
634 pDestDoc->ShowRow( nRow, 0, false );
635 else
637 pDestDoc->SetRowHeight( nRow, 0, pDoc->GetOriginalHeight( nRow, nSrcTab ) );
639 // if height was set manually, that flag has to be copied, too
640 bool bManual = pDoc->IsManualRowHeight(nRow, nSrcTab);
641 pDestDoc->SetManualHeight(nRow, nRow, 0, bManual);
645 if ( pDoc->GetDrawLayer() )
646 pDocSh->MakeDrawLayer();
648 // cell range is copied to the original position, but on the first sheet
649 // -> bCutMode must be set
650 // pDoc is always a Clipboard-document
652 ScRange aDestRange( nStartX,nStartY,0, nEndX,nEndY,0 );
653 bool bWasCut = pDoc->IsCutMode();
654 if (!bWasCut)
655 pDoc->SetClipArea( aDestRange, true ); // Cut
656 pDestDoc->CopyFromClip( aDestRange, aDestMark, IDF_ALL, NULL, pDoc, false );
657 pDoc->SetClipArea( aDestRange, bWasCut );
659 StripRefs( pDoc, nStartX,nStartY, nEndX,nEndY, pDestDoc, 0,0 );
661 ScRange aMergeRange = aDestRange;
662 pDestDoc->ExtendMerge( aMergeRange, true );
664 pDoc->CopyDdeLinks( pDestDoc ); // copy values of DDE Links
666 // page format (grid etc) and page size (maximum size for ole object)
668 Size aPaperSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); // Twips
669 ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
670 OUString aStyleName = pDoc->GetPageStyle( aBlock.aStart.Tab() );
671 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
672 if (pStyleSheet)
674 const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
675 aPaperSize = ((const SvxSizeItem&) rSourceSet.Get(ATTR_PAGE_SIZE)).GetSize();
677 // CopyStyleFrom kopiert SetItems mit richtigem Pool
678 ScStyleSheetPool* pDestPool = pDestDoc->GetStyleSheetPool();
679 pDestPool->CopyStyleFrom( pStylePool, aStyleName, SFX_STYLE_FAMILY_PAGE );
682 ScViewData aViewData( pDocSh, NULL );
683 aViewData.SetScreen( nStartX,nStartY, nEndX,nEndY );
684 aViewData.SetCurX( nStartX );
685 aViewData.SetCurY( nStartY );
687 pDestDoc->SetViewOptions( pDoc->GetViewOptions() );
689 // Size
690 //! get while copying sizes
692 long nPosX = 0;
693 long nPosY = 0;
695 for (nCol=0; nCol<nStartX; nCol++)
696 nPosX += pDestDoc->GetColWidth( nCol, 0 );
697 nPosY += pDestDoc->GetRowHeight( 0, nStartY-1, 0 );
698 nPosX = (long) ( nPosX * HMM_PER_TWIPS );
699 nPosY = (long) ( nPosY * HMM_PER_TWIPS );
702 aPaperSize.Width() *= 2; // limit OLE object to double of page size
703 aPaperSize.Height() *= 2;
705 long nSizeX = 0;
706 long nSizeY = 0;
707 for (nCol=nStartX; nCol<=nEndX; nCol++)
709 long nAdd = pDestDoc->GetColWidth( nCol, 0 );
710 if ( bLimitToPageSize && nSizeX+nAdd > aPaperSize.Width() && nSizeX ) // above limit?
711 break;
712 nSizeX += nAdd;
714 for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
716 long nAdd = pDestDoc->GetRowHeight( nRow, 0 );
717 if ( bLimitToPageSize && nSizeY+nAdd > aPaperSize.Height() && nSizeY ) // above limit?
718 break;
719 nSizeY += nAdd;
721 nSizeX = (long) ( nSizeX * HMM_PER_TWIPS );
722 nSizeY = (long) ( nSizeY * HMM_PER_TWIPS );
724 // pDocSh->SetVisAreaSize( Size(nSizeX,nSizeY) );
726 Rectangle aNewArea( Point(nPosX,nPosY), Size(nSizeX,nSizeY) );
727 //TODO/LATER: why twice?!
728 //pDocSh->SvInPlaceObject::SetVisArea( aNewArea );
729 pDocSh->SetVisArea( aNewArea );
731 pDocSh->UpdateOle(&aViewData, true);
733 //! SetDocumentModified?
734 if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() )
735 pDestDoc->UpdateChartListenerCollection();
739 SfxObjectShell* ScTransferObj::SetDrawClipDoc( sal_Bool bAnyOle )
741 // update ScGlobal::pDrawClipDocShellRef
743 delete ScGlobal::pDrawClipDocShellRef;
744 if (bAnyOle)
746 ScGlobal::pDrawClipDocShellRef =
747 new ScDocShellRef(new ScDocShell(SFX_CREATE_MODE_INTERNAL)); // there must be a ref
748 (*ScGlobal::pDrawClipDocShellRef)->DoInitNew(NULL);
749 return *ScGlobal::pDrawClipDocShellRef;
751 else
753 ScGlobal::pDrawClipDocShellRef = NULL;
754 return NULL;
758 void ScTransferObj::StripRefs( ScDocument* pDoc,
759 SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
760 ScDocument* pDestDoc, SCCOL nSubX, SCROW nSubY )
762 if (!pDestDoc)
764 pDestDoc = pDoc;
765 OSL_ENSURE(nSubX==0&&nSubY==0, "can't move within the document");
768 // In a clipboard doc the data don't have to be on the first sheet
770 SCTAB nSrcTab = 0;
771 while (nSrcTab<pDoc->GetTableCount() && !pDoc->HasTable(nSrcTab))
772 ++nSrcTab;
773 SCTAB nDestTab = 0;
774 while (nDestTab<pDestDoc->GetTableCount() && !pDestDoc->HasTable(nDestTab))
775 ++nDestTab;
777 if (!pDoc->HasTable(nSrcTab) || !pDestDoc->HasTable(nDestTab))
779 OSL_FAIL("Sheet not found in ScTransferObj::StripRefs");
780 return;
783 ScRange aRef;
785 ScCellIterator aIter( pDoc, ScRange(nStartX, nStartY, nSrcTab, nEndX, nEndY, nSrcTab) );
786 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
788 if (aIter.getType() != CELLTYPE_FORMULA)
789 continue;
791 ScFormulaCell* pFCell = aIter.getFormulaCell();
792 bool bOut = false;
793 ScDetectiveRefIter aRefIter( pFCell );
794 while ( !bOut && aRefIter.GetNextRef( aRef ) )
796 if ( aRef.aStart.Tab() != nSrcTab || aRef.aEnd.Tab() != nSrcTab ||
797 aRef.aStart.Col() < nStartX || aRef.aEnd.Col() > nEndX ||
798 aRef.aStart.Row() < nStartY || aRef.aEnd.Row() > nEndY )
799 bOut = true;
801 if (bOut)
803 SCCOL nCol = aIter.GetPos().Col() - nSubX;
804 SCROW nRow = aIter.GetPos().Row() - nSubY;
806 sal_uInt16 nErrCode = pFCell->GetErrCode();
807 ScAddress aPos(nCol, nRow, nDestTab);
808 if (nErrCode)
810 if ( ((const SvxHorJustifyItem*) pDestDoc->GetAttr(
811 nCol,nRow,nDestTab, ATTR_HOR_JUSTIFY))->GetValue() ==
812 SVX_HOR_JUSTIFY_STANDARD )
813 pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
814 SvxHorJustifyItem(SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY) );
816 ScSetStringParam aParam;
817 aParam.setTextInput();
818 pDestDoc->SetString(aPos, ScGlobal::GetErrorString(nErrCode), &aParam);
820 else if (pFCell->IsValue())
822 pDestDoc->SetValue(aPos, pFCell->GetValue());
824 else
826 OUString aStr = pFCell->GetString().getString();
827 if ( pFCell->IsMultilineResult() )
829 ScFieldEditEngine& rEngine = pDestDoc->GetEditEngine();
830 rEngine.SetText(aStr);
831 pDestDoc->SetEditText(ScAddress(nCol,nRow,nDestTab), rEngine.CreateTextObject());
833 else
835 ScSetStringParam aParam;
836 aParam.setTextInput();
837 pDestDoc->SetString(aPos, aStr, &aParam);
844 namespace
846 class theScTransferUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theScTransferUnoTunnelId> {};
849 const com::sun::star::uno::Sequence< sal_Int8 >& ScTransferObj::getUnoTunnelId()
851 return theScTransferUnoTunnelId::get().getSeq();
854 sal_Int64 SAL_CALL ScTransferObj::getSomething( const com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( com::sun::star::uno::RuntimeException )
856 sal_Int64 nRet;
857 if( ( rId.getLength() == 16 ) &&
858 ( 0 == memcmp( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
860 nRet = reinterpret_cast< sal_Int64 >( this );
862 else
863 nRet = TransferableHelper::getSomething(rId);
864 return nRet;
868 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */