blob: 8ea28a2580d26af523979f53273e0841fe11bc24 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
// INCLUDE ---------------------------------------------------------------
#include "scitems.hxx"
#include <editeng/eeitem.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <unotools/tempfile.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <comphelper/storagehelper.hxx>
#include <sot/storage.hxx>
#include <vcl/svapp.hxx>
#include <vcl/virdev.hxx>
#include <vos/mutex.hxx>
#include <sfx2/app.hxx>
#include <sfx2/docfile.hxx>
#include "transobj.hxx"
#include "document.hxx"
#include "viewopti.hxx"
#include "editutil.hxx"
#include "impex.hxx"
#include "cell.hxx"
#include "printfun.hxx"
#include "docfunc.hxx"
#include "scmod.hxx"
// for InitDocShell
#include <editeng/paperinf.hxx>
#include <editeng/sizeitem.hxx>
#include <svx/algitem.hxx>
#include <svl/intitem.hxx>
#include <svl/zforlist.hxx>
#include "docsh.hxx"
#include "markdata.hxx"
#include "stlpool.hxx"
#include "viewdata.hxx"
#include "dociter.hxx"
#include "cellsuno.hxx"
using namespace com::sun::star;
// -----------------------------------------------------------------------
#define SCTRANS_TYPE_IMPEX 1
#define SCTRANS_TYPE_EDIT_RTF 2
#define SCTRANS_TYPE_EDIT_BIN 3
#define SCTRANS_TYPE_EMBOBJ 4
// -----------------------------------------------------------------------
// static
void ScTransferObj::GetAreaSize( ScDocument* pDoc, SCTAB nTab1, SCTAB nTab2, SCROW& nRow, SCCOL& nCol )
{
SCCOL nMaxCol = 0;
SCROW nMaxRow = 0;
for( SCTAB nTab = nTab1; nTab <= nTab2; nTab++ )
{
SCCOL nLastCol = 0;
SCROW nLastRow = 0;
// GetPrintArea instead of GetCellArea - include drawing objects
if( pDoc->GetPrintArea( nTab, nLastCol, nLastRow ) )
{
if( nLastCol > nMaxCol )
nMaxCol = nLastCol;
if( nLastRow > nMaxRow )
nMaxRow = nLastRow;
}
}
nRow = nMaxRow;
nCol = nMaxCol;
}
// static
void ScTransferObj::PaintToDev( OutputDevice* pDev, ScDocument* pDoc, double nPrintFactor,
const ScRange& rBlock, sal_Bool bMetaFile )
{
if (!pDoc)
return;
Point aPoint;
Rectangle aBound( aPoint, pDev->GetOutputSize() ); //! use size from clip area?
ScViewData aViewData(NULL,NULL);
aViewData.InitData( pDoc );
aViewData.SetTabNo( rBlock.aEnd.Tab() );
aViewData.SetScreen( rBlock.aStart.Col(), rBlock.aStart.Row(),
rBlock.aEnd.Col(), rBlock.aEnd.Row() );
ScPrintFunc::DrawToDev( pDoc, pDev, nPrintFactor, aBound, &aViewData, bMetaFile );
}
// -----------------------------------------------------------------------
ScTransferObj::ScTransferObj( ScDocument* pClipDoc, const TransferableObjectDescriptor& rDesc ) :
pDoc( pClipDoc ),
aObjDesc( rDesc ),
nDragHandleX( 0 ),
nDragHandleY( 0 ),
nDragSourceFlags( 0 ),
bDragWasInternal( sal_False ),
bUsedForLink( sal_False ),
bUseInApi( false )
{
DBG_ASSERT(pDoc->IsClipboard(), "wrong document");
//
// get aBlock from clipboard doc
//
SCCOL nCol1;
SCROW nRow1;
SCCOL nCol2;
SCROW nRow2;
pDoc->GetClipStart( nCol1, nRow1 );
pDoc->GetClipArea( nCol2, nRow2, sal_True ); // real source area - include filtered rows
nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nCol1 );
nRow2 = sal::static_int_cast<SCROW>( nRow2 + nRow1 );
SCCOL nDummy;
pDoc->GetClipArea( nDummy, nNonFiltered, sal_False );
bHasFiltered = (nNonFiltered < (nRow2 - nRow1));
++nNonFiltered; // to get count instead of diff
SCTAB nTab1=0;
SCTAB nTab2=0;
sal_Bool bFirst = sal_True;
for (SCTAB i=0; i<=MAXTAB; i++)
if (pDoc->HasTable(i))
{
if (bFirst)
nTab1 = i;
nTab2 = i;
bFirst = sal_False;
}
DBG_ASSERT(!bFirst, "no sheet selected");
// only limit to used cells if whole sheet was marked
// (so empty cell areas can be copied)
if ( nCol2>=MAXCOL && nRow2>=MAXROW )
{
SCROW nMaxRow;
SCCOL nMaxCol;
GetAreaSize( pDoc, nTab1, nTab2, nMaxRow, nMaxCol );
if( nMaxRow < nRow2 )
nRow2 = nMaxRow;
if( nMaxCol < nCol2 )
nCol2 = nMaxCol;
}
aBlock = ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
nVisibleTab = nTab1; // valid table as default
Rectangle aMMRect = pDoc->GetMMRect( nCol1,nRow1, nCol2,nRow2, nTab1 );
aObjDesc.maSize = aMMRect.GetSize();
PrepareOLE( aObjDesc );
}
ScTransferObj::~ScTransferObj()
{
Application::GetSolarMutex().acquire();
ScModule* pScMod = SC_MOD();
if ( pScMod->GetClipData().pCellClipboard == this )
{
DBG_ERROR("ScTransferObj wasn't released");
pScMod->SetClipObject( NULL, NULL );
}
if ( pScMod->GetDragData().pCellTransfer == this )
{
DBG_ERROR("ScTransferObj wasn't released");
pScMod->ResetDragObject();
}
delete pDoc; // ScTransferObj is owner of clipboard document
aDocShellRef.Clear(); // before releasing the mutex
aDrawPersistRef.Clear(); // after the model
Application::GetSolarMutex().release();
}
// static
ScTransferObj* ScTransferObj::GetOwnClipboard( Window* pUIWin )
{
ScTransferObj* pObj = SC_MOD()->GetClipData().pCellClipboard;
if ( pObj && pUIWin )
{
// check formats to see if pObj is really in the system clipboard
// pUIWin is NULL when called from core (IsClipboardSource),
// in that case don't access the system clipboard, because the call
// may be from other clipboard operations (like flushing, #86059#)
TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pUIWin ) );
if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_DIF ) )
{
// DBG_ERROR("ScTransferObj wasn't released");
pObj = NULL;
}
}
return pObj;
}
void ScTransferObj::AddSupportedFormats()
{
AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
AddFormat( SOT_FORMAT_GDIMETAFILE );
AddFormat( SOT_FORMATSTR_ID_PNG );
AddFormat( SOT_FORMAT_BITMAP );
// ScImportExport formats
AddFormat( SOT_FORMATSTR_ID_HTML );
AddFormat( SOT_FORMATSTR_ID_SYLK );
AddFormat( SOT_FORMATSTR_ID_LINK );
AddFormat( SOT_FORMATSTR_ID_DIF );
AddFormat( SOT_FORMAT_STRING );
AddFormat( SOT_FORMAT_RTF );
if ( aBlock.aStart == aBlock.aEnd )
AddFormat( SOT_FORMATSTR_ID_EDITENGINE );
}
sal_Bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor )
{
sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
sal_Bool bOK = sal_False;
if( HasFormat( nFormat ) )
{
if ( nFormat == SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR || nFormat == SOT_FORMATSTR_ID_OBJECTDESCRIPTOR )
{
bOK = SetTransferableObjectDescriptor( aObjDesc, rFlavor );
}
else if ( ( nFormat == SOT_FORMAT_RTF || nFormat == SOT_FORMATSTR_ID_EDITENGINE ) &&
aBlock.aStart == aBlock.aEnd )
{
// RTF from a single cell is handled by EditEngine
SCCOL nCol = aBlock.aStart.Col();
SCROW nRow = aBlock.aStart.Row();
SCTAB nTab = aBlock.aStart.Tab();
const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
ScTabEditEngine aEngine( *pPattern, pDoc->GetEditPool() );
ScBaseCell* pCell = NULL;
pDoc->GetCell( nCol, nRow, nTab, pCell );
if (pCell)
{
if (pCell->GetCellType() == CELLTYPE_EDIT)
{
const EditTextObject* pObj;
((ScEditCell*)pCell)->GetData(pObj);
aEngine.SetText( *pObj );
}
else
{
String aText;
pDoc->GetString( nCol, nRow, nTab, aText );
aEngine.SetText(aText);
}
}
bOK = SetObject( &aEngine,
(nFormat == FORMAT_RTF) ? SCTRANS_TYPE_EDIT_RTF : SCTRANS_TYPE_EDIT_BIN,
rFlavor );
}
else if ( ScImportExport::IsFormatSupported( nFormat ) || nFormat == SOT_FORMAT_RTF )
{
// if this transfer object was used to create a DDE link, filtered rows
// have to be included for subsequent calls (to be consistent with link data)
if ( nFormat == SOT_FORMATSTR_ID_LINK )
bUsedForLink = sal_True;
sal_Bool bIncludeFiltered = pDoc->IsCutMode() || bUsedForLink;
ScImportExport aObj( pDoc, aBlock );
if ( bUsedForLink )
aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) );
aObj.SetFormulas( pDoc->GetViewOptions().GetOption( VOPT_FORMULAS ) );
aObj.SetIncludeFiltered( bIncludeFiltered );
// DataType depends on format type:
if ( rFlavor.DataType.equals( ::getCppuType( (const ::rtl::OUString*) 0 ) ) )
{
rtl::OUString aString;
if ( aObj.ExportString( aString, nFormat ) )
bOK = SetString( aString, rFlavor );
}
else if ( rFlavor.DataType.equals( ::getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ) )
{
// SetObject converts a stream into a Int8-Sequence
bOK = SetObject( &aObj, SCTRANS_TYPE_IMPEX, rFlavor );
}
else
{
DBG_ERROR("unknown DataType");
}
}
else if ( nFormat == SOT_FORMAT_BITMAP || nFormat == SOT_FORMATSTR_ID_PNG )
{
Rectangle aMMRect = pDoc->GetMMRect( aBlock.aStart.Col(), aBlock.aStart.Row(),
aBlock.aEnd.Col(), aBlock.aEnd.Row(),
aBlock.aStart.Tab() );
VirtualDevice aVirtDev;
aVirtDev.SetOutputSizePixel( aVirtDev.LogicToPixel( aMMRect.GetSize(), MAP_100TH_MM ) );
PaintToDev( &aVirtDev, pDoc, 1.0, aBlock, sal_False );
aVirtDev.SetMapMode( MapMode( MAP_PIXEL ) );
Bitmap aBmp = aVirtDev.GetBitmap( Point(), aVirtDev.GetOutputSize() );
bOK = SetBitmapEx( aBmp, rFlavor );
}
else if ( nFormat == SOT_FORMAT_GDIMETAFILE )
{
// #123405# Do not limit visual size calculation for metafile creation.
// It seems unlikely that removing the limitation causes problems since
// metafile creation means that no real pixel device in the needed size is
// created.
InitDocShell(false);
SfxObjectShell* pEmbObj = aDocShellRef;
// like SvEmbeddedTransfer::GetData:
GDIMetaFile aMtf;
VirtualDevice aVDev;
MapMode aMapMode( pEmbObj->GetMapUnit() );
Rectangle aVisArea( pEmbObj->GetVisArea( ASPECT_CONTENT ) );
aVDev.EnableOutput( sal_False );
aVDev.SetMapMode( aMapMode );
aMtf.SetPrefSize( aVisArea.GetSize() );
aMtf.SetPrefMapMode( aMapMode );
aMtf.Record( &aVDev );
pEmbObj->DoDraw( &aVDev, Point(), aVisArea.GetSize(), JobSetup(), ASPECT_CONTENT );
aMtf.Stop();
aMtf.WindStart();
bOK = SetGDIMetaFile( aMtf, rFlavor );
}
else if ( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE )
{
//TODO/LATER: differentiate between formats?!
// #123405# Do limit visual size calculation to PageSize
InitDocShell(true); // set aDocShellRef
SfxObjectShell* pEmbObj = aDocShellRef;
bOK = SetObject( pEmbObj, SCTRANS_TYPE_EMBOBJ, rFlavor );
}
}
return bOK;
}
sal_Bool ScTransferObj::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId,
const datatransfer::DataFlavor& rFlavor )
{
// called from SetObject, put data into stream
sal_Bool bRet = sal_False;
switch (nUserObjectId)
{
case SCTRANS_TYPE_IMPEX:
{
ScImportExport* pImpEx = (ScImportExport*)pUserObject;
sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
// mba: no BaseURL for data exchange
if ( pImpEx->ExportStream( *rxOStm, String(), nFormat ) )
bRet = ( rxOStm->GetError() == ERRCODE_NONE );
}
break;
case SCTRANS_TYPE_EDIT_RTF:
case SCTRANS_TYPE_EDIT_BIN:
{
ScTabEditEngine* pEngine = (ScTabEditEngine*)pUserObject;
if ( nUserObjectId == SCTRANS_TYPE_EDIT_RTF )
{
pEngine->Write( *rxOStm, EE_FORMAT_RTF );
bRet = ( rxOStm->GetError() == ERRCODE_NONE );
}
else
{
// #107722# can't use Write for EditEngine format because that would
// write old format without support for unicode characters.
// Get the data from the EditEngine's transferable instead.
sal_uInt16 nParCnt = pEngine->GetParagraphCount();
if ( nParCnt == 0 )
nParCnt = 1;
ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) );
uno::Reference<datatransfer::XTransferable> xEditTrans = pEngine->CreateTransferable( aSel );
TransferableDataHelper aEditHelper( xEditTrans );
bRet = aEditHelper.GetSotStorageStream( rFlavor, rxOStm );
}
}
break;
case SCTRANS_TYPE_EMBOBJ:
{
// TODO/MBA: testing
SfxObjectShell* pEmbObj = (SfxObjectShell*) pUserObject;
::utl::TempFile aTempFile;
aTempFile.EnableKillingFile();
uno::Reference< embed::XStorage > xWorkStore =
::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
// write document storage
pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, sal_False );
// mba: no relative ULRs for clipboard!
SfxMedium aMedium( xWorkStore, String() );
bRet = pEmbObj->DoSaveObjectAs( aMedium, sal_False );
pEmbObj->DoSaveCompleted();
uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
if ( xTransact.is() )
xTransact->commit();
SvStream* pSrcStm = ::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), STREAM_READ );
if( pSrcStm )
{
rxOStm->SetBufferSize( 0xff00 );
*rxOStm << *pSrcStm;
delete pSrcStm;
}
bRet = sal_True;
xWorkStore->dispose();
xWorkStore = uno::Reference < embed::XStorage >();
rxOStm->Commit();
}
break;
default:
DBG_ERROR("unknown object id");
}
return bRet;
}
void ScTransferObj::ObjectReleased()
{
ScModule* pScMod = SC_MOD();
if ( pScMod->GetClipData().pCellClipboard == this )
pScMod->SetClipObject( NULL, NULL );
TransferableHelper::ObjectReleased();
}
void ScTransferObj::DragFinished( sal_Int8 nDropAction )
{
if ( nDropAction == DND_ACTION_MOVE && !bDragWasInternal && !(nDragSourceFlags & SC_DROP_NAVIGATOR) )
{
// move: delete source data
ScDocShell* pSourceSh = GetSourceDocShell();
if (pSourceSh)
{
ScMarkData aMarkData = GetSourceMarkData();
// external drag&drop doesn't copy objects, so they also aren't deleted:
// #105703# bApi=sal_True, don't show error messages from drag&drop
pSourceSh->GetDocFunc().DeleteContents( aMarkData, IDF_ALL & ~IDF_OBJECTS, sal_True, sal_True );
}
}
ScModule* pScMod = SC_MOD();
if ( pScMod->GetDragData().pCellTransfer == this )
pScMod->ResetDragObject();
xDragSourceRanges = NULL; // don't keep source after dropping
TransferableHelper::DragFinished( nDropAction );
}
void ScTransferObj::SetDragHandlePos( SCCOL nX, SCROW nY )
{
nDragHandleX = nX;
nDragHandleY = nY;
}
void ScTransferObj::SetVisibleTab( SCTAB nNew )
{
nVisibleTab = nNew;
}
void ScTransferObj::SetDrawPersist( const SfxObjectShellRef& rRef )
{
aDrawPersistRef = rRef;
}
void ScTransferObj::SetDragSource( ScDocShell* pSourceShell, const ScMarkData& rMark )
{
ScRangeList aRanges;
rMark.FillRangeListWithMarks( &aRanges, sal_False );
xDragSourceRanges = new ScCellRangesObj( pSourceShell, aRanges );
}
void ScTransferObj::SetDragSourceFlags( sal_uInt16 nFlags )
{
nDragSourceFlags = nFlags;
}
void ScTransferObj::SetDragWasInternal()
{
bDragWasInternal = sal_True;
}
void ScTransferObj::SetUseInApi( bool bSet )
{
bUseInApi = bSet;
}
ScDocument* ScTransferObj::GetSourceDocument()
{
ScDocShell* pSourceDocSh = GetSourceDocShell();
if (pSourceDocSh)
return pSourceDocSh->GetDocument();
return NULL;
}
ScDocShell* ScTransferObj::GetSourceDocShell()
{
ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
if (pRangesObj)
return pRangesObj->GetDocShell();
return NULL; // none set
}
ScMarkData ScTransferObj::GetSourceMarkData()
{
ScMarkData aMarkData;
ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
if (pRangesObj)
{
const ScRangeList& rRanges = pRangesObj->GetRangeList();
aMarkData.MarkFromRangeList( rRanges, sal_False );
}
return aMarkData;
}
//
// initialize aDocShellRef with a live document from the ClipDoc
//
// #123405# added parameter to allow size calculation without limitation
// to PageSize, e.g. used for Metafile creation for clipboard.
void ScTransferObj::InitDocShell(bool bLimitToPageSize)
{
if ( !aDocShellRef.Is() )
{
ScDocShell* pDocSh = new ScDocShell;
aDocShellRef = pDocSh; // ref must be there before InitNew
pDocSh->DoInitNew(NULL);
ScDocument* pDestDoc = pDocSh->GetDocument();
ScMarkData aDestMark;
aDestMark.SelectTable( 0, sal_True );
pDestDoc->SetDocOptions( pDoc->GetDocOptions() ); // #i42666#
String aTabName;
pDoc->GetName( aBlock.aStart.Tab(), aTabName );
pDestDoc->RenameTab( 0, aTabName, sal_False ); // no UpdateRef (empty)
pDestDoc->CopyStdStylesFrom( pDoc );
SCCOL nStartX = aBlock.aStart.Col();
SCROW nStartY = aBlock.aStart.Row();
SCCOL nEndX = aBlock.aEnd.Col();
SCROW nEndY = aBlock.aEnd.Row();
// widths / heights
// (must be copied before CopyFromClip, for drawing objects)
SCCOL nCol, nLastCol;
SCTAB nSrcTab = aBlock.aStart.Tab();
pDestDoc->SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab));
for (nCol=nStartX; nCol<=nEndX; nCol++)
if ( pDoc->ColHidden(nCol, nSrcTab, nLastCol) )
pDestDoc->ShowCol( nCol, 0, sal_False );
else
pDestDoc->SetColWidth( nCol, 0, pDoc->GetColWidth( nCol, nSrcTab ) );
ScBitMaskCompressedArray< SCROW, sal_uInt8> & rDestRowFlags =
pDestDoc->GetRowFlagsArrayModifiable(0);
for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow)
{
sal_uInt8 nSourceFlags = pDoc->GetRowFlags(nRow, nSrcTab);
SCROW nLastRow = -1;
if ( pDoc->RowHidden(nRow, nSrcTab, nLastRow) )
pDestDoc->ShowRow( nRow, 0, sal_False );
else
{
pDestDoc->SetRowHeight( nRow, 0, pDoc->GetOriginalHeight( nRow, nSrcTab ) );
// if height was set manually, that flag has to be copied, too
if ( nSourceFlags & CR_MANUALSIZE )
rDestRowFlags.OrValue( nRow, CR_MANUALSIZE);
}
}
if ( pDoc->GetDrawLayer() )
pDocSh->MakeDrawLayer();
// cell range is copied to the original position, but on the first sheet
// -> bCutMode must be set
// pDoc is always a Clipboard-document
ScRange aDestRange( nStartX,nStartY,0, nEndX,nEndY,0 );
sal_Bool bWasCut = pDoc->IsCutMode();
if (!bWasCut)
pDoc->SetClipArea( aDestRange, sal_True ); // Cut
pDestDoc->CopyFromClip( aDestRange, aDestMark, IDF_ALL, NULL, pDoc, sal_False );
pDoc->SetClipArea( aDestRange, bWasCut );
StripRefs( pDoc, nStartX,nStartY, nEndX,nEndY, pDestDoc, 0,0 );
ScRange aMergeRange = aDestRange;
pDestDoc->ExtendMerge( aMergeRange, sal_True );
pDoc->CopyDdeLinks( pDestDoc ); // copy values of DDE Links
// page format (grid etc) and page size (maximum size for ole object)
Size aPaperSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); // Twips
ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
String aStyleName = pDoc->GetPageStyle( aBlock.aStart.Tab() );
SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
if (pStyleSheet)
{
const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
aPaperSize = ((const SvxSizeItem&) rSourceSet.Get(ATTR_PAGE_SIZE)).GetSize();
// CopyStyleFrom kopiert SetItems mit richtigem Pool
ScStyleSheetPool* pDestPool = pDestDoc->GetStyleSheetPool();
pDestPool->CopyStyleFrom( pStylePool, aStyleName, SFX_STYLE_FAMILY_PAGE );
}
ScViewData aViewData( pDocSh, NULL );
aViewData.SetScreen( nStartX,nStartY, nEndX,nEndY );
aViewData.SetCurX( nStartX );
aViewData.SetCurY( nStartY );
pDestDoc->SetViewOptions( pDoc->GetViewOptions() );
// Size
//! get while copying sizes
long nPosX = 0;
long nPosY = 0;
for (nCol=0; nCol<nStartX; nCol++)
nPosX += pDestDoc->GetColWidth( nCol, 0 );
nPosY += pDestDoc->GetRowHeight( 0, nStartY-1, 0 );
nPosX = (long) ( nPosX * HMM_PER_TWIPS );
nPosY = (long) ( nPosY * HMM_PER_TWIPS );
aPaperSize.Width() *= 2; // limit OLE object to double of page size
aPaperSize.Height() *= 2;
long nSizeX = 0;
long nSizeY = 0;
for (nCol=nStartX; nCol<=nEndX; nCol++)
{
long nAdd = pDestDoc->GetColWidth( nCol, 0 );
if ( bLimitToPageSize && nSizeX+nAdd > aPaperSize.Width() && nSizeX ) // above limit?
break;
nSizeX += nAdd;
}
for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
{
long nAdd = pDestDoc->GetRowHeight( nRow, 0 );
if ( bLimitToPageSize && nSizeY+nAdd > aPaperSize.Height() && nSizeY ) // above limit?
break;
nSizeY += nAdd;
}
nSizeX = (long) ( nSizeX * HMM_PER_TWIPS );
nSizeY = (long) ( nSizeY * HMM_PER_TWIPS );
// pDocSh->SetVisAreaSize( Size(nSizeX,nSizeY) );
Rectangle aNewArea( Point(nPosX,nPosY), Size(nSizeX,nSizeY) );
//TODO/LATER: why twice?!
//pDocSh->SvInPlaceObject::SetVisArea( aNewArea );
pDocSh->SetVisArea( aNewArea );
pDocSh->UpdateOle(&aViewData, sal_True);
//! SetDocumentModified?
if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() )
pDestDoc->UpdateChartListenerCollection();
}
}
// static
SfxObjectShell* ScTransferObj::SetDrawClipDoc( sal_Bool bAnyOle )
{
// update ScGlobal::pDrawClipDocShellRef
delete ScGlobal::pDrawClipDocShellRef;
if (bAnyOle)
{
ScGlobal::pDrawClipDocShellRef =
new ScDocShellRef(new ScDocShell(SFX_CREATE_MODE_INTERNAL)); // there must be a ref
(*ScGlobal::pDrawClipDocShellRef)->DoInitNew(NULL);
return *ScGlobal::pDrawClipDocShellRef;
}
else
{
ScGlobal::pDrawClipDocShellRef = NULL;
return NULL;
}
}
// static
void ScTransferObj::StripRefs( ScDocument* pDoc,
SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
ScDocument* pDestDoc, SCCOL nSubX, SCROW nSubY )
{
if (!pDestDoc)
{
pDestDoc = pDoc;
DBG_ASSERT(nSubX==0&&nSubY==0, "can't move within the document");
}
// In a clipboard doc the data don't have to be on the first sheet
SCTAB nSrcTab = 0;
while (nSrcTab<MAXTAB && !pDoc->HasTable(nSrcTab))
++nSrcTab;
SCTAB nDestTab = 0;
while (nDestTab<MAXTAB && !pDestDoc->HasTable(nDestTab))
++nDestTab;
if (!pDoc->HasTable(nSrcTab) || !pDestDoc->HasTable(nDestTab))
{
DBG_ERROR("Sheet not found in ScTransferObj::StripRefs");
return;
}
SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
ScRange aRef;
ScCellIterator aIter( pDoc, nStartX, nStartY, nSrcTab, nEndX, nEndY, nSrcTab );
ScBaseCell* pCell = aIter.GetFirst();
while (pCell)
{
if (pCell->GetCellType() == CELLTYPE_FORMULA)
{
ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
sal_Bool bOut = sal_False;
ScDetectiveRefIter aRefIter( pFCell );
while ( !bOut && aRefIter.GetNextRef( aRef ) )
{
if ( aRef.aStart.Tab() != nSrcTab || aRef.aEnd.Tab() != nSrcTab ||
aRef.aStart.Col() < nStartX || aRef.aEnd.Col() > nEndX ||
aRef.aStart.Row() < nStartY || aRef.aEnd.Row() > nEndY )
bOut = sal_True;
}
if (bOut)
{
SCCOL nCol = aIter.GetCol() - nSubX;
SCROW nRow = aIter.GetRow() - nSubY;
ScBaseCell* pNew = 0;
sal_uInt16 nErrCode = pFCell->GetErrCode();
if (nErrCode)
{
pNew = new ScStringCell( ScGlobal::GetErrorString(nErrCode) );
if ( ((const SvxHorJustifyItem*) pDestDoc->GetAttr(
nCol,nRow,nDestTab, ATTR_HOR_JUSTIFY))->GetValue() ==
SVX_HOR_JUSTIFY_STANDARD )
pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
SvxHorJustifyItem(SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY) );
}
else if (pFCell->IsValue())
{
double fVal = pFCell->GetValue();
pNew = new ScValueCell( fVal );
}
else
{
String aStr;
pFCell->GetString(aStr);
if ( pFCell->IsMultilineResult() )
pNew = new ScEditCell( aStr, pDestDoc );
else
pNew = new ScStringCell( aStr );
}
pDestDoc->PutCell( nCol,nRow,nDestTab, pNew );
// number formats
sal_uLong nOldFormat = ((const SfxUInt32Item*)
pDestDoc->GetAttr(nCol,nRow,nDestTab, ATTR_VALUE_FORMAT))->GetValue();
if ( (nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
{
sal_uLong nNewFormat = pFCell->GetStandardFormat( *pFormatter,
nOldFormat );
pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
SfxUInt32Item(ATTR_VALUE_FORMAT, nNewFormat) );
}
}
}
pCell = aIter.GetNext();
}
}
const com::sun::star::uno::Sequence< sal_Int8 >& ScTransferObj::getUnoTunnelId()
{
static com::sun::star::uno::Sequence< sal_Int8 > aSeq;
if( !aSeq.getLength() )
{
static osl::Mutex aCreateMutex;
osl::Guard< osl::Mutex > aGuard( aCreateMutex );
aSeq.realloc( 16 );
rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
}
return aSeq;
}
sal_Int64 SAL_CALL ScTransferObj::getSomething( const com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( com::sun::star::uno::RuntimeException )
{
sal_Int64 nRet;
if( ( rId.getLength() == 16 ) &&
( 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
{
nRet = reinterpret_cast< sal_Int64 >( this );
}
else
nRet = TransferableHelper::getSomething(rId);
return nRet;
}