Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / source / ui / app / transobj.cxx
blob802533f05e11531a282cee4f60227e1dfb61c386
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>
24 #include <com/sun/star/uno/Sequence.hxx>
25 #include <com/sun/star/embed/XTransactedObject.hpp>
27 #include <unotools/tempfile.hxx>
28 #include <unotools/ucbstreamhelper.hxx>
29 #include <comphelper/storagehelper.hxx>
30 #include <comphelper/servicehelper.hxx>
31 #include <sot/storage.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/virdev.hxx>
34 #include <osl/mutex.hxx>
35 #include <sfx2/app.hxx>
36 #include <sfx2/docfile.hxx>
38 #include "transobj.hxx"
39 #include "patattr.hxx"
40 #include "cellvalue.hxx"
41 #include "cellform.hxx"
42 #include "document.hxx"
43 #include "viewopti.hxx"
44 #include "editutil.hxx"
45 #include "impex.hxx"
46 #include "formulacell.hxx"
47 #include "printfun.hxx"
48 #include "docfunc.hxx"
49 #include "scmod.hxx"
50 #include "dragdata.hxx"
51 #include "clipdata.hxx"
52 #include "clipparam.hxx"
54 #include <editeng/paperinf.hxx>
55 #include <editeng/sizeitem.hxx>
56 #include <svx/algitem.hxx>
57 #include <svl/intitem.hxx>
58 #include <svl/zforlist.hxx>
59 #include "docsh.hxx"
60 #include "markdata.hxx"
61 #include "stlpool.hxx"
62 #include "viewdata.hxx"
63 #include "dociter.hxx"
64 #include "cellsuno.hxx"
65 #include "stringutil.hxx"
66 #include "formulaiter.hxx"
67 #include <gridwin.hxx>
69 using namespace com::sun::star;
71 #define SCTRANS_TYPE_IMPEX SotClipboardFormatId::STRING
72 #define SCTRANS_TYPE_EDIT_RTF SotClipboardFormatId::BITMAP
73 #define SCTRANS_TYPE_EDIT_BIN SotClipboardFormatId::GDIMETAFILE
74 #define SCTRANS_TYPE_EMBOBJ SotClipboardFormatId::PRIVATE
76 void ScTransferObj::GetAreaSize( ScDocument* pDoc, SCTAB nTab1, SCTAB nTab2, SCROW& nRow, SCCOL& nCol )
78 SCCOL nMaxCol = 0;
79 SCROW nMaxRow = 0;
80 for( SCTAB nTab = nTab1; nTab <= nTab2; nTab++ )
82 SCCOL nLastCol = 0;
83 SCROW nLastRow = 0;
84 // GetPrintArea instead of GetCellArea - include drawing objects
85 if( pDoc->GetPrintArea( nTab, nLastCol, nLastRow ) )
87 if( nLastCol > nMaxCol )
88 nMaxCol = nLastCol;
89 if( nLastRow > nMaxRow )
90 nMaxRow = nLastRow;
93 nRow = nMaxRow;
94 nCol = nMaxCol;
97 void ScTransferObj::PaintToDev( OutputDevice* pDev, ScDocument* pDoc, double nPrintFactor,
98 const ScRange& rBlock, bool bMetaFile )
100 if (!pDoc)
101 return;
103 Point aPoint;
104 Rectangle aBound( aPoint, pDev->GetOutputSize() ); //! use size from clip area?
106 ScViewData aViewData(nullptr,nullptr);
107 aViewData.InitData( pDoc );
109 aViewData.SetTabNo( rBlock.aEnd.Tab() );
110 aViewData.SetScreen( rBlock.aStart.Col(), rBlock.aStart.Row(),
111 rBlock.aEnd.Col(), rBlock.aEnd.Row() );
113 ScPrintFunc::DrawToDev( pDoc, pDev, nPrintFactor, aBound, &aViewData, bMetaFile );
116 ScTransferObj::ScTransferObj( ScDocument* pClipDoc, const TransferableObjectDescriptor& rDesc ) :
117 pDoc( pClipDoc ),
118 nNonFiltered(0),
119 aObjDesc( rDesc ),
120 nDragHandleX( 0 ),
121 nDragHandleY( 0 ),
122 nSourceCursorX( MAXCOL + 1 ),
123 nSourceCursorY( MAXROW + 1 ),
124 nDragSourceFlags( 0 ),
125 bDragWasInternal( false ),
126 bUsedForLink( false ),
127 bUseInApi( false )
129 OSL_ENSURE(pDoc->IsClipboard(), "wrong document");
131 // get aBlock from clipboard doc
133 SCCOL nCol1;
134 SCROW nRow1;
135 SCCOL nCol2;
136 SCROW nRow2;
137 pDoc->GetClipStart( nCol1, nRow1 );
138 pDoc->GetClipArea( nCol2, nRow2, true ); // real source area - include filtered rows
139 nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nCol1 );
140 nRow2 = sal::static_int_cast<SCROW>( nRow2 + nRow1 );
142 SCCOL nDummy;
143 pDoc->GetClipArea( nDummy, nNonFiltered, false );
144 bHasFiltered = (nNonFiltered < (nRow2 - nRow1));
145 ++nNonFiltered; // to get count instead of diff
147 SCTAB nTab1=0;
148 SCTAB nTab2=0;
149 bool bFirst = true;
150 for (SCTAB i=0; i< pDoc->GetTableCount(); i++)
151 if (pDoc->HasTable(i))
153 if (bFirst)
154 nTab1 = i;
155 nTab2 = i;
156 bFirst = false;
158 OSL_ENSURE(!bFirst, "no sheet selected");
160 // only limit to used cells if whole sheet was marked
161 // (so empty cell areas can be copied)
162 if ( nCol2>=MAXCOL && nRow2>=MAXROW )
164 SCROW nMaxRow;
165 SCCOL nMaxCol;
166 GetAreaSize( pDoc, nTab1, nTab2, nMaxRow, nMaxCol );
167 if( nMaxRow < nRow2 )
168 nRow2 = nMaxRow;
169 if( nMaxCol < nCol2 )
170 nCol2 = nMaxCol;
173 aBlock = ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
174 nVisibleTab = nTab1; // valid table as default
176 Rectangle aMMRect = pDoc->GetMMRect( nCol1,nRow1, nCol2,nRow2, nTab1 );
177 aObjDesc.maSize = aMMRect.GetSize();
178 PrepareOLE( aObjDesc );
181 ScTransferObj::~ScTransferObj()
183 SolarMutexGuard aSolarGuard;
185 ScModule* pScMod = SC_MOD();
186 if ( pScMod->GetClipData().pCellClipboard == this )
188 OSL_FAIL("ScTransferObj wasn't released");
189 pScMod->SetClipObject( nullptr, nullptr );
191 if ( pScMod->GetDragData().pCellTransfer == this )
193 OSL_FAIL("ScTransferObj wasn't released");
194 pScMod->ResetDragObject();
197 delete pDoc; // ScTransferObj is owner of clipboard document
199 aDocShellRef.Clear(); // before releasing the mutex
201 aDrawPersistRef.Clear(); // after the model
205 ScTransferObj* ScTransferObj::GetOwnClipboard( vcl::Window* pUIWin )
207 ScTransferObj* pObj = SC_MOD()->GetClipData().pCellClipboard;
208 if ( pObj && pUIWin )
210 // check formats to see if pObj is really in the system clipboard
212 // pUIWin is NULL when called from core (IsClipboardSource),
213 // in that case don't access the system clipboard, because the call
214 // may be from other clipboard operations (like flushing, #86059#)
216 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pUIWin ) );
217 if ( !aDataHelper.HasFormat( SotClipboardFormatId::DIF ) )
219 // OSL_FAIL("ScTransferObj wasn't released");
220 pObj = nullptr;
223 return pObj;
226 void ScTransferObj::AddSupportedFormats()
228 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
229 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
230 AddFormat( SotClipboardFormatId::GDIMETAFILE );
231 AddFormat( SotClipboardFormatId::PNG );
232 AddFormat( SotClipboardFormatId::BITMAP );
234 // ScImportExport formats
235 AddFormat( SotClipboardFormatId::HTML );
236 AddFormat( SotClipboardFormatId::SYLK );
237 AddFormat( SotClipboardFormatId::LINK );
238 AddFormat( SotClipboardFormatId::DIF );
239 AddFormat( SotClipboardFormatId::STRING );
241 AddFormat( SotClipboardFormatId::RTF );
242 if ( aBlock.aStart == aBlock.aEnd )
243 AddFormat( SotClipboardFormatId::EDITENGINE );
246 bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
248 SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
249 bool bOK = false;
251 if( HasFormat( nFormat ) )
253 if ( nFormat == SotClipboardFormatId::LINKSRCDESCRIPTOR || nFormat == SotClipboardFormatId::OBJECTDESCRIPTOR )
255 bOK = SetTransferableObjectDescriptor( aObjDesc, rFlavor );
257 else if ( ( nFormat == SotClipboardFormatId::RTF || nFormat == SotClipboardFormatId::EDITENGINE ) &&
258 aBlock.aStart == aBlock.aEnd )
260 // RTF from a single cell is handled by EditEngine
262 SCCOL nCol = aBlock.aStart.Col();
263 SCROW nRow = aBlock.aStart.Row();
264 SCTAB nTab = aBlock.aStart.Tab();
265 ScAddress aPos(nCol, nRow, nTab);
267 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
268 ScTabEditEngine aEngine( *pPattern, pDoc->GetEditPool() );
269 ScRefCellValue aCell(*pDoc, aPos);
270 if (aCell.meType == CELLTYPE_EDIT)
272 const EditTextObject* pObj = aCell.mpEditText;
273 aEngine.SetText(*pObj);
275 else
277 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
278 sal_uLong nNumFmt = pPattern->GetNumberFormat(pFormatter);
279 OUString aText;
280 Color* pColor;
281 ScCellFormat::GetString(aCell, nNumFmt, aText, &pColor, *pFormatter, pDoc);
282 if (!aText.isEmpty())
283 aEngine.SetText(aText);
286 bOK = SetObject( &aEngine,
287 (nFormat == SotClipboardFormatId::RTF) ? SCTRANS_TYPE_EDIT_RTF : SCTRANS_TYPE_EDIT_BIN,
288 rFlavor );
290 else if ( ScImportExport::IsFormatSupported( nFormat ) || nFormat == SotClipboardFormatId::RTF )
292 // if this transfer object was used to create a DDE link, filtered rows
293 // have to be included for subsequent calls (to be consistent with link data)
294 if ( nFormat == SotClipboardFormatId::LINK )
295 bUsedForLink = true;
297 bool bIncludeFiltered = pDoc->IsCutMode() || bUsedForLink;
299 bool bReduceBlockFormat = nFormat == SotClipboardFormatId::HTML || nFormat == SotClipboardFormatId::RTF;
300 ScRange aReducedBlock = aBlock;
301 if (bReduceBlockFormat && (aBlock.aEnd.Col() == MAXCOL || aBlock.aEnd.Row() == MAXROW) && aBlock.aStart.Tab() == aBlock.aEnd.Tab())
303 bool bShrunk = false;
304 //shrink the area to allow pasting to external applications
305 SCCOL aStartCol = aReducedBlock.aStart.Col();
306 SCROW aStartRow = aReducedBlock.aStart.Row();
307 SCCOL aEndCol = aReducedBlock.aEnd.Col();
308 SCROW aEndRow = aReducedBlock.aEnd.Row();
309 pDoc->ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), aStartCol, aStartRow, aEndCol, aEndRow, false);
310 aReducedBlock = ScRange(aStartCol, aStartRow, aReducedBlock.aStart.Tab(), aEndCol, aEndRow, aReducedBlock.aEnd.Tab());
313 ScImportExport aObj( pDoc, aReducedBlock );
314 ScExportTextOptions aTextOptions(ScExportTextOptions::None, 0, true);
315 if ( bUsedForLink )
317 // For a DDE link, convert line breaks and separators to space.
318 aTextOptions.meNewlineConversion = ScExportTextOptions::ToSpace;
319 aTextOptions.mcSeparatorConvertTo = ' ';
320 aTextOptions.mbAddQuotes = false;
322 aObj.SetExportTextOptions(aTextOptions);
323 aObj.SetFormulas( pDoc->GetViewOptions().GetOption( VOPT_FORMULAS ) );
324 aObj.SetIncludeFiltered( bIncludeFiltered );
326 // DataType depends on format type:
328 if ( rFlavor.DataType.equals( ::cppu::UnoType<OUString>::get() ) )
330 OUString aString;
331 if ( aObj.ExportString( aString, nFormat ) )
332 bOK = SetString( aString, rFlavor );
334 else if ( rFlavor.DataType.equals( cppu::UnoType<uno::Sequence< sal_Int8 >>::get() ) )
336 // SetObject converts a stream into a Int8-Sequence
337 bOK = SetObject( &aObj, SCTRANS_TYPE_IMPEX, rFlavor );
339 else
341 OSL_FAIL("unknown DataType");
344 else if ( nFormat == SotClipboardFormatId::BITMAP || nFormat == SotClipboardFormatId::PNG )
346 Rectangle aMMRect = pDoc->GetMMRect( aBlock.aStart.Col(), aBlock.aStart.Row(),
347 aBlock.aEnd.Col(), aBlock.aEnd.Row(),
348 aBlock.aStart.Tab() );
349 ScopedVclPtrInstance< VirtualDevice > pVirtDev;
350 pVirtDev->SetOutputSizePixel( pVirtDev->LogicToPixel( aMMRect.GetSize(), MAP_100TH_MM ) );
352 PaintToDev( pVirtDev, pDoc, 1.0, aBlock, false );
354 pVirtDev->SetMapMode( MapMode( MAP_PIXEL ) );
355 Bitmap aBmp = pVirtDev->GetBitmap( Point(), pVirtDev->GetOutputSize() );
356 bOK = SetBitmapEx( aBmp, rFlavor );
358 else if ( nFormat == SotClipboardFormatId::GDIMETAFILE )
360 // #i123405# Do not limit visual size calculation for metafile creation.
361 // It seems unlikely that removing the limitation causes problems since
362 // metafile creation means that no real pixel device in the needed size is
363 // created.
364 InitDocShell(false);
366 SfxObjectShell* pEmbObj = aDocShellRef;
368 // like SvEmbeddedTransfer::GetData:
369 GDIMetaFile aMtf;
370 ScopedVclPtrInstance< VirtualDevice > pVDev;
371 MapMode aMapMode( pEmbObj->GetMapUnit() );
372 Rectangle aVisArea( pEmbObj->GetVisArea( ASPECT_CONTENT ) );
374 pVDev->EnableOutput( false );
375 pVDev->SetMapMode( aMapMode );
376 aMtf.SetPrefSize( aVisArea.GetSize() );
377 aMtf.SetPrefMapMode( aMapMode );
378 aMtf.Record( pVDev );
380 pEmbObj->DoDraw( pVDev, Point(), aVisArea.GetSize(), JobSetup() );
382 aMtf.Stop();
383 aMtf.WindStart();
385 bOK = SetGDIMetaFile( aMtf, rFlavor );
387 else if ( nFormat == SotClipboardFormatId::EMBED_SOURCE )
389 //TODO/LATER: differentiate between formats?!
390 // #i123405# Do limit visual size calculation to PageSize
391 InitDocShell(true); // set aDocShellRef
393 SfxObjectShell* pEmbObj = aDocShellRef;
394 bOK = SetObject( pEmbObj, SCTRANS_TYPE_EMBOBJ, rFlavor );
397 return bOK;
400 bool ScTransferObj::WriteObject( tools::SvRef<SotStorageStream>& rxOStm, void* pUserObject, SotClipboardFormatId nUserObjectId,
401 const datatransfer::DataFlavor& rFlavor )
403 // called from SetObject, put data into stream
405 bool bRet = false;
406 switch (nUserObjectId)
408 case SCTRANS_TYPE_IMPEX:
410 ScImportExport* pImpEx = static_cast<ScImportExport*>(pUserObject);
412 SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
413 // mba: no BaseURL for data exchange
414 if ( pImpEx->ExportStream( *rxOStm, OUString(), nFormat ) )
415 bRet = ( rxOStm->GetError() == ERRCODE_NONE );
417 break;
419 case SCTRANS_TYPE_EDIT_RTF:
420 case SCTRANS_TYPE_EDIT_BIN:
422 ScTabEditEngine* pEngine = static_cast<ScTabEditEngine*>(pUserObject);
423 if ( nUserObjectId == SCTRANS_TYPE_EDIT_RTF )
425 pEngine->Write( *rxOStm, EE_FORMAT_RTF );
426 bRet = ( rxOStm->GetError() == ERRCODE_NONE );
428 else
430 // can't use Write for EditEngine format because that would
431 // write old format without support for unicode characters.
432 // Get the data from the EditEngine's transferable instead.
434 sal_Int32 nParCnt = pEngine->GetParagraphCount();
435 if ( nParCnt == 0 )
436 nParCnt = 1;
437 ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) );
439 uno::Reference<datatransfer::XTransferable> xEditTrans = pEngine->CreateTransferable( aSel );
440 TransferableDataHelper aEditHelper( xEditTrans );
442 bRet = aEditHelper.GetSotStorageStream( rFlavor, rxOStm );
445 break;
447 case SCTRANS_TYPE_EMBOBJ:
449 // TODO/MBA: testing
450 SfxObjectShell* pEmbObj = static_cast<SfxObjectShell*>(pUserObject);
451 ::utl::TempFile aTempFile;
452 aTempFile.EnableKillingFile();
453 uno::Reference< embed::XStorage > xWorkStore =
454 ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
456 // write document storage
457 pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false );
459 // mba: no relative URLs for clipboard!
460 SfxMedium aMedium( xWorkStore, OUString() );
461 pEmbObj->DoSaveObjectAs( aMedium, false );
462 pEmbObj->DoSaveCompleted();
464 uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
465 if ( xTransact.is() )
466 xTransact->commit();
468 SvStream* pSrcStm = ::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), StreamMode::READ );
469 if( pSrcStm )
471 rxOStm->SetBufferSize( 0xff00 );
472 rxOStm->WriteStream( *pSrcStm );
473 delete pSrcStm;
476 bRet = true;
478 xWorkStore->dispose();
479 xWorkStore.clear();
480 rxOStm->Commit();
482 break;
484 default:
485 OSL_FAIL("unknown object id");
487 return bRet;
490 void ScTransferObj::ObjectReleased()
492 ScModule* pScMod = SC_MOD();
493 if ( pScMod->GetClipData().pCellClipboard == this )
494 pScMod->SetClipObject( nullptr, nullptr );
496 TransferableHelper::ObjectReleased();
499 void ScTransferObj::DragFinished( sal_Int8 nDropAction )
501 if ( nDropAction == DND_ACTION_MOVE && !bDragWasInternal && !(nDragSourceFlags & SC_DROP_NAVIGATOR) )
503 // move: delete source data
504 ScDocShell* pSourceSh = GetSourceDocShell();
505 if (pSourceSh)
507 ScMarkData aMarkData = GetSourceMarkData();
508 // external drag&drop doesn't copy objects, so they also aren't deleted:
509 // bApi=TRUE, don't show error messages from drag&drop
510 pSourceSh->GetDocFunc().DeleteContents( aMarkData, InsertDeleteFlags::ALL & ~InsertDeleteFlags::OBJECTS, true, true );
514 ScModule* pScMod = SC_MOD();
515 if ( pScMod->GetDragData().pCellTransfer == this )
516 pScMod->ResetDragObject();
518 xDragSourceRanges = nullptr; // don't keep source after dropping
520 TransferableHelper::DragFinished( nDropAction );
523 void ScTransferObj::SetDragHandlePos( SCCOL nX, SCROW nY )
525 nDragHandleX = nX;
526 nDragHandleY = nY;
529 void ScTransferObj::SetSourceCursorPos( SCCOL nX, SCROW nY )
531 nSourceCursorX = nX;
532 nSourceCursorY = nY;
535 bool ScTransferObj::WasSourceCursorInSelection() const
537 return
538 nSourceCursorX >= aBlock.aStart.Col() && nSourceCursorX <= aBlock.aEnd.Col() &&
539 nSourceCursorY >= aBlock.aStart.Row() && nSourceCursorY <= aBlock.aEnd.Row();
542 void ScTransferObj::SetVisibleTab( SCTAB nNew )
544 nVisibleTab = nNew;
547 void ScTransferObj::SetDrawPersist( const SfxObjectShellRef& rRef )
549 aDrawPersistRef = rRef;
552 void ScTransferObj::SetDragSource( ScDocShell* pSourceShell, const ScMarkData& rMark )
554 ScRangeList aRanges;
555 rMark.FillRangeListWithMarks( &aRanges, false );
556 xDragSourceRanges = new ScCellRangesObj( pSourceShell, aRanges );
559 void ScTransferObj::SetDragSourceFlags( sal_uInt16 nFlags )
561 nDragSourceFlags = nFlags;
564 void ScTransferObj::SetDragWasInternal()
566 bDragWasInternal = true;
569 void ScTransferObj::SetUseInApi( bool bSet )
571 bUseInApi = bSet;
574 ScDocument* ScTransferObj::GetSourceDocument()
576 ScDocShell* pSourceDocSh = GetSourceDocShell();
577 if (pSourceDocSh)
578 return &pSourceDocSh->GetDocument();
579 return nullptr;
582 ScDocShell* ScTransferObj::GetSourceDocShell()
584 ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
585 if (pRangesObj)
586 return pRangesObj->GetDocShell();
588 return nullptr; // none set
591 ScMarkData ScTransferObj::GetSourceMarkData()
593 ScMarkData aMarkData;
594 ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
595 if (pRangesObj)
597 const ScRangeList& rRanges = pRangesObj->GetRangeList();
598 aMarkData.MarkFromRangeList( rRanges, false );
600 return aMarkData;
603 // initialize aDocShellRef with a live document from the ClipDoc
605 // #i123405# added parameter to allow size calculation without limitation
606 // to PageSize, e.g. used for Metafile creation for clipboard.
608 void ScTransferObj::InitDocShell(bool bLimitToPageSize)
610 if ( !aDocShellRef.Is() )
612 ScDocShell* pDocSh = new ScDocShell;
613 aDocShellRef = pDocSh; // ref must be there before InitNew
615 pDocSh->DoInitNew();
617 ScDocument& rDestDoc = pDocSh->GetDocument();
618 ScMarkData aDestMark;
619 aDestMark.SelectTable( 0, true );
621 rDestDoc.SetDocOptions( pDoc->GetDocOptions() ); // #i42666#
623 OUString aTabName;
624 pDoc->GetName( aBlock.aStart.Tab(), aTabName );
625 rDestDoc.RenameTab( 0, aTabName, false ); // no UpdateRef (empty)
627 rDestDoc.CopyStdStylesFrom( pDoc );
629 SCCOL nStartX = aBlock.aStart.Col();
630 SCROW nStartY = aBlock.aStart.Row();
631 SCCOL nEndX = aBlock.aEnd.Col();
632 SCROW nEndY = aBlock.aEnd.Row();
634 // widths / heights
635 // (must be copied before CopyFromClip, for drawing objects)
637 SCCOL nCol;
638 SCTAB nSrcTab = aBlock.aStart.Tab();
639 rDestDoc.SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab));
640 for (nCol=nStartX; nCol<=nEndX; nCol++)
641 if ( pDoc->ColHidden(nCol, nSrcTab) )
642 rDestDoc.ShowCol( nCol, 0, false );
643 else
644 rDestDoc.SetColWidth( nCol, 0, pDoc->GetColWidth( nCol, nSrcTab ) );
646 for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow)
648 if ( pDoc->RowHidden(nRow, nSrcTab) )
649 rDestDoc.ShowRow( nRow, 0, false );
650 else
652 rDestDoc.SetRowHeight( nRow, 0, pDoc->GetOriginalHeight( nRow, nSrcTab ) );
654 // if height was set manually, that flag has to be copied, too
655 bool bManual = pDoc->IsManualRowHeight(nRow, nSrcTab);
656 rDestDoc.SetManualHeight(nRow, nRow, 0, bManual);
660 if (pDoc->GetDrawLayer() || pDoc->HasNotes())
661 pDocSh->MakeDrawLayer();
663 // cell range is copied to the original position, but on the first sheet
664 // -> bCutMode must be set
665 // pDoc is always a Clipboard-document
667 ScRange aDestRange( nStartX,nStartY,0, nEndX,nEndY,0 );
668 bool bWasCut = pDoc->IsCutMode();
669 if (!bWasCut)
670 pDoc->SetClipArea( aDestRange, true ); // Cut
671 rDestDoc.CopyFromClip( aDestRange, aDestMark, InsertDeleteFlags::ALL, nullptr, pDoc, false );
672 pDoc->SetClipArea( aDestRange, bWasCut );
674 StripRefs( pDoc, nStartX,nStartY, nEndX,nEndY, &rDestDoc );
676 ScRange aMergeRange = aDestRange;
677 rDestDoc.ExtendMerge( aMergeRange, true );
679 pDoc->CopyDdeLinks( &rDestDoc ); // copy values of DDE Links
681 // page format (grid etc) and page size (maximum size for ole object)
683 Size aPaperSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); // Twips
684 ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
685 OUString aStyleName = pDoc->GetPageStyle( aBlock.aStart.Tab() );
686 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
687 if (pStyleSheet)
689 const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
690 aPaperSize = static_cast<const SvxSizeItem&>( rSourceSet.Get(ATTR_PAGE_SIZE)).GetSize();
692 // CopyStyleFrom kopiert SetItems mit richtigem Pool
693 ScStyleSheetPool* pDestPool = rDestDoc.GetStyleSheetPool();
694 pDestPool->CopyStyleFrom( pStylePool, aStyleName, SfxStyleFamily::Page );
697 ScViewData aViewData( pDocSh, nullptr );
698 aViewData.SetScreen( nStartX,nStartY, nEndX,nEndY );
699 aViewData.SetCurX( nStartX );
700 aViewData.SetCurY( nStartY );
702 rDestDoc.SetViewOptions( pDoc->GetViewOptions() );
704 // Size
705 //! get while copying sizes
707 long nPosX = 0;
708 long nPosY = 0;
710 for (nCol=0; nCol<nStartX; nCol++)
711 nPosX += rDestDoc.GetColWidth( nCol, 0 );
712 nPosY += rDestDoc.GetRowHeight( 0, nStartY-1, 0 );
713 nPosX = (long) ( nPosX * HMM_PER_TWIPS );
714 nPosY = (long) ( nPosY * HMM_PER_TWIPS );
716 aPaperSize.Width() *= 2; // limit OLE object to double of page size
717 aPaperSize.Height() *= 2;
719 long nSizeX = 0;
720 long nSizeY = 0;
721 for (nCol=nStartX; nCol<=nEndX; nCol++)
723 long nAdd = rDestDoc.GetColWidth( nCol, 0 );
724 if ( bLimitToPageSize && nSizeX+nAdd > aPaperSize.Width() && nSizeX ) // above limit?
725 break;
726 nSizeX += nAdd;
728 for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
730 long nAdd = rDestDoc.GetRowHeight( nRow, 0 );
731 if ( bLimitToPageSize && nSizeY+nAdd > aPaperSize.Height() && nSizeY ) // above limit?
732 break;
733 nSizeY += nAdd;
735 nSizeX = (long) ( nSizeX * HMM_PER_TWIPS );
736 nSizeY = (long) ( nSizeY * HMM_PER_TWIPS );
738 // pDocSh->SetVisAreaSize( Size(nSizeX,nSizeY) );
740 Rectangle aNewArea( Point(nPosX,nPosY), Size(nSizeX,nSizeY) );
741 //TODO/LATER: why twice?!
742 //pDocSh->SvInPlaceObject::SetVisArea( aNewArea );
743 pDocSh->SetVisArea( aNewArea );
745 pDocSh->UpdateOle(&aViewData, true);
747 //! SetDocumentModified?
748 if ( rDestDoc.IsChartListenerCollectionNeedsUpdate() )
749 rDestDoc.UpdateChartListenerCollection();
753 SfxObjectShell* ScTransferObj::SetDrawClipDoc( bool bAnyOle )
755 // update ScGlobal::xDrawClipDocShellRef
757 ScGlobal::xDrawClipDocShellRef.Clear();
758 if (bAnyOle)
760 ScGlobal::xDrawClipDocShellRef = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS); // there must be a ref
761 ScGlobal::xDrawClipDocShellRef->DoInitNew();
762 return ScGlobal::xDrawClipDocShellRef.get();
764 else
766 ScGlobal::xDrawClipDocShellRef.Clear();
767 return nullptr;
771 void ScTransferObj::StripRefs( ScDocument* pDoc,
772 SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
773 ScDocument* pDestDoc, SCCOL nSubX, SCROW nSubY )
775 if (!pDestDoc)
777 pDestDoc = pDoc;
778 OSL_ENSURE(nSubX==0&&nSubY==0, "can't move within the document");
781 // In a clipboard doc the data don't have to be on the first sheet
783 SCTAB nSrcTab = 0;
784 while (nSrcTab<pDoc->GetTableCount() && !pDoc->HasTable(nSrcTab))
785 ++nSrcTab;
786 SCTAB nDestTab = 0;
787 while (nDestTab<pDestDoc->GetTableCount() && !pDestDoc->HasTable(nDestTab))
788 ++nDestTab;
790 if (!pDoc->HasTable(nSrcTab) || !pDestDoc->HasTable(nDestTab))
792 OSL_FAIL("Sheet not found in ScTransferObj::StripRefs");
793 return;
796 ScRange aRef;
798 ScCellIterator aIter( pDoc, ScRange(nStartX, nStartY, nSrcTab, nEndX, nEndY, nSrcTab) );
799 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
801 if (aIter.getType() != CELLTYPE_FORMULA)
802 continue;
804 ScFormulaCell* pFCell = aIter.getFormulaCell();
805 bool bOut = false;
806 ScDetectiveRefIter aRefIter( pFCell );
807 while ( !bOut && aRefIter.GetNextRef( aRef ) )
809 if ( aRef.aStart.Tab() != nSrcTab || aRef.aEnd.Tab() != nSrcTab ||
810 aRef.aStart.Col() < nStartX || aRef.aEnd.Col() > nEndX ||
811 aRef.aStart.Row() < nStartY || aRef.aEnd.Row() > nEndY )
812 bOut = true;
814 if (bOut)
816 SCCOL nCol = aIter.GetPos().Col() - nSubX;
817 SCROW nRow = aIter.GetPos().Row() - nSubY;
819 sal_uInt16 nErrCode = pFCell->GetErrCode();
820 ScAddress aPos(nCol, nRow, nDestTab);
821 if (nErrCode)
823 if ( static_cast<const SvxHorJustifyItem*>(pDestDoc->GetAttr(
824 nCol,nRow,nDestTab, ATTR_HOR_JUSTIFY))->GetValue() ==
825 SVX_HOR_JUSTIFY_STANDARD )
826 pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
827 SvxHorJustifyItem(SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY) );
829 ScSetStringParam aParam;
830 aParam.setTextInput();
831 pDestDoc->SetString(aPos, ScGlobal::GetErrorString(nErrCode), &aParam);
833 else if (pFCell->IsValue())
835 pDestDoc->SetValue(aPos, pFCell->GetValue());
837 else
839 OUString aStr = pFCell->GetString().getString();
840 if ( pFCell->IsMultilineResult() )
842 ScFieldEditEngine& rEngine = pDestDoc->GetEditEngine();
843 rEngine.SetText(aStr);
844 pDestDoc->SetEditText(ScAddress(nCol,nRow,nDestTab), rEngine.CreateTextObject());
846 else
848 ScSetStringParam aParam;
849 aParam.setTextInput();
850 pDestDoc->SetString(aPos, aStr, &aParam);
857 namespace
859 class theScTransferUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theScTransferUnoTunnelId> {};
862 const css::uno::Sequence< sal_Int8 >& ScTransferObj::getUnoTunnelId()
864 return theScTransferUnoTunnelId::get().getSeq();
867 sal_Int64 SAL_CALL ScTransferObj::getSomething( const css::uno::Sequence< sal_Int8 >& rId ) throw( css::uno::RuntimeException, std::exception )
869 sal_Int64 nRet;
870 if( ( rId.getLength() == 16 ) &&
871 ( 0 == memcmp( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
873 nRet = reinterpret_cast< sal_Int64 >( this );
875 else
876 nRet = TransferableHelper::getSomething(rId);
877 return nRet;
880 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */